@@ -13,6 +13,7 @@ use mas_axum_utils::{
1313 cookies:: CookieJar , http_client_factory:: HttpClientFactory , sentry:: SentryEventID ,
1414} ;
1515use mas_data_model:: UpstreamOAuthProvider ;
16+ use mas_data_model:: UpstreamOAuthProviderUserProfileMethod ;
1617use mas_keystore:: { Encrypter , Keystore } ;
1718use mas_oidc_client:: requests:: {
1819 authorization_code:: AuthorizationValidationData , jose:: JwtVerificationData ,
@@ -94,13 +95,14 @@ pub(crate) enum RouteError {
9495 MissingCookie ,
9596
9697 #[ error( transparent) ]
97- Internal ( Box < dyn std:: error:: Error > ) ,
98+ Internal ( Box < dyn std:: error:: Error + Send + Sync + ' static > ) ,
9899}
99100
100101impl_from_error_for_route ! ( mas_storage:: RepositoryError ) ;
101102impl_from_error_for_route ! ( mas_oidc_client:: error:: DiscoveryError ) ;
102103impl_from_error_for_route ! ( mas_oidc_client:: error:: JwksError ) ;
103104impl_from_error_for_route ! ( mas_oidc_client:: error:: TokenAuthorizationCodeError ) ;
105+ impl_from_error_for_route ! ( mas_oidc_client:: error:: UserInfoError ) ;
104106impl_from_error_for_route ! ( super :: ProviderCredentialsError ) ;
105107impl_from_error_for_route ! ( super :: cookie:: UpstreamSessionNotFound ) ;
106108
@@ -212,32 +214,54 @@ pub(crate) async fn get(
212214 redirect_uri,
213215 } ;
214216
215- let id_token_verification_data = JwtVerificationData {
217+ let verification_data = JwtVerificationData {
216218 issuer : & provider. issuer ,
217219 jwks : & jwks,
218220 // TODO: make that configurable
219221 signing_algorithm : & mas_iana:: jose:: JsonWebSignatureAlg :: Rs256 ,
220222 client_id : & provider. client_id ,
221223 } ;
222224
223- let ( response, id_token ) =
225+ let ( response, id_token_map ) =
224226 mas_oidc_client:: requests:: authorization_code:: access_token_with_authorization_code (
225227 & http_service,
226228 client_credentials,
227229 lazy_metadata. token_endpoint ( ) . await ?,
228230 code,
229231 validation_data,
230- Some ( id_token_verification_data ) ,
232+ Some ( verification_data ) ,
231233 clock. now ( ) ,
232234 & mut rng,
233235 )
234236 . await ?;
235237
236- let ( _header, id_token) = id_token. ok_or ( RouteError :: MissingIDToken ) ?. into_parts ( ) ;
238+ let ( _header, id_token) = id_token_map
239+ . clone ( )
240+ . ok_or ( RouteError :: MissingIDToken ) ?
241+ . into_parts ( ) ;
242+
243+ let use_userinfo_endpoint = match provider. user_profile_method {
244+ UpstreamOAuthProviderUserProfileMethod :: Auto => !provider. scope . contains ( "openid" ) ,
245+ UpstreamOAuthProviderUserProfileMethod :: UserinfoEndpoint => true ,
246+ } ;
247+
248+ let userinfo = if use_userinfo_endpoint {
249+ let user_info_resp = mas_oidc_client:: requests:: userinfo:: fetch_userinfo (
250+ & http_service,
251+ lazy_metadata. userinfo_endpoint ( ) . await ?,
252+ response. access_token . as_str ( ) ,
253+ Some ( verification_data) ,
254+ & id_token_map. ok_or ( RouteError :: MissingIDToken ) ?,
255+ )
256+ . await ?;
257+ minijinja:: Value :: from_serialize ( & user_info_resp)
258+ } else {
259+ minijinja:: Value :: from_serialize ( & id_token)
260+ } ;
237261
238262 let env = {
239263 let mut env = environment ( ) ;
240- env. add_global ( "user" , minijinja :: Value :: from_serialize ( & id_token ) ) ;
264+ env. add_global ( "user" , userinfo ) ;
241265 env
242266 } ;
243267
0 commit comments