You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-09 04:22:45 +03:00
Axum migration: CSRF token and login page
This commit is contained in:
@@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, TimestampSeconds};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{CookieExt, PrivateCookieJar};
|
||||
use crate::{cookies::CookieDecodeError, CookieExt, PrivateCookieJar};
|
||||
|
||||
/// Failed to validate CSRF token
|
||||
#[derive(Debug, Error)]
|
||||
@@ -28,6 +28,14 @@ pub enum CsrfError {
|
||||
#[error("CSRF token mismatch")]
|
||||
Mismatch,
|
||||
|
||||
/// The token in the form did not match the token in the cookie
|
||||
#[error("Missing CSRF cookie")]
|
||||
Missing,
|
||||
|
||||
/// Failed to decode the token
|
||||
#[error("could not decode CSRF cookie")]
|
||||
DecodeCookie(#[from] CookieDecodeError),
|
||||
|
||||
/// The token expired
|
||||
#[error("CSRF token expired")]
|
||||
Expired,
|
||||
@@ -89,8 +97,18 @@ impl CsrfToken {
|
||||
}
|
||||
}
|
||||
|
||||
// A CSRF-protected form
|
||||
#[derive(Deserialize)]
|
||||
pub struct ProtectedForm<T> {
|
||||
csrf: String,
|
||||
|
||||
#[serde(flatten)]
|
||||
inner: T,
|
||||
}
|
||||
|
||||
pub trait CsrfExt {
|
||||
fn csrf_token(self) -> (CsrfToken, Self);
|
||||
fn verify_form<T>(&self, form: ProtectedForm<T>) -> Result<T, CsrfError>;
|
||||
}
|
||||
|
||||
impl<K> CsrfExt for PrivateCookieJar<K> {
|
||||
@@ -108,4 +126,12 @@ impl<K> CsrfExt for PrivateCookieJar<K> {
|
||||
let jar = jar.add(cookie);
|
||||
(new_token, jar)
|
||||
}
|
||||
|
||||
fn verify_form<T>(&self, form: ProtectedForm<T>) -> Result<T, CsrfError> {
|
||||
let cookie = self.get("csrf").ok_or(CsrfError::Missing)?;
|
||||
let token: CsrfToken = cookie.decode()?;
|
||||
let token = token.verify_expiration()?;
|
||||
token.verify_form_value(&form.csrf)?;
|
||||
Ok(form.inner)
|
||||
}
|
||||
}
|
||||
|
@@ -50,7 +50,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fancy_error<E: Error + 'static>(templates: Templates) -> impl Fn(E) -> FancyError {
|
||||
pub fn fancy_error<E: std::fmt::Display + 'static>(
|
||||
templates: Templates,
|
||||
) -> impl Fn(E) -> FancyError {
|
||||
move |error: E| FancyError {
|
||||
templates: Some(templates.clone()),
|
||||
error: Box::new(error),
|
||||
@@ -69,7 +71,7 @@ where
|
||||
|
||||
pub struct FancyError {
|
||||
templates: Option<Templates>,
|
||||
error: Box<dyn Error>,
|
||||
error: Box<dyn std::fmt::Display>,
|
||||
}
|
||||
|
||||
impl IntoResponse for FancyError {
|
||||
@@ -99,4 +101,3 @@ impl IntoResponse for FancyError {
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user