66
77use axum:: {
88 extract:: { Path , Query , State } ,
9+ http:: Method ,
910 response:: { IntoResponse , Response } ,
1011 Form ,
1112} ;
@@ -110,9 +111,6 @@ pub(crate) enum RouteError {
110111 #[ error( "Missing form parameters" ) ]
111112 MissingFormParams ,
112113
113- #[ error( "Ambiguous parameters: got both query and form parameters" ) ]
114- AmbiguousParams ,
115-
116114 #[ error( "Invalid response mode, expected '{expected}'" ) ]
117115 InvalidParamsMode {
118116 expected : UpstreamOAuthProviderResponseMode ,
@@ -161,11 +159,11 @@ pub(crate) async fn handler(
161159 State ( keystore) : State < Keystore > ,
162160 State ( client) : State < reqwest:: Client > ,
163161 State ( templates) : State < Templates > ,
162+ method : Method ,
164163 PreferredLanguage ( locale) : PreferredLanguage ,
165164 cookie_jar : CookieJar ,
166165 Path ( provider_id) : Path < Ulid > ,
167- query_params : Option < Query < Params > > ,
168- form_params : Option < Form < Params > > ,
166+ params : Option < Form < Params > > ,
169167) -> Result < Response , RouteError > {
170168 let provider = repo
171169 . upstream_oauth_provider ( )
@@ -176,35 +174,37 @@ pub(crate) async fn handler(
176174
177175 let sessions_cookie = UpstreamSessionsCookie :: load ( & cookie_jar) ;
178176
179- // Read the parameters from the query or the form, depending on what
180- // response_mode the provider uses
181- let params = match ( provider. response_mode , query_params, form_params) {
182- ( UpstreamOAuthProviderResponseMode :: Query , Some ( Query ( query_params) ) , None ) => query_params,
183- ( UpstreamOAuthProviderResponseMode :: FormPost , None , Some ( Form ( mut form_params) ) ) => {
177+ let Some ( Form ( params) ) = params else {
178+ if let Method :: GET = method {
179+ return Err ( RouteError :: MissingQueryParams ) ;
180+ }
181+
182+ return Err ( RouteError :: MissingFormParams ) ;
183+ } ;
184+
185+ // The `Form` extractor will use the body of the request for POST requests and
186+ // the query parameters for GET requests. We need to then look at the method do
187+ // make sure it matches the expected `response_mode`
188+ match ( provider. response_mode , method) {
189+ ( UpstreamOAuthProviderResponseMode :: Query , Method :: GET ) => { }
190+ ( UpstreamOAuthProviderResponseMode :: FormPost , Method :: POST ) => {
184191 // We set the cookies with a `Same-Site` policy set to `Lax`, so because this is
185192 // usually a cross-site form POST, we need to render a form with the
186193 // same values, which posts back to the same URL. However, there are
187194 // other valid reasons for the cookie to be missing, so to track whether we did
188195 // this POST ourselves, we set a flag.
189- if sessions_cookie. is_empty ( ) && !form_params. did_mas_repost_to_itself {
190- form_params. did_mas_repost_to_itself = true ;
191- let context =
192- FormPostContext :: new_for_current_url ( form_params) . with_language ( & locale) ;
196+ if sessions_cookie. is_empty ( ) && !params. did_mas_repost_to_itself {
197+ let params = Params {
198+ did_mas_repost_to_itself : true ,
199+ ..params
200+ } ;
201+ let context = FormPostContext :: new_for_current_url ( params) . with_language ( & locale) ;
193202 let html = templates. render_form_post ( & context) ?;
194203 return Ok ( Html ( html) . into_response ( ) ) ;
195204 }
196-
197- form_params
198- }
199- ( UpstreamOAuthProviderResponseMode :: Query , None , None ) => {
200- return Err ( RouteError :: MissingQueryParams )
201- }
202- ( UpstreamOAuthProviderResponseMode :: FormPost , None , None ) => {
203- return Err ( RouteError :: MissingFormParams )
204205 }
205- ( _, Some ( _) , Some ( _) ) => return Err ( RouteError :: AmbiguousParams ) ,
206- ( expected, _, _) => return Err ( RouteError :: InvalidParamsMode { expected } ) ,
207- } ;
206+ ( expected, _) => return Err ( RouteError :: InvalidParamsMode { expected } ) ,
207+ }
208208
209209 let ( session_id, _post_auth_action) = sessions_cookie
210210 . find_session ( provider_id, & params. state )
0 commit comments