1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-09 04:22:45 +03:00

handlers: box the rng and clock, and extract it from the state

This commit is contained in:
Quentin Gliech
2023-01-18 17:32:54 +01:00
parent 8c585b20f0
commit 9005931e2a
52 changed files with 291 additions and 193 deletions

View File

@@ -15,6 +15,7 @@
use axum_extra::extract::cookie::{Cookie, PrivateCookieJar};
use chrono::{DateTime, Duration, Utc};
use data_encoding::{DecodeError, BASE64URL_NOPAD};
use mas_storage::Clock;
use rand::{Rng, RngCore};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, TimestampSeconds};
@@ -108,22 +109,27 @@ pub struct ProtectedForm<T> {
}
pub trait CsrfExt {
fn csrf_token<R>(self, now: DateTime<Utc>, rng: R) -> (CsrfToken, Self)
fn csrf_token<C, R>(self, clock: &C, rng: R) -> (CsrfToken, Self)
where
R: RngCore;
fn verify_form<T>(&self, now: DateTime<Utc>, form: ProtectedForm<T>) -> Result<T, CsrfError>;
R: RngCore,
C: Clock;
fn verify_form<C, T>(&self, clock: &C, form: ProtectedForm<T>) -> Result<T, CsrfError>
where
C: Clock;
}
impl<K> CsrfExt for PrivateCookieJar<K> {
fn csrf_token<R>(self, now: DateTime<Utc>, rng: R) -> (CsrfToken, Self)
fn csrf_token<C, R>(self, clock: &C, rng: R) -> (CsrfToken, Self)
where
R: RngCore,
C: Clock,
{
let jar = self;
let mut cookie = jar.get("csrf").unwrap_or_else(|| Cookie::new("csrf", ""));
cookie.set_path("/");
cookie.set_http_only(true);
let now = clock.now();
let new_token = cookie
.decode()
.ok()
@@ -136,10 +142,13 @@ impl<K> CsrfExt for PrivateCookieJar<K> {
(new_token, jar)
}
fn verify_form<T>(&self, now: DateTime<Utc>, form: ProtectedForm<T>) -> Result<T, CsrfError> {
fn verify_form<C, T>(&self, clock: &C, form: ProtectedForm<T>) -> Result<T, CsrfError>
where
C: Clock,
{
let cookie = self.get("csrf").ok_or(CsrfError::Missing)?;
let token: CsrfToken = cookie.decode()?;
let token = token.verify_expiration(now)?;
let token = token.verify_expiration(clock.now())?;
token.verify_form_value(&form.csrf)?;
Ok(form.inner)
}

View File

@@ -24,13 +24,12 @@ use axum::{
response::{IntoResponse, Response},
BoxError,
};
use chrono::{DateTime, Utc};
use headers::{authorization::Bearer, Authorization, Header, HeaderMapExt, HeaderName};
use http::{header::WWW_AUTHENTICATE, HeaderMap, HeaderValue, Request, StatusCode};
use mas_data_model::Session;
use mas_storage::{
oauth2::{OAuth2AccessTokenRepository, OAuth2SessionRepository},
Repository,
Clock, Repository,
};
use serde::{de::DeserializeOwned, Deserialize};
use thiserror::Error;
@@ -86,10 +85,10 @@ pub struct UserAuthorization<F = ()> {
impl<F: Send> UserAuthorization<F> {
// TODO: take scopes to validate as parameter
pub async fn protected_form<R: Repository>(
pub async fn protected_form<R: Repository, C: Clock>(
self,
repo: &mut R,
now: DateTime<Utc>,
clock: &C,
) -> Result<(Session, F), AuthorizationVerificationError<R::Error>> {
let form = match self.form {
Some(f) => f,
@@ -98,7 +97,7 @@ impl<F: Send> UserAuthorization<F> {
let (token, session) = self.access_token.fetch(repo).await?;
if !token.is_valid(now) || !session.is_valid() {
if !token.is_valid(clock.now()) || !session.is_valid() {
return Err(AuthorizationVerificationError::InvalidToken);
}
@@ -106,14 +105,14 @@ impl<F: Send> UserAuthorization<F> {
}
// TODO: take scopes to validate as parameter
pub async fn protected<R: Repository>(
pub async fn protected<R: Repository, C: Clock>(
self,
repo: &mut R,
now: DateTime<Utc>,
clock: &C,
) -> Result<Session, AuthorizationVerificationError<R::Error>> {
let (token, session) = self.access_token.fetch(repo).await?;
if !token.is_valid(now) || !session.is_valid() {
if !token.is_valid(clock.now()) || !session.is_valid() {
return Err(AuthorizationVerificationError::InvalidToken);
}