From dcfd1a17b6d86e3e4d1ef5e278bd3fa0f202685c Mon Sep 17 00:00:00 2001 From: avdb13 Date: Sun, 24 Nov 2024 06:42:25 +0000 Subject: [PATCH] use SessionStore in OAuthSession --- atrium-common/src/store/memory.rs | 4 +- .../oauth-client/src/http_client/dpop.rs | 2 + .../oauth-client/src/oauth_session.rs | 48 +++++++++++++------ atrium-oauth/oauth-client/src/server_agent.rs | 36 ++++---------- .../oauth-client/src/store/session.rs | 18 +++++-- 5 files changed, 61 insertions(+), 47 deletions(-) diff --git a/atrium-common/src/store/memory.rs b/atrium-common/src/store/memory.rs index b792bf4d..2500959e 100644 --- a/atrium-common/src/store/memory.rs +++ b/atrium-common/src/store/memory.rs @@ -23,8 +23,8 @@ impl Default for MemoryStore { impl Store for MemoryStore where - K: Debug + Eq + Hash + Send + Sync + 'static, - V: Debug + Clone + Send + Sync + 'static, + K: Eq + Hash + Send + Sync, + V: Clone + Send, { type Error = Error; diff --git a/atrium-oauth/oauth-client/src/http_client/dpop.rs b/atrium-oauth/oauth-client/src/http_client/dpop.rs index 2ba8f287..a45fb76c 100644 --- a/atrium-oauth/oauth-client/src/http_client/dpop.rs +++ b/atrium-oauth/oauth-client/src/http_client/dpop.rs @@ -32,6 +32,8 @@ pub enum Error { UnsupportedKey, #[error("nonce store error: {0}")] Nonces(Box), + #[error("session store error: {0}")] + SessionStore(Box), #[error(transparent)] SerdeJson(#[from] serde_json::Error), } diff --git a/atrium-oauth/oauth-client/src/oauth_session.rs b/atrium-oauth/oauth-client/src/oauth_session.rs index 8db608e1..b9c1faf5 100644 --- a/atrium-oauth/oauth-client/src/oauth_session.rs +++ b/atrium-oauth/oauth-client/src/oauth_session.rs @@ -9,24 +9,35 @@ use atrium_xrpc::{ }; use jose_jwk::Key; -use crate::{http_client::dpop::Error, server_agent::OAuthServerAgent, DpopClient, TokenSet}; +use crate::{ + http_client::dpop::Error, + server_agent::OAuthServerAgent, + store::session::{MemorySessionStore, SessionStore}, + DpopClient, TokenSet, +}; -pub struct OAuthSession> -where +pub struct OAuthSession< + T, + D, + H, + S0 = MemoryStore, + S1 = MemorySessionStore<(), TokenSet>, +> where T: HttpClient + Send + Sync + 'static, - S: Store, + S0: Store, + S1: SessionStore<(), TokenSet>, { #[allow(dead_code)] server_agent: OAuthServerAgent, - dpop_client: DpopClient, - token_set: TokenSet, + dpop_client: DpopClient, + session_store: S1, } impl OAuthSession where T: HttpClient + Send + Sync + 'static, { - pub(crate) fn new( + pub(crate) async fn new( server_agent: OAuthServerAgent, dpop_key: Key, http_client: Arc, @@ -38,13 +49,19 @@ where false, &server_agent.server_metadata.token_endpoint_auth_signing_alg_values_supported, )?; - Ok(Self { server_agent, dpop_client, token_set }) + + let session_store = MemorySessionStore::default(); + session_store.set((), token_set).await.map_err(|e| Error::SessionStore(Box::new(e)))?; + + Ok(Self { server_agent, dpop_client, session_store }) } pub fn dpop_key(&self) -> Key { self.dpop_client.key.clone() } - pub fn token_set(&self) -> TokenSet { - self.token_set.clone() + pub async fn token_set(&self) -> Result { + let token_set = + self.session_store.get(&()).await.map_err(|e| Error::SessionStore(Box::new(e)))?; + Ok(token_set.expect("session store can never be empty")) } // pub async fn get_session(&self, refresh: bool) -> crate::Result { // let Some(session) = self @@ -97,13 +114,15 @@ where S::Error: std::error::Error + Send + Sync + 'static, { fn base_uri(&self) -> String { - self.token_set.aud.clone() + // self.token_set.aud.clone() + todo!() } async fn authorization_token(&self, is_refresh: bool) -> Option { + let token_set = self.session_store.get(&()).await.transpose().and_then(Result::ok)?; if is_refresh { - self.token_set.refresh_token.as_ref().cloned().map(AuthorizationToken::Dpop) + token_set.refresh_token.as_ref().cloned().map(AuthorizationToken::Dpop) } else { - Some(AuthorizationToken::Dpop(self.token_set.access_token.clone())) + Some(AuthorizationToken::Dpop(token_set.access_token.clone())) } } } @@ -117,6 +136,7 @@ where S::Error: std::error::Error + Send + Sync + 'static, { async fn did(&self) -> Option { - Some(self.token_set.sub.clone()) + let token_set = self.session_store.get(&()).await.transpose().and_then(Result::ok)?; + Some(token_set.sub.clone()) } } diff --git a/atrium-oauth/oauth-client/src/server_agent.rs b/atrium-oauth/oauth-client/src/server_agent.rs index 4c5e15f7..866adc0a 100644 --- a/atrium-oauth/oauth-client/src/server_agent.rs +++ b/atrium-oauth/oauth-client/src/server_agent.rs @@ -193,39 +193,19 @@ where .await; } #[allow(dead_code)] - pub async fn refresh(&self, token_set: &TokenSet) { + pub async fn refresh(&self, token_set: &TokenSet) -> Result { let Some(refresh_token) = token_set.refresh_token.as_ref() else { - // TODO - return; + return Err(Error::NoRefreshToken(token_set.sub.to_string())); }; - // TODO - let result = self - .request::(OAuthRequest::Refresh(RefreshRequestParameters { + self.verify_token_response( + self.request::(OAuthRequest::Refresh(RefreshRequestParameters { grant_type: TokenGrantType::RefreshToken, refresh_token: refresh_token.clone(), scope: None, })) - .await; - println!("{result:?}"); - - // let Some(refresh_token) = token_set.refresh_token else { - // return Err(Error::NoRefreshToken(token_set.sub.clone())); - // }; - // let (metadata, atrium_identity::identity_resolver::ResolvedIdentity { pds: aud, .. }) = - // self.resolver.resolve_from_identity(&token_set.sub).await?; - // if metadata.issuer != self.server_metadata.issuer { - // let _ = self.revoke(&token_set.access_token).await; - // return Err(Error::Token("issuer mismatch".into())); - // } - // let token_set = self - // .verify_token_response( - // self.request(OAuthRequest::Token(TokenRequestParameters::RefreshToken( - // RefreshTokenParameters { refresh_token, scope: token_set.scope.clone() }, - // ))) - // .await?, - // ) - // .await?; - // Ok(TokenSet { aud, ..token_set }) + .await?, + ) + .await } pub async fn request(&self, request: OAuthRequest) -> Result where @@ -345,6 +325,6 @@ where let dpop_key = self.dpop_client.key.clone(); // TODO let session = session_getter.get(&sub).await.expect("").unwrap(); - Ok(OAuthSession::new(self, dpop_key, http_client, session.token_set)?) + OAuthSession::new(self, dpop_key, http_client, session.token_set).await.map_err(Into::into) } } diff --git a/atrium-oauth/oauth-client/src/store/session.rs b/atrium-oauth/oauth-client/src/store/session.rs index 0dd73f92..9e0da984 100644 --- a/atrium-oauth/oauth-client/src/store/session.rs +++ b/atrium-oauth/oauth-client/src/store/session.rs @@ -1,3 +1,5 @@ +use std::hash::Hash; + use crate::types::TokenSet; use atrium_api::types::string::{Datetime, Did}; use atrium_common::store::{memory::MemoryStore, Store}; @@ -19,8 +21,18 @@ impl Session { } } -pub trait SessionStore: Store {} +pub trait SessionStore: Store +where + K: Eq + Hash, + V: Clone, +{ +} -pub type MemorySessionStore = MemoryStore; +pub type MemorySessionStore = MemoryStore; -impl SessionStore for MemorySessionStore {} +impl SessionStore for MemorySessionStore +where + K: Eq + Hash + Send + Sync, + V: Clone + Send, +{ +}