feat(auth): add base oauth client
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
9d064a1287
commit
5e879b7ef2
33
como_auth/Cargo.toml
Normal file
33
como_auth/Cargo.toml
Normal file
@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "como_auth"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
como_gql.workspace = true
|
||||
como_core.workspace = true
|
||||
como_domain.workspace = true
|
||||
como_infrastructure.workspace = true
|
||||
|
||||
async-trait.workspace = true
|
||||
async-graphql.workspace = true
|
||||
async-graphql-axum.workspace = true
|
||||
axum.workspace = true
|
||||
axum-extra.workspace = true
|
||||
axum-sessions.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
uuid.workspace = true
|
||||
sqlx.workspace = true
|
||||
anyhow.workspace = true
|
||||
tracing.workspace = true
|
||||
async-sqlx-session.workspace = true
|
||||
|
||||
zitadel = { version = "3.3.1", features = ["axum"] }
|
||||
tower = "0.4.13"
|
||||
tower-http = { version = "0.4.0", features = ["cors", "trace"] }
|
||||
oauth2 = "4.4.0"
|
||||
openidconnect = "3.0.0"
|
1
como_auth/src/lib.rs
Normal file
1
como_auth/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
mod oauth;
|
143
como_auth/src/oauth.rs
Normal file
143
como_auth/src/oauth.rs
Normal file
@ -0,0 +1,143 @@
|
||||
use async_trait::async_trait;
|
||||
use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, RedirectUrl, TokenUrl};
|
||||
use std::{env, ops::Deref, sync::Arc};
|
||||
|
||||
#[async_trait]
|
||||
pub trait OAuthClient {
|
||||
async fn get_token(&self) -> anyhow::Result<()>;
|
||||
}
|
||||
|
||||
pub struct OAuth(Arc<dyn OAuthClient + Send + Sync + 'static>);
|
||||
|
||||
impl OAuth {
|
||||
pub fn new_zitadel(config: ZitadelConfig) -> Self {
|
||||
Self(Arc::new(ZitadelOAuthClient::from(config)))
|
||||
}
|
||||
pub fn new_noop() -> Self {
|
||||
Self(Arc::new(NoopOAuthClient {}))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum OAuthConfig {
|
||||
Zitadel(ZitadelConfig),
|
||||
Noop,
|
||||
}
|
||||
|
||||
impl From<OAuthConfig> for OAuth {
|
||||
fn from(value: OAuthConfig) -> Self {
|
||||
match value {
|
||||
OAuthConfig::Zitadel(c) => c.into(),
|
||||
OAuthConfig::Noop => Self::new_noop(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OAuth {
|
||||
type Target = Arc<dyn OAuthClient + Send + Sync + 'static>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ZitadelConfig> for OAuth {
|
||||
fn from(value: ZitadelConfig) -> Self {
|
||||
Self::new_zitadel(value)
|
||||
}
|
||||
}
|
||||
|
||||
// -- Noop
|
||||
pub struct NoopOAuthClient;
|
||||
#[async_trait]
|
||||
impl OAuthClient for NoopOAuthClient {
|
||||
async fn get_token(&self) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// -- Zitadel
|
||||
|
||||
pub struct ZitadelConfig {
|
||||
client_id: String,
|
||||
client_secret: String,
|
||||
redirect_url: String,
|
||||
auth_url: String,
|
||||
token_url: String,
|
||||
}
|
||||
|
||||
pub struct ZitadelOAuthClient {
|
||||
client: BasicClient,
|
||||
}
|
||||
|
||||
impl ZitadelOAuthClient {
|
||||
pub fn new(
|
||||
client_id: impl Into<String>,
|
||||
client_secret: impl Into<String>,
|
||||
redirect_url: impl Into<String>,
|
||||
auth_url: impl Into<String>,
|
||||
token_url: impl Into<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
client: Self::oauth_client(ZitadelConfig {
|
||||
client_id: client_id.into(),
|
||||
client_secret: client_secret.into(),
|
||||
redirect_url: redirect_url.into(),
|
||||
auth_url: auth_url.into(),
|
||||
token_url: token_url.into(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
fn oauth_client(config: ZitadelConfig) -> BasicClient {
|
||||
BasicClient::new(
|
||||
ClientId::new(config.client_id),
|
||||
Some(ClientSecret::new(config.client_secret)),
|
||||
AuthUrl::new(config.auth_url).unwrap(),
|
||||
Some(TokenUrl::new(config.token_url).unwrap()),
|
||||
)
|
||||
.set_redirect_uri(RedirectUrl::new(config.redirect_url).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ZitadelConfig> for ZitadelOAuthClient {
|
||||
fn from(value: ZitadelConfig) -> Self {
|
||||
Self::new(
|
||||
value.client_id,
|
||||
value.client_secret,
|
||||
value.redirect_url,
|
||||
value.auth_url,
|
||||
value.token_url,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl OAuthClient for ZitadelOAuthClient {
|
||||
async fn get_token(&self) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::oauth::{OAuth, OAuthConfig, ZitadelConfig};
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_noop() {
|
||||
OAuth::from(OAuthConfig::Noop).get_token().await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_zitadel() {
|
||||
OAuth::from(OAuthConfig::Zitadel(ZitadelConfig {
|
||||
client_id: "something".into(),
|
||||
client_secret: "something".into(),
|
||||
redirect_url: "https://something".into(),
|
||||
auth_url: "https://something".into(),
|
||||
token_url: "https://something".into(),
|
||||
}))
|
||||
.get_token()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user