Use our own session-bound XSRF tokens for the consent screen
This commit is contained in:
parent
2d23eae641
commit
3584302bee
@ -6,8 +6,8 @@ use axum::{
|
|||||||
response::{Html, IntoResponse, Response},
|
response::{Html, IntoResponse, Response},
|
||||||
Extension, Form,
|
Extension, Form,
|
||||||
};
|
};
|
||||||
use axum_csrf::CsrfToken;
|
|
||||||
|
|
||||||
|
use chrono::Utc;
|
||||||
use eyre::{Context, ContextCompat};
|
use eyre::{Context, ContextCompat};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -59,7 +59,6 @@ pub async fn oidc_authorisation(
|
|||||||
login_session: Option<LoginSession>,
|
login_session: Option<LoginSession>,
|
||||||
Extension(config): Extension<Arc<Configuration>>,
|
Extension(config): Extension<Arc<Configuration>>,
|
||||||
Extension(code_store): Extension<VolatileCodeStore>,
|
Extension(code_store): Extension<VolatileCodeStore>,
|
||||||
csrf: CsrfToken,
|
|
||||||
OriginalUri(uri): OriginalUri,
|
OriginalUri(uri): OriginalUri,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let Query(query) = match query {
|
let Query(query) = match query {
|
||||||
@ -87,7 +86,7 @@ pub async fn oidc_authorisation(
|
|||||||
|
|
||||||
// If the application requires consent, then we should ask for that.
|
// If the application requires consent, then we should ask for that.
|
||||||
if !client_config.skip_consent {
|
if !client_config.skip_consent {
|
||||||
return show_consent_page(login_session, client_config, &config, csrf).await;
|
return show_consent_page(login_session, client_config, &config).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No consent needed: process the authorisation.
|
// No consent needed: process the authorisation.
|
||||||
@ -107,6 +106,7 @@ pub async fn oidc_authorisation(
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct PostConsentForm {
|
pub struct PostConsentForm {
|
||||||
action: String,
|
action: String,
|
||||||
|
csrf: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn post_oidc_authorisation_consent(
|
pub async fn post_oidc_authorisation_consent(
|
||||||
@ -114,7 +114,6 @@ pub async fn post_oidc_authorisation_consent(
|
|||||||
login_session: Option<LoginSession>,
|
login_session: Option<LoginSession>,
|
||||||
Extension(config): Extension<Arc<Configuration>>,
|
Extension(config): Extension<Arc<Configuration>>,
|
||||||
Extension(code_store): Extension<VolatileCodeStore>,
|
Extension(code_store): Extension<VolatileCodeStore>,
|
||||||
_csrf: CsrfToken,
|
|
||||||
OriginalUri(uri): OriginalUri,
|
OriginalUri(uri): OriginalUri,
|
||||||
Form(form): Form<PostConsentForm>,
|
Form(form): Form<PostConsentForm>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
@ -128,6 +127,14 @@ pub async fn post_oidc_authorisation_consent(
|
|||||||
return make_login_redirect(uri);
|
return make_login_redirect(uri);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if login_session
|
||||||
|
.validate_csrf_token(&form.csrf, Utc::now())
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
// XSRF token is not valid, so show the consent form again...
|
||||||
|
return show_consent_page(login_session, client_config, &config).await;
|
||||||
|
}
|
||||||
|
|
||||||
match form.action.as_str() {
|
match form.action.as_str() {
|
||||||
"accept" => {
|
"accept" => {
|
||||||
// TODO CORS not ok: send strict prevention headers and frame headers
|
// TODO CORS not ok: send strict prevention headers and frame headers
|
||||||
@ -204,18 +211,14 @@ async fn show_consent_page(
|
|||||||
login_session: LoginSession,
|
login_session: LoginSession,
|
||||||
client_config: &OidcClientConfiguration,
|
client_config: &OidcClientConfiguration,
|
||||||
_config: &Configuration,
|
_config: &Configuration,
|
||||||
csrf: CsrfToken,
|
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let csrf_token = csrf
|
let csrf_token = login_session
|
||||||
.authenticity_token()
|
.generate_csrf_token(Utc::now())
|
||||||
.expect("must be able to create a CSRF token");
|
.expect("must be able to create a CSRF token");
|
||||||
(
|
Html(format!(
|
||||||
csrf,
|
"hi <u>{}</u>, consent to <u>{}</u>? <form method='POST'><input type='hidden' name='csrf' value='{}'><button type='submit' name='action' value='accept'>Accept</button> <button type='submit' name='action' value='deny'>Deny</button></form>",
|
||||||
Html(format!(
|
login_session.user_name, client_config.name, csrf_token
|
||||||
"hi <u>{}</u>, consent to <u>{}</u>? <form method='POST'><input type='hidden' name='csrf' value='{}'><button type='submit' name='action' value='accept'>Accept</button> <button type='submit' name='action' value='deny'>Deny</button></form>",
|
))
|
||||||
login_session.user_name, client_config.name, csrf_token
|
|
||||||
))
|
|
||||||
)
|
|
||||||
.into_response()
|
.into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user