You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-11-21 23:00:50 +03:00
Use axum-extra's PrivateCookieJar
This commit is contained in:
@@ -14,113 +14,10 @@
|
||||
|
||||
//! Private (encrypted) cookie jar, based on axum-extra's cookie jar
|
||||
|
||||
use std::{convert::Infallible, marker::PhantomData};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use axum::{
|
||||
extract::{Extension, FromRequest, RequestParts},
|
||||
response::IntoResponseParts,
|
||||
};
|
||||
pub use cookie::Cookie;
|
||||
use data_encoding::BASE64URL_NOPAD;
|
||||
use headers::HeaderMap;
|
||||
use http::header::{COOKIE, SET_COOKIE};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
pub struct PrivateCookieJar<K = cookie::Key> {
|
||||
jar: cookie::CookieJar,
|
||||
key: cookie::Key,
|
||||
_marker: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<K> PrivateCookieJar<K> {
|
||||
pub fn get(&self, name: &str) -> Option<Cookie<'static>> {
|
||||
self.private_jar().get(name)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn remove(mut self, cookie: Cookie<'static>) -> Self {
|
||||
self.private_jar_mut().remove(cookie);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn add(mut self, cookie: Cookie<'static>) -> Self {
|
||||
self.private_jar_mut().add(cookie);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn decrypt(&self, cookie: Cookie<'static>) -> Option<Cookie<'static>> {
|
||||
self.private_jar().decrypt(cookie)
|
||||
}
|
||||
|
||||
fn private_jar(&self) -> cookie::PrivateJar<&'_ cookie::CookieJar> {
|
||||
self.jar.private(&self.key)
|
||||
}
|
||||
|
||||
fn private_jar_mut(&mut self) -> cookie::PrivateJar<&'_ mut cookie::CookieJar> {
|
||||
self.jar.private_mut(&self.key)
|
||||
}
|
||||
|
||||
pub fn set_cookies(self, headers: &mut HeaderMap) {
|
||||
for cookie in self.jar.delta() {
|
||||
if let Ok(header_value) = cookie.encoded().to_string().parse() {
|
||||
headers.append(SET_COOKIE, header_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<B, K> FromRequest<B> for PrivateCookieJar<K>
|
||||
where
|
||||
B: Send,
|
||||
K: Into<cookie::Key> + Clone + Send + Sync + 'static,
|
||||
{
|
||||
type Rejection = <Extension<K> as FromRequest<B>>::Rejection;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let Extension(key): Extension<K> = Extension::from_request(req).await?;
|
||||
let key = key.into();
|
||||
|
||||
let mut jar = cookie::CookieJar::new();
|
||||
let mut private_jar = jar.private_mut(&key);
|
||||
|
||||
let cookies = req
|
||||
.headers()
|
||||
.get_all(COOKIE)
|
||||
.into_iter()
|
||||
.filter_map(|value| value.to_str().ok())
|
||||
.flat_map(|value| value.split(';'))
|
||||
.filter_map(|cookie| Cookie::parse_encoded(cookie.to_owned()).ok());
|
||||
|
||||
for cookie in cookies {
|
||||
if let Some(cookie) = private_jar.decrypt(cookie) {
|
||||
private_jar.add_original(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
jar,
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<K> IntoResponseParts for PrivateCookieJar<K> {
|
||||
type Error = Infallible;
|
||||
fn into_response_parts(
|
||||
self,
|
||||
mut res: axum::response::ResponseParts,
|
||||
) -> Result<axum::response::ResponseParts, Self::Error> {
|
||||
self.set_cookies(res.headers_mut());
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("could not decode cookie")]
|
||||
pub enum CookieDecodeError {
|
||||
@@ -138,7 +35,7 @@ pub trait CookieExt {
|
||||
T: Serialize;
|
||||
}
|
||||
|
||||
impl<'a> CookieExt for Cookie<'a> {
|
||||
impl<'a> CookieExt for axum_extra::extract::cookie::Cookie<'a> {
|
||||
fn decode<T>(&self) -> Result<T, CookieDecodeError>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
|
||||
Reference in New Issue
Block a user