@@ -64,6 +64,7 @@ struct DiscoveryResponse {
6464 response_types_supported : Vec < String > ,
6565 subject_types_supported : Vec < String > ,
6666 id_token_signing_alg_values_supported : Vec < String > ,
67+ end_session_endpoint : String ,
6768}
6869
6970#[ derive( Serialize ) ]
@@ -89,6 +90,7 @@ async fn discovery_endpoint(state: Data<SharedProviderState>) -> impl Responder
8990 response_types_supported : vec ! [ "code" . to_string( ) ] ,
9091 subject_types_supported : vec ! [ "public" . to_string( ) ] ,
9192 id_token_signing_alg_values_supported : vec ! [ "HS256" . to_string( ) ] ,
93+ end_session_endpoint : format ! ( "{}/logout" , state. issuer_url) ,
9294 } ;
9395 HttpResponse :: Ok ( )
9496 . insert_header ( ( header:: CONTENT_TYPE , "application/json" ) )
@@ -435,3 +437,46 @@ async fn test_oidc_expired_token_is_rejected() {
435437 } )
436438 . await ;
437439}
440+
441+ #[ actix_web:: test]
442+ async fn test_oidc_logout_uses_correct_scheme ( ) {
443+ use sqlpage:: {
444+ app_config:: { test_database_url, AppConfig } ,
445+ webserver:: oidc:: create_logout_url,
446+ AppState ,
447+ } ;
448+
449+ crate :: common:: init_log ( ) ;
450+ let provider = FakeOidcProvider :: new ( ) . await ;
451+
452+ let db_url = test_database_url ( ) ;
453+ let config_json = format ! (
454+ r#"{{
455+ "database_url": "{db_url}",
456+ "oidc_issuer_url": "{}",
457+ "oidc_client_id": "{}",
458+ "oidc_client_secret": "{}",
459+ "https_domain": "example.com"
460+ }}"# ,
461+ provider. issuer_url, provider. client_id, provider. client_secret
462+ ) ;
463+
464+ let config: AppConfig = serde_json:: from_str ( & config_json) . unwrap ( ) ;
465+ let app_state = AppState :: init ( & config) . await . unwrap ( ) ;
466+ let app = test:: init_service ( create_app ( Data :: new ( app_state) ) ) . await ;
467+
468+ let logout_path = create_logout_url ( "/logged_out" , "" , & provider. client_secret ) ;
469+ // make sure the logout path includes the configured domain
470+ assert ! ( logout_path. starts_with( "/sqlpage/oidc_logout" ) ) ;
471+
472+ let req = test:: TestRequest :: get ( ) . uri ( & logout_path) . to_request ( ) ;
473+ let resp = test:: call_service ( & app, req) . await ;
474+
475+ assert_eq ! ( resp. status( ) , StatusCode :: SEE_OTHER ) ;
476+ let location = resp. headers ( ) . get ( "location" ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
477+ let location_url = Url :: parse ( location) . unwrap ( ) ;
478+ assert_eq ! ( location_url. path( ) , "/logout" ) ;
479+ let params: HashMap < String , String > = location_url. query_pairs ( ) . into_owned ( ) . collect ( ) ;
480+ let post_logout = params. get ( "post_logout_redirect_uri" ) . unwrap ( ) ;
481+ assert_eq ! ( post_logout, "https://example.com/logged_out" ) ;
482+ }
0 commit comments