@@ -41,7 +41,8 @@ type LocalBoxFuture<T> = Pin<Box<dyn Future<Output = T> + 'static>>;
4141const SQLPAGE_AUTH_COOKIE_NAME : & str = "sqlpage_auth" ;
4242const SQLPAGE_REDIRECT_URI : & str = "/sqlpage/oidc_callback" ;
4343const SQLPAGE_STATE_COOKIE_NAME : & str = "sqlpage_oidc_state" ;
44- const OIDC_CLIENT_REFRESH_INTERVAL : Duration = Duration :: from_secs ( 60 * 60 ) ;
44+ const OIDC_CLIENT_MAX_REFRESH_INTERVAL : Duration = Duration :: from_secs ( 60 * 60 ) ;
45+ const OIDC_CLIENT_MIN_REFRESH_INTERVAL : Duration = Duration :: from_secs ( 5 ) ;
4546
4647#[ derive( Clone , Debug , Serialize , Deserialize ) ]
4748#[ serde( transparent) ]
@@ -184,7 +185,14 @@ impl OidcState {
184185 /// Refreshes the OIDC client from the provider metadata URL if it has expired.
185186 /// Most providers update their signing keys periodically.
186187 pub async fn refresh_if_expired ( & self , service_request : & ServiceRequest ) {
187- if self . client . read ( ) . await . last_update . elapsed ( ) > OIDC_CLIENT_REFRESH_INTERVAL {
188+ if self . client . read ( ) . await . last_update . elapsed ( ) > OIDC_CLIENT_MAX_REFRESH_INTERVAL {
189+ self . refresh ( service_request) . await ;
190+ }
191+ }
192+
193+ /// When an authentication error is encountered, refresh the OIDC client info faster
194+ pub async fn refresh_on_error ( & self , service_request : & ServiceRequest ) {
195+ if self . client . read ( ) . await . last_update . elapsed ( ) > OIDC_CLIENT_MIN_REFRESH_INTERVAL {
188196 self . refresh ( service_request) . await ;
189197 }
190198 }
@@ -337,6 +345,7 @@ async fn handle_request(
337345 }
338346 Err ( e) => {
339347 log:: debug!( "An auth cookie is present but could not be verified. Redirecting to OIDC provider to re-authenticate. {e:?}" ) ;
348+ oidc_state. refresh_on_error ( & request) . await ;
340349 handle_unauthenticated_request ( oidc_state, request) . await
341350 }
342351 }
@@ -419,7 +428,7 @@ async fn process_oidc_callback(
419428) -> anyhow:: Result < HttpResponse > {
420429 let http_client = get_http_client_from_appdata ( request) ?;
421430
422- let state = get_state_from_cookie ( request) ?;
431+ let state = get_state_from_cookie ( request) . context ( "Failed to read oidc state cookie" ) ?;
423432
424433 let params = Query :: < OidcCallbackParams > :: from_query ( query_string)
425434 . with_context ( || {
@@ -442,7 +451,9 @@ async fn process_oidc_callback(
442451 let redirect_target = validate_redirect_url ( state. initial_url ) ;
443452 log:: info!( "Redirecting to {redirect_target} after a successful login" ) ;
444453 let mut response = build_redirect_response ( redirect_target) ;
445- set_auth_cookie ( & mut response, & token_response, oidc_state) . await ?;
454+ set_auth_cookie ( & mut response, & token_response, oidc_state)
455+ . await
456+ . context ( "Failed to set auth cookie" ) ?;
446457 Ok ( response)
447458}
448459
@@ -456,7 +467,8 @@ async fn exchange_code_for_token(
456467 oidc_callback_params. code ,
457468 ) ) ?
458469 . request_async ( & AwcHttpClient :: from_client ( http_client) )
459- . await ?;
470+ . await
471+ . context ( "Failed to exchange code for token" ) ?;
460472 Ok ( token_response)
461473}
462474
@@ -471,7 +483,10 @@ async fn set_auth_cookie(
471483 . id_token ( )
472484 . context ( "No ID token found in the token response. You may have specified an oauth2 provider that does not support OIDC." ) ?;
473485
474- let claims = oidc_state. get_token_claims ( id_token. clone ( ) , None ) . await ?;
486+ let claims = oidc_state
487+ . get_token_claims ( id_token. clone ( ) , None )
488+ . await
489+ . context ( "Invalid token returned by OIDC provider" ) ?;
475490 let expiration = claims. expiration ( ) ;
476491 let max_age_seconds = expiration. signed_duration_since ( Utc :: now ( ) ) . num_seconds ( ) ;
477492
0 commit comments