3
3
// SPDX-License-Identifier: AGPL-3.0-only
4
4
// Please see LICENSE in the repository root for full details.
5
5
6
- use mas_axum_utils :: cookies :: CookieJar ;
6
+ use mas_data_model :: { AuthenticationMethod , BrowserSession } ;
7
7
use mas_router:: UrlBuilder ;
8
8
use mas_storage:: { RepositoryAccess , upstream_oauth2:: UpstreamOAuthProviderRepository } ;
9
9
use serde:: { Deserialize , Serialize } ;
10
10
use thiserror:: Error ;
11
- use tracing:: { error, warn } ;
11
+ use tracing:: error;
12
12
use url:: Url ;
13
13
14
- use super :: UpstreamSessionsCookie ;
15
14
use crate :: impl_from_error_for_route;
16
15
17
16
#[ derive( Serialize , Deserialize ) ]
@@ -69,7 +68,7 @@ impl From<reqwest::Error> for RouteError {
69
68
pub async fn get_rp_initiated_logout_endpoints < E > (
70
69
url_builder : & UrlBuilder ,
71
70
repo : & mut impl RepositoryAccess < Error = E > ,
72
- cookie_jar : & CookieJar ,
71
+ browser_session : & BrowserSession ,
73
72
) -> Result < UpstreamLogoutInfo , RouteError >
74
73
where
75
74
RouteError : std:: convert:: From < E > ,
@@ -81,68 +80,55 @@ where
81
80
. to_string ( ) ;
82
81
result. post_logout_redirect_uri = Some ( post_logout_redirect_uri. clone ( ) ) ;
83
82
84
- let sessions_cookie = UpstreamSessionsCookie :: load ( cookie_jar) ;
85
- // Standard location for OIDC end session endpoint
86
- let session_ids = sessions_cookie. session_ids ( ) ;
87
- if session_ids. is_empty ( ) {
88
- return Ok ( result) ;
89
- }
90
- // We only support the first upstream session
91
- let mut provider = None ;
92
- let mut upstream_session = None ;
93
- for session_id in session_ids {
94
- // Get the session and assign its value, wrapped in Some
95
- let session = repo
96
- . upstream_oauth_session ( )
97
- . lookup ( session_id)
98
- . await ?
99
- . ok_or ( RouteError :: SessionNotFound ) ?;
100
- // Get the provider and assign its value, wrapped in Some
101
- let prov = repo
102
- . upstream_oauth_provider ( )
103
- . lookup ( session. provider_id )
104
- . await ?
105
- . ok_or ( RouteError :: ProviderNotFound ) ?;
83
+ let upstream_oauth2_session_id = repo
84
+ . browser_session ( )
85
+ . get_last_authentication ( browser_session)
86
+ . await ?
87
+ . ok_or ( RouteError :: SessionNotFound )
88
+ . map ( |auth| match auth. authentication_method {
89
+ AuthenticationMethod :: UpstreamOAuth2 {
90
+ upstream_oauth2_session_id,
91
+ } => Some ( upstream_oauth2_session_id) ,
92
+ _ => None ,
93
+ } ) ?
94
+ . ok_or ( RouteError :: SessionNotFound ) ?;
106
95
107
- if prov. allow_rp_initiated_logout {
108
- upstream_session = Some ( session) ;
109
- provider = Some ( prov) ;
110
- break ;
111
- }
112
- }
96
+ // Get the session and assign its value, wrapped in Some
97
+ let upstream_session = repo
98
+ . upstream_oauth_session ( )
99
+ . lookup ( upstream_oauth2_session_id)
100
+ . await ?
101
+ . ok_or ( RouteError :: SessionNotFound ) ?;
102
+ // Get the provider and assign its value, wrapped in Some
103
+ let provider = repo
104
+ . upstream_oauth_provider ( )
105
+ . lookup ( upstream_session. provider_id )
106
+ . await ?
107
+ . filter ( |provider| provider. allow_rp_initiated_logout )
108
+ . ok_or ( RouteError :: ProviderNotFound ) ?;
113
109
114
- // Check if we found a provider with allow_rp_initiated_logout
115
- if let Some ( provider) = provider {
116
- // Look for end session endpoint
117
- // In a real implementation, we'd have end_session_endpoint fields in the
118
- // provider For now, we'll try to construct one from the issuer if
119
- // available
120
- if let Some ( issuer) = & provider. issuer {
121
- let end_session_endpoint = format ! ( "{issuer}/protocol/openid-connect/logout" ) ;
122
- let mut logout_url = end_session_endpoint;
123
- // Add post_logout_redirect_uri
124
- if let Some ( post_uri) = & result. post_logout_redirect_uri {
125
- if let Ok ( mut url) = Url :: parse ( & logout_url) {
126
- url. query_pairs_mut ( )
127
- . append_pair ( "post_logout_redirect_uri" , post_uri) ;
128
- url. query_pairs_mut ( )
129
- . append_pair ( "client_id" , & provider. client_id ) ;
130
- // Add id_token_hint if available
131
- if let Some ( session) = & upstream_session {
132
- if let Some ( id_token) = session. id_token ( ) {
133
- url. query_pairs_mut ( ) . append_pair ( "id_token_hint" , id_token) ;
134
- }
135
- }
136
- logout_url = url. to_string ( ) ;
110
+ // Look for end session endpoint
111
+ // In a real implementation, we'd have end_session_endpoint fields in the
112
+ // provider For now, we'll try to construct one from the issuer if
113
+ // available
114
+ if let Some ( issuer) = & provider. issuer {
115
+ let end_session_endpoint = format ! ( "{issuer}/protocol/openid-connect/logout" ) ;
116
+ let mut logout_url = end_session_endpoint;
117
+ // Add post_logout_redirect_uri
118
+ if let Some ( post_uri) = & result. post_logout_redirect_uri {
119
+ if let Ok ( mut url) = Url :: parse ( & logout_url) {
120
+ url. query_pairs_mut ( )
121
+ . append_pair ( "post_logout_redirect_uri" , post_uri) ;
122
+ url. query_pairs_mut ( )
123
+ . append_pair ( "client_id" , & provider. client_id ) ;
124
+ // Add id_token_hint if available
125
+ if let Some ( id_token) = upstream_session. id_token ( ) {
126
+ url. query_pairs_mut ( ) . append_pair ( "id_token_hint" , id_token) ;
137
127
}
128
+ logout_url = url. to_string ( ) ;
138
129
}
139
- result. logout_endpoints . clone_from ( & logout_url) ;
140
- } else {
141
- warn ! (
142
- upstream_oauth_provider. id = %provider. id,
143
- "Provider has no issuer defined, cannot construct RP-initiated logout URL"
144
- ) ;
145
130
}
131
+ result. logout_endpoints . clone_from ( & logout_url) ;
146
132
}
147
133
Ok ( result)
148
134
}
0 commit comments