From 3584302beeef3dd12fab2418d6f3b53734e933b4 Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Sat, 20 Jan 2024 17:50:13 +0000 Subject: [PATCH] Use our own session-bound XSRF tokens for the consent screen --- src/web/oauth_openid/authorisation.rs | 31 +++++++++++++++------------ 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/web/oauth_openid/authorisation.rs b/src/web/oauth_openid/authorisation.rs index 024eb5f..a3483dd 100644 --- a/src/web/oauth_openid/authorisation.rs +++ b/src/web/oauth_openid/authorisation.rs @@ -6,8 +6,8 @@ use axum::{ response::{Html, IntoResponse, Response}, Extension, Form, }; -use axum_csrf::CsrfToken; +use chrono::Utc; use eyre::{Context, ContextCompat}; use serde::{Deserialize, Serialize}; @@ -59,7 +59,6 @@ pub async fn oidc_authorisation( login_session: Option, Extension(config): Extension>, Extension(code_store): Extension, - csrf: CsrfToken, OriginalUri(uri): OriginalUri, ) -> Response { 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 !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. @@ -107,6 +106,7 @@ pub async fn oidc_authorisation( #[derive(Deserialize)] pub struct PostConsentForm { action: String, + csrf: String, } pub async fn post_oidc_authorisation_consent( @@ -114,7 +114,6 @@ pub async fn post_oidc_authorisation_consent( login_session: Option, Extension(config): Extension>, Extension(code_store): Extension, - _csrf: CsrfToken, OriginalUri(uri): OriginalUri, Form(form): Form, ) -> Response { @@ -128,6 +127,14 @@ pub async fn post_oidc_authorisation_consent( 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() { "accept" => { // TODO CORS not ok: send strict prevention headers and frame headers @@ -204,18 +211,14 @@ async fn show_consent_page( login_session: LoginSession, client_config: &OidcClientConfiguration, _config: &Configuration, - csrf: CsrfToken, ) -> Response { - let csrf_token = csrf - .authenticity_token() + let csrf_token = login_session + .generate_csrf_token(Utc::now()) .expect("must be able to create a CSRF token"); - ( - csrf, - Html(format!( - "hi {}, consent to {}?
", - login_session.user_name, client_config.name, csrf_token - )) - ) + Html(format!( + "hi {}, consent to {}?
", + login_session.user_name, client_config.name, csrf_token + )) .into_response() }