@@ -41,32 +41,33 @@ use crate::{impl_from_error_for_route, upstream_oauth2::cache::MetadataCache, Pr
4141
4242#[ derive( Serialize , Deserialize ) ]
4343pub struct Params {
44- state : String ,
44+ state : Option < String > ,
4545
4646 /// An extra parameter to track whether the POST request was re-made by us
4747 /// to the same URL to escape Same-Site cookies restrictions
4848 #[ serde( default ) ]
4949 did_mas_repost_to_itself : bool ,
5050
51+ code : Option < String > ,
52+
53+ error : Option < ClientErrorCode > ,
54+ error_description : Option < String > ,
55+ #[ allow( dead_code) ]
56+ error_uri : Option < String > ,
57+
5158 #[ serde( flatten) ]
52- code_or_error : CodeOrError ,
59+ extra_callback_parameters : Option < serde_json :: Value > ,
5360}
5461
55- #[ derive( Serialize , Deserialize ) ]
56- #[ serde( untagged) ]
57- enum CodeOrError {
58- Code {
59- code : String ,
60-
61- #[ serde( flatten) ]
62- extra_callback_parameters : Option < serde_json:: Value > ,
63- } ,
64- Error {
65- error : ClientErrorCode ,
66- error_description : Option < String > ,
67- #[ allow( dead_code) ]
68- error_uri : Option < String > ,
69- } ,
62+ impl Params {
63+ /// Returns true if none of the fields are set
64+ pub fn is_empty ( & self ) -> bool {
65+ self . state . is_none ( )
66+ && self . code . is_none ( )
67+ && self . error . is_none ( )
68+ && self . error_description . is_none ( )
69+ && self . error_uri . is_none ( )
70+ }
7071}
7172
7273#[ derive( Debug , Error ) ]
@@ -86,6 +87,12 @@ pub(crate) enum RouteError {
8687 #[ error( "State parameter mismatch" ) ]
8788 StateMismatch ,
8889
90+ #[ error( "Missing state parameter" ) ]
91+ MissingState ,
92+
93+ #[ error( "Missing code parameter" ) ]
94+ MissingCode ,
95+
8996 #[ error( "Could not extract subject from ID token" ) ]
9097 ExtractSubject ( #[ source] minijinja:: Error ) ,
9198
@@ -161,7 +168,7 @@ pub(crate) async fn handler(
161168 PreferredLanguage ( locale) : PreferredLanguage ,
162169 cookie_jar : CookieJar ,
163170 Path ( provider_id) : Path < Ulid > ,
164- Form ( params) : Form < Option < Params > > ,
171+ Form ( params) : Form < Params > ,
165172) -> Result < Response , RouteError > {
166173 let provider = repo
167174 . upstream_oauth_provider ( )
@@ -172,7 +179,7 @@ pub(crate) async fn handler(
172179
173180 let sessions_cookie = UpstreamSessionsCookie :: load ( & cookie_jar) ;
174181
175- let Some ( params) = params else {
182+ if params. is_empty ( ) {
176183 if let Method :: GET = method {
177184 return Err ( RouteError :: MissingQueryParams ) ;
178185 }
@@ -204,8 +211,19 @@ pub(crate) async fn handler(
204211 ( Some ( expected) , _) => return Err ( RouteError :: InvalidResponseMode { expected } ) ,
205212 }
206213
214+ if let Some ( error) = params. error {
215+ return Err ( RouteError :: ClientError {
216+ error,
217+ error_description : params. error_description . clone ( ) ,
218+ } ) ;
219+ }
220+
221+ let Some ( state) = params. state else {
222+ return Err ( RouteError :: MissingState ) ;
223+ } ;
224+
207225 let ( session_id, _post_auth_action) = sessions_cookie
208- . find_session ( provider_id, & params . state )
226+ . find_session ( provider_id, & state)
209227 . map_err ( |_| RouteError :: MissingCookie ) ?;
210228
211229 let session = repo
@@ -219,7 +237,7 @@ pub(crate) async fn handler(
219237 return Err ( RouteError :: ProviderMismatch ) ;
220238 }
221239
222- if params . state != session. state_str {
240+ if state != session. state_str {
223241 // The state in the session cookie should match the one from the params
224242 return Err ( RouteError :: StateMismatch ) ;
225243 }
@@ -230,21 +248,8 @@ pub(crate) async fn handler(
230248 }
231249
232250 // Let's extract the code from the params, and return if there was an error
233- let ( code, extra_callback_parameters) = match params. code_or_error {
234- CodeOrError :: Error {
235- error,
236- error_description,
237- ..
238- } => {
239- return Err ( RouteError :: ClientError {
240- error,
241- error_description,
242- } )
243- }
244- CodeOrError :: Code {
245- code,
246- extra_callback_parameters,
247- } => ( code, extra_callback_parameters) ,
251+ let Some ( code) = params. code else {
252+ return Err ( RouteError :: MissingCode ) ;
248253 } ;
249254
250255 let mut lazy_metadata = LazyProviderInfos :: new ( & metadata_cache, & provider, & client) ;
@@ -326,7 +331,7 @@ pub(crate) async fn handler(
326331 context = context. with_id_token_claims ( claims) ;
327332 }
328333
329- if let Some ( extra_callback_parameters) = extra_callback_parameters. clone ( ) {
334+ if let Some ( extra_callback_parameters) = params . extra_callback_parameters . clone ( ) {
330335 context = context. with_extra_callback_parameters ( extra_callback_parameters) ;
331336 }
332337
@@ -432,7 +437,7 @@ pub(crate) async fn handler(
432437 session,
433438 & link,
434439 token_response. id_token ,
435- extra_callback_parameters,
440+ params . extra_callback_parameters ,
436441 userinfo,
437442 )
438443 . await ?;
0 commit comments