1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-31 09:24:31 +03:00

Pass time and RNG in CSRF verification methods

This commit is contained in:
Quentin Gliech
2022-10-24 14:12:07 +02:00
parent f0d95a7613
commit b7c50b5403
26 changed files with 143 additions and 81 deletions

View File

@ -28,10 +28,7 @@ use mas_axum_utils::{
use mas_data_model::Device;
use mas_keystore::Encrypter;
use mas_router::{CompatLoginSsoAction, PostAuthAction, Route};
use mas_storage::{
compat::{fullfill_compat_sso_login, get_compat_sso_login_by_id},
Clock,
};
use mas_storage::compat::{fullfill_compat_sso_login, get_compat_sso_login_by_id};
use mas_templates::{CompatSsoContext, ErrorContext, TemplateContext, Templates};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
@ -58,11 +55,11 @@ pub async fn get(
Path(id): Path<Ulid>,
Query(params): Query<Params>,
) -> Result<Response, FancyError> {
let clock = Clock::default();
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (session_info, cookie_jar) = cookie_jar.session_info();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let maybe_session = session_info.load_session(&mut conn).await?;
@ -128,7 +125,7 @@ pub async fn post(
let mut txn = pool.begin().await?;
let (session_info, cookie_jar) = cookie_jar.session_info();
cookie_jar.verify_form(form)?;
cookie_jar.verify_form(clock.now(), form)?;
let maybe_session = session_info.load_session(&mut txn).await?;

View File

@ -57,6 +57,7 @@ pub(crate) async fn get(
cookie_jar: PrivateCookieJar<Encrypter>,
Path(grant_id): Path<Ulid>,
) -> Result<Response, RouteError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool
.acquire()
.await
@ -76,7 +77,7 @@ pub(crate) async fn get(
}
if let Some(session) = maybe_session {
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let mut policy = policy_factory.instantiate().await?;
let res = policy
@ -126,7 +127,7 @@ pub(crate) async fn post(
.context("failed to begin db transaction")?;
cookie_jar
.verify_form(form)
.verify_form(clock.now(), form)
.context("csrf verification failed")?;
let (session_info, cookie_jar) = cookie_jar.session_info();

View File

@ -42,9 +42,10 @@ pub(crate) async fn get(
State(pool): State<PgPool>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.begin().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut conn).await?;
@ -75,7 +76,7 @@ pub(crate) async fn post(
let (clock, mut rng) = crate::rng_and_clock()?;
let mut txn = pool.begin().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut txn).await?;

View File

@ -57,6 +57,8 @@ pub(crate) async fn get(
State(pool): State<PgPool>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (session_info, cookie_jar) = cookie_jar.session_info();
@ -64,7 +66,7 @@ pub(crate) async fn get(
let maybe_session = session_info.load_session(&mut conn).await?;
if let Some(session) = maybe_session {
render(templates, session, cookie_jar, &mut conn).await
render(&mut rng, &clock, templates, session, cookie_jar, &mut conn).await
} else {
let login = mas_router::Login::default();
Ok((cookie_jar, login.go()).into_response())
@ -72,12 +74,14 @@ pub(crate) async fn get(
}
async fn render(
rng: impl Rng,
clock: &Clock,
templates: Templates,
session: BrowserSession<PostgresqlBackend>,
cookie_jar: PrivateCookieJar<Encrypter>,
executor: impl PgExecutor<'_>,
) -> Result<Response, FancyError> {
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), rng);
let emails = get_user_emails(executor, &session.user).await?;
@ -149,7 +153,7 @@ pub(crate) async fn post(
return Ok((cookie_jar, login.go()).into_response());
};
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
match form {
ManagementForm::Add { email } => {
@ -199,7 +203,15 @@ pub(crate) async fn post(
}
};
let reply = render(templates.clone(), session, cookie_jar, &mut txn).await?;
let reply = render(
&mut rng,
&clock,
templates.clone(),
session,
cookie_jar,
&mut txn,
)
.await?;
txn.commit().await?;

View File

@ -49,9 +49,10 @@ pub(crate) async fn get(
Path(id): Path<Ulid>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut conn).await?;
@ -90,7 +91,7 @@ pub(crate) async fn post(
let clock = Clock::default();
let mut txn = pool.begin().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut txn).await?;

View File

@ -32,9 +32,10 @@ pub(crate) async fn get(
State(pool): State<PgPool>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut conn).await?;

View File

@ -27,9 +27,10 @@ use mas_keystore::Encrypter;
use mas_router::Route;
use mas_storage::{
user::{authenticate_session, set_password},
PostgresqlBackend,
Clock, PostgresqlBackend,
};
use mas_templates::{EmptyContext, TemplateContext, Templates};
use rand::Rng;
use serde::Deserialize;
use sqlx::PgPool;
@ -45,6 +46,7 @@ pub(crate) async fn get(
State(pool): State<PgPool>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (session_info, cookie_jar) = cookie_jar.session_info();
@ -52,7 +54,7 @@ pub(crate) async fn get(
let maybe_session = session_info.load_session(&mut conn).await?;
if let Some(session) = maybe_session {
render(templates, session, cookie_jar).await
render(&mut rng, &clock, templates, session, cookie_jar).await
} else {
let login = mas_router::Login::and_then(mas_router::PostAuthAction::ChangePassword);
Ok((cookie_jar, login.go()).into_response())
@ -60,11 +62,13 @@ pub(crate) async fn get(
}
async fn render(
rng: impl Rng,
clock: &Clock,
templates: Templates,
session: BrowserSession<PostgresqlBackend>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), rng);
let ctx = EmptyContext
.with_session(session)
@ -84,7 +88,7 @@ pub(crate) async fn post(
let (clock, mut rng) = crate::rng_and_clock()?;
let mut txn = pool.begin().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (session_info, cookie_jar) = cookie_jar.session_info();
@ -122,7 +126,7 @@ pub(crate) async fn post(
)
.await?;
let reply = render(templates.clone(), session, cookie_jar).await?;
let reply = render(&mut rng, &clock, templates.clone(), session, cookie_jar).await?;
txn.commit().await?;

View File

@ -29,9 +29,10 @@ pub async fn get(
State(pool): State<PgPool>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<impl IntoResponse, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let session = session_info.load_session(&mut conn).await?;

View File

@ -42,16 +42,16 @@ impl ToFormState for LoginForm {
type Field = LoginFormField;
}
#[tracing::instrument(skip(templates, pool, cookie_jar))]
pub(crate) async fn get(
State(templates): State<Templates>,
State(pool): State<PgPool>,
Query(query): Query<OptionalPostAuthAction>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut conn).await?;
@ -83,9 +83,9 @@ pub(crate) async fn post(
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
// Validate the form
let state = {

View File

@ -34,7 +34,7 @@ pub(crate) async fn post(
let clock = Clock::default();
let mut txn = pool.begin().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (session_info, mut cookie_jar) = cookie_jar.session_info();

View File

@ -41,9 +41,10 @@ pub(crate) async fn get(
Query(query): Query<OptionalPostAuthAction>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut conn).await?;
@ -83,7 +84,7 @@ pub(crate) async fn post(
let (clock, mut rng) = crate::rng_and_clock()?;
let mut txn = pool.begin().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (session_info, cookie_jar) = cookie_jar.session_info();

View File

@ -63,9 +63,10 @@ pub(crate) async fn get(
Query(query): Query<OptionalPostAuthAction>,
cookie_jar: PrivateCookieJar<Encrypter>,
) -> Result<Response, FancyError> {
let (clock, mut rng) = crate::rng_and_clock()?;
let mut conn = pool.acquire().await?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
let (session_info, cookie_jar) = cookie_jar.session_info();
let maybe_session = session_info.load_session(&mut conn).await?;
@ -100,9 +101,9 @@ pub(crate) async fn post(
let (clock, mut rng) = crate::rng_and_clock()?;
let mut txn = pool.begin().await?;
let form = cookie_jar.verify_form(form)?;
let form = cookie_jar.verify_form(clock.now(), form)?;
let (csrf_token, cookie_jar) = cookie_jar.csrf_token();
let (csrf_token, cookie_jar) = cookie_jar.csrf_token(clock.now(), &mut rng);
// Validate the form
let state = {