core_crypto/e2e_identity/
refresh_token.rs

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