@@ -368,7 +368,8 @@ async fn handle_unauthenticated_request(
368368
369369 log:: debug!( "Redirecting to OIDC provider" ) ;
370370
371- let response = build_auth_provider_redirect_response ( oidc_state, & request) . await ;
371+ let initial_url = request. uri ( ) . to_string ( ) ;
372+ let response = build_auth_provider_redirect_response ( oidc_state, initial_url) . await ;
372373 Ok ( MiddlewareResponse :: Respond ( request. into_response ( response) ) )
373374}
374375
@@ -380,9 +381,11 @@ async fn handle_oidc_callback(
380381 match process_oidc_callback ( oidc_state, query_string, & request) . await {
381382 Ok ( response) => Ok ( request. into_response ( response) ) ,
382383 Err ( e) => {
383- log:: error!( "Failed to process OIDC callback with params {query_string}: {e:#}" ) ;
384+ let redirect_url =
385+ get_state_from_cookie ( & request) . map_or_else ( |_| "/" . into ( ) , |s| s. initial_url ) ;
386+ log:: error!( "Failed to process OIDC callback. Refreshing oidc provider metadata, then redirecting to {redirect_url}: {e:#}" ) ;
384387 oidc_state. refresh_on_error ( & request) . await ;
385- let resp = build_auth_provider_redirect_response ( oidc_state, & request ) . await ;
388+ let resp = build_auth_provider_redirect_response ( oidc_state, redirect_url ) . await ;
386389 Ok ( request. into_response ( resp) )
387390 }
388391 }
@@ -511,10 +514,11 @@ async fn set_auth_cookie(
511514
512515async fn build_auth_provider_redirect_response (
513516 oidc_state : & OidcState ,
514- request : & ServiceRequest ,
517+ initial_url : String ,
515518) -> HttpResponse {
516519 let AuthUrl { url, params } = build_auth_url ( oidc_state) . await ;
517- let state_cookie = create_state_cookie ( request, params) ;
520+ let state = OidcLoginState :: new ( initial_url, params) ;
521+ let state_cookie = create_state_cookie ( & state) ;
518522 HttpResponse :: TemporaryRedirect ( )
519523 . append_header ( ( "Location" , url. to_string ( ) ) )
520524 . cookie ( state_cookie)
@@ -730,20 +734,6 @@ async fn build_auth_url(oidc_state: &OidcState) -> AuthUrl {
730734 }
731735}
732736
733- #[ derive( Debug , Serialize , Deserialize ) ]
734- struct OidcLoginState {
735- /// The URL to redirect to after the login process is complete.
736- #[ serde( rename = "u" ) ]
737- initial_url : String ,
738- /// The CSRF token to use for the login process.
739- #[ serde( rename = "c" ) ]
740- csrf_token : CsrfToken ,
741- /// The source nonce to use for the login process. It must be checked against the hash
742- /// stored in the ID token.
743- #[ serde( rename = "n" ) ]
744- nonce : Nonce ,
745- }
746-
747737fn hash_nonce ( nonce : & Nonce ) -> String {
748738 use argon2:: password_hash:: { rand_core:: OsRng , PasswordHasher , SaltString } ;
749739 let salt = SaltString :: generate ( & mut OsRng ) ;
@@ -791,19 +781,32 @@ fn nonce_matches(id_token_nonce: &Nonce, state_nonce: &Nonce) -> Result<(), Stri
791781 Ok ( ( ) )
792782}
793783
784+ #[ derive( Debug , Serialize , Deserialize ) ]
785+ struct OidcLoginState {
786+ /// The URL to redirect to after the login process is complete.
787+ #[ serde( rename = "u" ) ]
788+ initial_url : String ,
789+ /// The CSRF token to use for the login process.
790+ #[ serde( rename = "c" ) ]
791+ csrf_token : CsrfToken ,
792+ /// The source nonce to use for the login process. It must be checked against the hash
793+ /// stored in the ID token.
794+ #[ serde( rename = "n" ) ]
795+ nonce : Nonce ,
796+ }
797+
794798impl OidcLoginState {
795- fn new ( request : & ServiceRequest , auth_url : AuthUrlParams ) -> Self {
799+ fn new ( initial_url : String , auth_url : AuthUrlParams ) -> Self {
796800 Self {
797- initial_url : request . uri ( ) . to_string ( ) ,
801+ initial_url,
798802 csrf_token : auth_url. csrf_token ,
799803 nonce : auth_url. nonce ,
800804 }
801805 }
802806}
803807
804- fn create_state_cookie ( request : & ServiceRequest , auth_url : AuthUrlParams ) -> Cookie {
805- let state = OidcLoginState :: new ( request, auth_url) ;
806- let state_json = serde_json:: to_string ( & state) . unwrap ( ) ;
808+ fn create_state_cookie ( login_state : & OidcLoginState ) -> Cookie {
809+ let state_json = serde_json:: to_string ( login_state) . unwrap ( ) ;
807810 Cookie :: build ( SQLPAGE_STATE_COOKIE_NAME , state_json)
808811 . secure ( true )
809812 . http_only ( true )
0 commit comments