@@ -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" ) )
@@ -500,3 +502,46 @@ async fn test_oidc_with_site_prefix() {
500502 redirect_uri
501503 ) ;
502504}
505+
506+ #[ actix_web:: test]
507+ async fn test_oidc_logout_uses_correct_scheme ( ) {
508+ use sqlpage:: {
509+ app_config:: { test_database_url, AppConfig } ,
510+ webserver:: oidc:: create_logout_url,
511+ AppState ,
512+ } ;
513+
514+ crate :: common:: init_log ( ) ;
515+ let provider = FakeOidcProvider :: new ( ) . await ;
516+
517+ let db_url = test_database_url ( ) ;
518+ let config_json = format ! (
519+ r#"{{
520+ "database_url": "{db_url}",
521+ "oidc_issuer_url": "{}",
522+ "oidc_client_id": "{}",
523+ "oidc_client_secret": "{}",
524+ "https_domain": "example.com"
525+ }}"# ,
526+ provider. issuer_url, provider. client_id, provider. client_secret
527+ ) ;
528+
529+ let config: AppConfig = serde_json:: from_str ( & config_json) . unwrap ( ) ;
530+ let app_state = AppState :: init ( & config) . await . unwrap ( ) ;
531+ let app = test:: init_service ( create_app ( Data :: new ( app_state) ) ) . await ;
532+
533+ let logout_path = create_logout_url ( "/logged_out" , "" , & provider. client_secret ) ;
534+ // make sure the logout path includes the configured domain
535+ assert ! ( logout_path. starts_with( "/sqlpage/oidc_logout" ) ) ;
536+
537+ let req = test:: TestRequest :: get ( ) . uri ( & logout_path) . to_request ( ) ;
538+ let resp = test:: call_service ( & app, req) . await ;
539+
540+ assert_eq ! ( resp. status( ) , StatusCode :: SEE_OTHER ) ;
541+ let location = resp. headers ( ) . get ( "location" ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
542+ let location_url = Url :: parse ( location) . unwrap ( ) ;
543+ assert_eq ! ( location_url. path( ) , "/logout" ) ;
544+ let params: HashMap < String , String > = location_url. query_pairs ( ) . into_owned ( ) . collect ( ) ;
545+ let post_logout = params. get ( "post_logout_redirect_uri" ) . unwrap ( ) ;
546+ assert_eq ! ( post_logout, "https://example.com/logged_out" ) ;
547+ }
0 commit comments