-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow response_mode to be null and if so do not add the query param #3700
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,18 +106,25 @@ fn resolve_response_mode( | |
) -> Result<ResponseMode, RouteError> { | ||
use ResponseMode as M; | ||
|
||
// If the response type includes either "token" or "id_token", the default | ||
// response mode is "fragment" and the response mode "query" must not be | ||
// used | ||
if response_type.has_token() || response_type.has_id_token() { | ||
match suggested_response_mode { | ||
None => Ok(M::Fragment), | ||
Some(M::Query) => Err(RouteError::InvalidResponseMode), | ||
Some(mode) => Ok(mode), | ||
// If the response type includes either "token" or "id_token", the default | ||
// response mode is "fragment" and the response mode "query" must not be | ||
// used | ||
if let Some(suggested_response_mode) = suggested_response_mode { | ||
match suggested_response_mode { | ||
M::Query => Err(RouteError::InvalidResponseMode), | ||
mode => Ok(mode), | ||
} | ||
} else { | ||
Ok(M::Fragment) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's unclear to me why this has to change? This code is for the client -> MAS login part, and it is spec-compliant, nothing to do with the upstream provider stuff |
||
} | ||
} else { | ||
// In other cases, all response modes are allowed, defaulting to "query" | ||
Ok(suggested_response_mode.unwrap_or(M::Query)) | ||
if let Some(suggested_response_mode) = suggested_response_mode { | ||
Ok(suggested_response_mode) | ||
} else { | ||
Ok(M::Query) | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -109,10 +109,13 @@ pub(crate) enum RouteError { | |
MissingFormParams, | ||
|
||
#[error("Invalid response mode, expected '{expected}'")] | ||
InvalidParamsMode { | ||
InvalidResponseMode { | ||
expected: UpstreamOAuthProviderResponseMode, | ||
}, | ||
|
||
#[error("Invalid request method '{method}'")] | ||
InvalidReqMethod { method: Method }, | ||
|
||
#[error(transparent)] | ||
Internal(Box<dyn std::error::Error + Send + Sync + 'static>), | ||
} | ||
|
@@ -184,25 +187,46 @@ pub(crate) async fn handler( | |
// The `Form` extractor will use the body of the request for POST requests and | ||
// the query parameters for GET requests. We need to then look at the method do | ||
// make sure it matches the expected `response_mode` | ||
match (provider.response_mode, method) { | ||
(UpstreamOAuthProviderResponseMode::Query, Method::GET) => {} | ||
(UpstreamOAuthProviderResponseMode::FormPost, Method::POST) => { | ||
// We set the cookies with a `Same-Site` policy set to `Lax`, so because this is | ||
// usually a cross-site form POST, we need to render a form with the | ||
// same values, which posts back to the same URL. However, there are | ||
// other valid reasons for the cookie to be missing, so to track whether we did | ||
// this POST ourselves, we set a flag. | ||
if sessions_cookie.is_empty() && !params.did_mas_repost_to_itself { | ||
let params = Params { | ||
did_mas_repost_to_itself: true, | ||
..params | ||
}; | ||
let context = FormPostContext::new_for_current_url(params).with_language(&locale); | ||
let html = templates.render_form_post(&context)?; | ||
return Ok(Html(html).into_response()); | ||
} | ||
match method { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm finding the old single match on the tuple easier to read. Could you go back to using that? |
||
Method::GET => { | ||
match provider.response_mode { | ||
Some(UpstreamOAuthProviderResponseMode::Query) | None => {} | ||
Some(UpstreamOAuthProviderResponseMode::FormPost) => { | ||
return Err(RouteError::InvalidResponseMode { | ||
expected: UpstreamOAuthProviderResponseMode::Query, | ||
}) | ||
} | ||
}; | ||
} | ||
Method::POST => { | ||
match provider.response_mode { | ||
Some(UpstreamOAuthProviderResponseMode::FormPost) => { | ||
// We set the cookies with a `Same-Site` policy set to `Lax`, so because this is | ||
// usually a cross-site form POST, we need to render a form with the | ||
// same values, which posts back to the same URL. However, there are | ||
// other valid reasons for the cookie to be missing, so to track whether we did | ||
// this POST ourselves, we set a flag. | ||
if sessions_cookie.is_empty() && !params.did_mas_repost_to_itself { | ||
let params = Params { | ||
did_mas_repost_to_itself: true, | ||
..params | ||
}; | ||
let context = | ||
FormPostContext::new_for_current_url(params).with_language(&locale); | ||
let html = templates.render_form_post(&context)?; | ||
return Ok(Html(html).into_response()); | ||
} | ||
} | ||
Some(UpstreamOAuthProviderResponseMode::Query) | None => { | ||
return Err(RouteError::InvalidResponseMode { | ||
expected: UpstreamOAuthProviderResponseMode::FormPost, | ||
}) | ||
} | ||
}; | ||
} | ||
method => { | ||
return Err(RouteError::InvalidReqMethod { method }); | ||
Comment on lines
+227
to
+228
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should never happen, the route is installed as POST and GET handler anyway |
||
} | ||
(expected, _) => return Err(RouteError::InvalidParamsMode { expected }), | ||
} | ||
|
||
let (session_id, _post_auth_action) = sessions_cookie | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALTER TABLE "upstream_oauth_providers" ALTER COLUMN "response_mode" DROP NOT NULL; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add the copyright header + a short description of what this migration does? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
provider.response_mode.map(…)
would help simplify this