diff options
Diffstat (limited to 'src/server/driver')
| -rw-r--r-- | src/server/driver/auth.rs | 39 | ||||
| -rw-r--r-- | src/server/driver/mod.rs | 50 |
2 files changed, 88 insertions, 1 deletions
diff --git a/src/server/driver/auth.rs b/src/server/driver/auth.rs index 9215372..28e9285 100644 --- a/src/server/driver/auth.rs +++ b/src/server/driver/auth.rs @@ -1,8 +1,17 @@ +use anyhow::Result; +use async_session::{Session, SessionStore}; +use async_trait::async_trait; use bon::Builder; use oauth2::{AuthUrl, ClientId, ClientSecret, EndpointNotSet, EndpointSet, RedirectUrl, TokenUrl}; use secrecy::{ExposeSecret, SecretString}; +use tracing::{instrument, trace}; -#[derive(Builder)] +use crate::server::driver::Services; + +pub(super) static COOKIE_NAME: &str = "SESSION"; +pub(super) static CSRF_TOKEN: &str = "csrf_token"; + +#[derive(Builder, Debug)] pub struct ClientOptions { client_id: String, client_secret: SecretString, @@ -20,6 +29,7 @@ pub type OauthClient = oauth2::basic::BasicClient< >; pub fn oauth_client(opts: &ClientOptions) -> anyhow::Result<OauthClient> { + dbg!(&opts); let redirect_url = RedirectUrl::new(opts.redirect_url.to_owned())?; let client_id = ClientId::new(opts.client_id.to_owned()); let auth_url = AuthUrl::new(opts.auth_url.to_owned())?; @@ -32,3 +42,30 @@ pub fn oauth_client(opts: &ClientOptions) -> anyhow::Result<OauthClient> { .set_token_uri(token_url) .set_redirect_uri(redirect_url)) } + +#[async_trait] +impl SessionStore for Services { + #[instrument(skip(self))] + async fn load_session(&self, cookie_value: String) -> Result<Option<Session>> { + let id = Session::id_from_cookie_value(&cookie_value)?; + let mut connection = self.database.acquire().await?; + + todo!() + } + + #[instrument(skip(self, session), fields(id = session.id()))] + async fn store_session(&self, session: Session) -> Result<Option<String>> { + let id = session.id(); + trace!("storing session"); + let mut connection = self.database.acquire().await?; + Ok(session.into_cookie_value()) + } + + async fn destroy_session(&self, session: Session) -> Result<()> { + todo!() + } + + async fn clear_store(&self) -> Result<()> { + todo!() + } +} diff --git a/src/server/driver/mod.rs b/src/server/driver/mod.rs index c006cb0..2debff2 100644 --- a/src/server/driver/mod.rs +++ b/src/server/driver/mod.rs @@ -1,11 +1,21 @@ #[cfg(feature = "oauth")] pub mod auth; +#[cfg(feature = "oauth")] +use async_session::Session; use async_trait::async_trait; +#[cfg(feature = "oauth")] +use axum::{ + http::HeaderMap, + response::{IntoResponse, Redirect}, +}; +#[cfg(feature = "oauth")] +use oauth2::CsrfToken; use sqlx::PgPool; use crate::{config::DatabaseOptions, server::state::database}; +#[derive(Debug, Clone)] pub struct Services { database: PgPool, // oauth: OauthClient, @@ -22,6 +32,13 @@ impl Services { #[async_trait] pub trait SellershutDriver: Send + Sync + 'static { async fn hello(&self); + + #[cfg(feature = "oauth")] + async fn create_auth_session( + &self, + csrf_token: &CsrfToken, + auth_url: &url::Url, + ) -> anyhow::Result<(HeaderMap, Redirect)>; } #[async_trait] @@ -29,4 +46,37 @@ impl SellershutDriver for Services { async fn hello(&self) { todo!() } + + #[cfg(feature = "oauth")] + async fn create_auth_session( + &self, + csrf_token: &CsrfToken, + auth_url: &url::Url, + ) -> anyhow::Result<(HeaderMap, Redirect)> { + use anyhow::Context; + use async_session::SessionStore; + use axum::{ + http::{HeaderMap, header::SET_COOKIE}, + response::Redirect, + }; + + use crate::server::driver::auth::{COOKIE_NAME, CSRF_TOKEN}; + + let mut session = Session::new(); + session.insert(CSRF_TOKEN, csrf_token)?; + + let res = self + .store_session(session) + .await? + .context("missing csrf token")?; + + let cookie = format!("{COOKIE_NAME}={res}; SameSite=Lax; HttpOnly; Secure; Path=/"); + let mut headers = HeaderMap::new(); + headers.insert( + SET_COOKIE, + cookie.parse().context("failed to parse cookie")?, + ); + + Ok((headers, Redirect::to(auth_url.as_str()))) + } } |
