core_crypto/e2e_identity/
refresh_token.rs

1use super::{
2    E2eiEnrollment,
3    error::{Error, Result},
4};
5use core_crypto_keystore::connection::FetchFromDatabase;
6use core_crypto_keystore::{CryptoKeystoreResult, entities::E2eiRefreshToken};
7use mls_crypto_provider::MlsCryptoProvider;
8use zeroize::Zeroize;
9
10/// An OIDC refresh token managed by CoreCrypto to benefit from encryption-at-rest
11#[derive(Debug, serde::Serialize, serde::Deserialize, Zeroize, derive_more::From, derive_more::Deref)]
12#[zeroize(drop)]
13pub struct RefreshToken(String);
14
15impl RefreshToken {
16    pub(crate) async fn find(key_store: &impl FetchFromDatabase) -> Result<RefreshToken> {
17        key_store.find_unique::<E2eiRefreshToken>().await?.try_into()
18    }
19
20    pub(crate) async fn replace(self, backend: &MlsCryptoProvider) -> CryptoKeystoreResult<()> {
21        let keystore = backend.keystore();
22        let rt = E2eiRefreshToken::from(self);
23        keystore.save(rt).await?;
24        Ok(())
25    }
26}
27
28impl E2eiEnrollment {
29    /// Lets clients retrieve the OIDC refresh token to try to renew the user's authorization.
30    /// If it's expired, the user needs to reauthenticate and they will update the refresh token
31    /// in [E2eiEnrollment::new_oidc_challenge_request]
32    pub fn get_refresh_token(&self) -> Result<&str> {
33        self.refresh_token
34            .as_ref()
35            .map(|rt| rt.as_str())
36            .ok_or(Error::OutOfOrderEnrollment(
37                "No OIDC refresh token registered yet or it has been persisted",
38            ))
39    }
40}
41
42impl TryFrom<E2eiRefreshToken> for RefreshToken {
43    type Error = Error;
44
45    fn try_from(mut entity: E2eiRefreshToken) -> Result<Self> {
46        let content = std::mem::take(&mut entity.content);
47        let content = String::from_utf8(content).map_err(|_| Error::InvalidRefreshToken)?;
48        Ok(Self(content))
49    }
50}
51
52impl From<RefreshToken> for E2eiRefreshToken {
53    fn from(mut rt: RefreshToken) -> Self {
54        let content = std::mem::take(&mut rt.0);
55        Self {
56            content: content.into_bytes(),
57        }
58    }
59}