1- use crate :: auth:: { AuthConfig , SessionToken } ;
1+ use crate :: auth:: { AuthConfig , AuthenticationClient , SessionToken } ;
22use anyhow;
33use async_trait:: async_trait;
44use http:: Extensions ;
@@ -93,17 +93,23 @@ struct TokenState {
9393 token : RwLock < Option < SessionToken > > ,
9494 /// Mutex for refresh operations - ensures single writer
9595 refresh_lock : Mutex < ( ) > ,
96- /// Authentication configuration
97- auth_config : AuthConfig ,
96+ /// Raw authentication client (no middleware to avoid loops)
97+ auth_client : AuthenticationClient ,
9898}
9999
100100impl TokenState {
101- fn new ( auth_config : AuthConfig ) -> Self {
102- Self {
101+ fn new (
102+ auth_config : AuthConfig ,
103+ ) -> Result < Self , Box < dyn std:: error:: Error + Send + Sync > > {
104+ // Create a raw authentication client to avoid middleware loops
105+ let auth_client = AuthenticationClient :: new_raw ( auth_config)
106+ . map_err ( |e| format ! ( "Failed to create auth client: {}" , e) ) ?;
107+
108+ Ok ( Self {
103109 token : RwLock :: new ( None ) ,
104110 refresh_lock : Mutex :: new ( ( ) ) ,
105- auth_config ,
106- }
111+ auth_client ,
112+ } )
107113 }
108114
109115 async fn get_valid_token (
@@ -113,9 +119,9 @@ impl TokenState {
113119 {
114120 let token_guard = self . token . read ( ) . await ;
115121 if let Some ( ref token) = * token_guard {
116- if token
117- . is_valid ( self . auth_config . token_refresh_buffer_minutes )
118- {
122+ if token. is_valid (
123+ self . auth_client . config ( ) . token_refresh_buffer_minutes ,
124+ ) {
119125 debug ! ( "Using existing valid token from middleware" ) ;
120126 return Ok ( token. token . clone ( ) ) ;
121127 }
@@ -136,19 +142,39 @@ impl TokenState {
136142 {
137143 let token_guard = self . token . read ( ) . await ;
138144 if let Some ( ref token) = * token_guard {
139- if token
140- . is_valid ( self . auth_config . token_refresh_buffer_minutes )
141- {
145+ if token. is_valid (
146+ self . auth_client . config ( ) . token_refresh_buffer_minutes ,
147+ ) {
142148 debug ! ( "Token was refreshed by another request" ) ;
143149 return Ok ( token. token . clone ( ) ) ;
144150 }
145151 }
146152 }
147153
148- // TODO: Next, we'll integrate with the actual AuthenticationClient
149- // For now, this is a placeholder that will be replaced
150- warn ! ( "Token refresh not yet implemented" ) ;
151- Err ( "Authentication not yet integrated" . into ( ) )
154+ // Use the raw authentication client to get a new token with metadata
155+ debug ! ( "Performing token refresh using raw authentication client" ) ;
156+ match self . auth_client . get_auth_token_with_metadata ( ) . await {
157+ Ok ( ( token_string, expires_at, session_id) ) => {
158+ let new_token = SessionToken {
159+ token : token_string. clone ( ) ,
160+ expires_at,
161+ session_id,
162+ } ;
163+
164+ // Store the new token
165+ {
166+ let mut token_guard = self . token . write ( ) . await ;
167+ * token_guard = Some ( new_token) ;
168+ }
169+
170+ debug ! ( "Token refresh completed successfully" ) ;
171+ Ok ( token_string)
172+ }
173+ Err ( e) => {
174+ warn ! ( "Token refresh failed: {}" , e) ;
175+ Err ( format ! ( "Authentication failed: {}" , e) . into ( ) )
176+ }
177+ }
152178 }
153179
154180 async fn clear_token ( & self ) {
@@ -165,9 +191,11 @@ pub struct AuthenticationMiddleware {
165191}
166192
167193impl AuthenticationMiddleware {
168- pub fn new ( auth_config : AuthConfig ) -> Self {
169- let token_state = Arc :: new ( TokenState :: new ( auth_config) ) ;
170- Self { token_state }
194+ pub fn new (
195+ auth_config : AuthConfig ,
196+ ) -> Result < Self , Box < dyn std:: error:: Error + Send + Sync > > {
197+ let token_state = Arc :: new ( TokenState :: new ( auth_config) ?) ;
198+ Ok ( Self { token_state } )
171199 }
172200
173201 fn is_auth_endpoint ( & self , req : & reqwest:: Request ) -> bool {
@@ -279,7 +307,7 @@ impl ResilientClient {
279307 max_retries : u32 ,
280308 success_codes : & [ StatusCode ] ,
281309 max_delay : Option < std:: time:: Duration > ,
282- ) -> Self {
310+ ) -> Result < Self , Box < dyn std :: error :: Error + Send + Sync > > {
283311 let base_client = client. unwrap_or_default ( ) ;
284312 let final_max_delay = max_delay. unwrap_or ( DEFAULT_MAX_DELAY ) ;
285313
@@ -300,15 +328,15 @@ impl ResilientClient {
300328 // Add authentication middleware if config is provided
301329 if let Some ( auth_cfg) = auth_config {
302330 debug ! ( "Adding authentication middleware to client" ) ;
303- let auth_middleware = AuthenticationMiddleware :: new ( auth_cfg) ;
331+ let auth_middleware = AuthenticationMiddleware :: new ( auth_cfg) ? ;
304332 builder = builder. with ( auth_middleware) ;
305333 }
306334
307335 let client_with_middleware = builder. with ( LoggingMiddleware ) . build ( ) ;
308336
309- Self {
337+ Ok ( Self {
310338 client : client_with_middleware,
311- }
339+ } )
312340 }
313341
314342 /// Generates a six-character lowercase alphanumeric request ID.
@@ -715,7 +743,8 @@ mod tests {
715743 3 ,
716744 & [ StatusCode :: OK ] ,
717745 None ,
718- ) ;
746+ )
747+ . unwrap ( ) ; //#[allow_ci]
719748
720749 // Verify the client was created successfully
721750 }
@@ -730,7 +759,8 @@ mod tests {
730759 3 ,
731760 & [ StatusCode :: OK ] ,
732761 None ,
733- ) ;
762+ )
763+ . unwrap ( ) ; //#[allow_ci]
734764
735765 // Verify the client was created successfully
736766 }
@@ -748,7 +778,7 @@ mod tests {
748778 max_auth_retries : 3 ,
749779 } ;
750780
751- let middleware = AuthenticationMiddleware :: new ( auth_config) ;
781+ let middleware = AuthenticationMiddleware :: new ( auth_config) . unwrap ( ) ; //#[allow_ci]
752782
753783 // Mock a request to a sessions endpoint (should be detected as auth endpoint)
754784 let mock_request = reqwest:: Request :: new (
0 commit comments