diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/driver/auth.rs | 39 | ||||
| -rw-r--r-- | src/server/driver/mod.rs | 50 | ||||
| -rw-r--r-- | src/server/mod.rs | 2 | ||||
| -rw-r--r-- | src/server/routes/auth/discord.rs | 8 | ||||
| -rw-r--r-- | src/server/routes/auth/mod.rs | 8 | ||||
| -rw-r--r-- | src/server/state/mod.rs | 6 |
6 files changed, 106 insertions, 7 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()))) + } } diff --git a/src/server/mod.rs b/src/server/mod.rs index 2050758..7357957 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -7,7 +7,7 @@ pub mod state; use std::time::Duration; -use activitypub_federation::config::{FederationConfig, FederationMiddleware}; +use activitypub_federation::config::FederationMiddleware; use axum::{ Router, http::{HeaderName, StatusCode}, diff --git a/src/server/routes/auth/discord.rs b/src/server/routes/auth/discord.rs index b141ce7..b0305f6 100644 --- a/src/server/routes/auth/discord.rs +++ b/src/server/routes/auth/discord.rs @@ -12,6 +12,12 @@ pub(super) async fn discord_auth(data: Data<AppState>) -> Result<impl IntoRespon .authorize_url(CsrfToken::new_random) .add_scope(Scope::new("identify".to_string())) .url(); + dbg!(&auth_url); - Ok(String::default()) + let response = data + .driver + .create_auth_session(&csrf_token, &auth_url) + .await?; + + Ok(response) } diff --git a/src/server/routes/auth/mod.rs b/src/server/routes/auth/mod.rs index b80c565..f0da7cd 100644 --- a/src/server/routes/auth/mod.rs +++ b/src/server/routes/auth/mod.rs @@ -50,10 +50,14 @@ pub struct OAuthDoc; ) )] #[axum::debug_handler] +#[cfg(feature = "oauth")] pub async fn auth( Query(params): Query<Params>, data: Data<AppState>, ) -> Result<impl IntoResponse, AppError> { - dbg!(¶ms); - Ok(String::default()) + + match params.provider { + #[cfg(feature = "oauth-discord")] + OauthProvider::Discord => discord::discord_auth(data), + }.await } diff --git a/src/server/state/mod.rs b/src/server/state/mod.rs index 03e8c70..c86052d 100644 --- a/src/server/state/mod.rs +++ b/src/server/state/mod.rs @@ -6,19 +6,20 @@ use std::sync::Arc; #[cfg(feature = "oauth-discord")] use url::Url; +use crate::{config::Config, server::driver::SellershutDriver}; #[cfg(feature = "oauth-discord")] use crate::{config::DiscordOauth, server::driver::auth::OauthClient}; -use crate::{config::Config, server::driver::SellershutDriver}; #[derive(Clone)] pub struct AppState { - driver: Arc<dyn SellershutDriver>, + pub driver: Arc<dyn SellershutDriver>, #[cfg(feature = "oauth-discord")] pub oauth_discord: OauthClient, } impl AppState { pub async fn new(config: &Config, driver: impl SellershutDriver) -> anyhow::Result<Self> { + dbg!(&config); Ok(Self { driver: Arc::new(driver), #[cfg(feature = "oauth-discord")] @@ -30,6 +31,7 @@ impl AppState { #[cfg(feature = "oauth-discord")] fn discord_client(disc: &DiscordOauth, redirect: &Url) -> anyhow::Result<OauthClient> { use crate::server::driver::{self, auth::ClientOptions}; + dbg!(&disc); let discord_opts = ClientOptions::builder() .client_id(disc.client_id.to_owned()) |
