77use axum:: {
88 extract:: { Path , Query , State } ,
99 response:: IntoResponse ,
10+ Form ,
1011} ;
1112use hyper:: StatusCode ;
1213use mas_axum_utils:: { cookies:: CookieJar , sentry:: SentryEventID } ;
13- use mas_data_model:: UpstreamOAuthProvider ;
14+ use mas_data_model:: { UpstreamOAuthProvider , UpstreamOAuthProviderResponseMode } ;
1415use mas_keystore:: { Encrypter , Keystore } ;
1516use mas_oidc_client:: requests:: {
1617 authorization_code:: AuthorizationValidationData , jose:: JwtVerificationData ,
@@ -35,7 +36,7 @@ use super::{
3536use crate :: { impl_from_error_for_route, upstream_oauth2:: cache:: MetadataCache } ;
3637
3738#[ derive( Deserialize ) ]
38- pub struct QueryParams {
39+ pub struct Params {
3940 state : String ,
4041
4142 #[ serde( flatten) ]
@@ -91,6 +92,20 @@ pub(crate) enum RouteError {
9192 #[ error( "Missing session cookie" ) ]
9293 MissingCookie ,
9394
95+ #[ error( "Missing query parameters" ) ]
96+ MissingQueryParams ,
97+
98+ #[ error( "Missing form parameters" ) ]
99+ MissingFormParams ,
100+
101+ #[ error( "Ambiguous parameters: got both query and form parameters" ) ]
102+ AmbiguousParams ,
103+
104+ #[ error( "Invalid response mode, expected '{expected}'" ) ]
105+ InvalidParamsMode {
106+ expected : UpstreamOAuthProviderResponseMode ,
107+ } ,
108+
94109 #[ error( transparent) ]
95110 Internal ( Box < dyn std:: error:: Error > ) ,
96111}
@@ -117,13 +132,13 @@ impl IntoResponse for RouteError {
117132}
118133
119134#[ tracing:: instrument(
120- name = "handlers.upstream_oauth2.callback.get " ,
135+ name = "handlers.upstream_oauth2.callback.handler " ,
121136 fields( upstream_oauth_provider. id = %provider_id) ,
122137 skip_all,
123138 err,
124139) ]
125140#[ allow( clippy:: too_many_lines, clippy:: too_many_arguments) ]
126- pub ( crate ) async fn get (
141+ pub ( crate ) async fn handler (
127142 mut rng : BoxRng ,
128143 clock : BoxClock ,
129144 State ( metadata_cache) : State < MetadataCache > ,
@@ -134,7 +149,8 @@ pub(crate) async fn get(
134149 State ( client) : State < reqwest:: Client > ,
135150 cookie_jar : CookieJar ,
136151 Path ( provider_id) : Path < Ulid > ,
137- Query ( params) : Query < QueryParams > ,
152+ query_params : Option < Query < Params > > ,
153+ form_params : Option < Form < Params > > ,
138154) -> Result < impl IntoResponse , RouteError > {
139155 let provider = repo
140156 . upstream_oauth_provider ( )
@@ -143,6 +159,21 @@ pub(crate) async fn get(
143159 . filter ( UpstreamOAuthProvider :: enabled)
144160 . ok_or ( RouteError :: ProviderNotFound ) ?;
145161
162+ // Read the parameters from the query or the form, depending on what
163+ // response_mode the provider uses
164+ let params = match ( provider. response_mode , query_params, form_params) {
165+ ( UpstreamOAuthProviderResponseMode :: Query , Some ( query_params) , None ) => query_params. 0 ,
166+ ( UpstreamOAuthProviderResponseMode :: FormPost , None , Some ( form_params) ) => form_params. 0 ,
167+ ( UpstreamOAuthProviderResponseMode :: Query , None , None ) => {
168+ return Err ( RouteError :: MissingQueryParams )
169+ }
170+ ( UpstreamOAuthProviderResponseMode :: FormPost , None , None ) => {
171+ return Err ( RouteError :: MissingFormParams )
172+ }
173+ ( _, Some ( _) , Some ( _) ) => return Err ( RouteError :: AmbiguousParams ) ,
174+ ( expected, _, _) => return Err ( RouteError :: InvalidParamsMode { expected } ) ,
175+ } ;
176+
146177 let sessions_cookie = UpstreamSessionsCookie :: load ( & cookie_jar) ;
147178 let ( session_id, _post_auth_action) = sessions_cookie
148179 . find_session ( provider_id, & params. state )
0 commit comments