feat: with fmt
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
6ca2c54b10
commit
f1cff02673
@ -15,7 +15,7 @@ pub mod auth {
|
|||||||
use crate::{
|
use crate::{
|
||||||
introspection::IntrospectionService,
|
introspection::IntrospectionService,
|
||||||
login::{config::AuthEngine, AuthClap},
|
login::{config::AuthEngine, AuthClap},
|
||||||
oauth::{OAuth, ZitadelConfig},
|
oauth::{zitadel::ZitadelConfig, OAuth},
|
||||||
session::{SessionService, User},
|
session::{SessionService, User},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ pub struct AuthClap {
|
|||||||
pub mod config {
|
pub mod config {
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::oauth::{OAuth, ZitadelConfig};
|
use crate::oauth::{zitadel::ZitadelConfig, OAuth};
|
||||||
|
|
||||||
use super::AuthClap;
|
use super::AuthClap;
|
||||||
|
|
||||||
|
@ -2,20 +2,13 @@ use std::{ops::Deref, sync::Arc};
|
|||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use oauth2::{
|
use oauth2::url::Url;
|
||||||
basic::BasicClient, reqwest::async_http_client, url::Url, AuthUrl, AuthorizationCode, ClientId,
|
|
||||||
ClientSecret, CsrfToken, RedirectUrl, Scope, TokenResponse, TokenUrl,
|
use self::{
|
||||||
|
noop::NoopOAuthClient,
|
||||||
|
zitadel::{ZitadelConfig, ZitadelOAuthClient},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::login::config::ZitadelClap;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait OAuthClient {
|
|
||||||
async fn get_token(&self) -> anyhow::Result<()>;
|
|
||||||
async fn authorize_url(&self) -> anyhow::Result<Url>;
|
|
||||||
async fn exchange(&self, code: &str) -> anyhow::Result<String>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct OAuth(Arc<dyn OAuthClient + Send + Sync + 'static>);
|
pub struct OAuth(Arc<dyn OAuthClient + Send + Sync + 'static>);
|
||||||
|
|
||||||
impl OAuth {
|
impl OAuth {
|
||||||
@ -35,143 +28,15 @@ impl Deref for OAuth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ZitadelConfig> for OAuth {
|
|
||||||
fn from(value: ZitadelConfig) -> Self {
|
|
||||||
Self::new_zitadel(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- Noop
|
|
||||||
#[derive(clap::Args, Clone)]
|
|
||||||
pub struct NoopOAuthClient;
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl OAuthClient for NoopOAuthClient {
|
pub trait OAuthClient {
|
||||||
async fn get_token(&self) -> anyhow::Result<()> {
|
async fn get_token(&self) -> anyhow::Result<()>;
|
||||||
Ok(())
|
async fn authorize_url(&self) -> anyhow::Result<Url>;
|
||||||
}
|
async fn exchange(&self, code: &str) -> anyhow::Result<String>;
|
||||||
async fn authorize_url(&self) -> anyhow::Result<Url> {
|
|
||||||
Ok(Url::parse("http://localhost:3000/auth/zitadel").unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn exchange(&self, _code: &str) -> anyhow::Result<String> {
|
|
||||||
Ok(String::new())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Zitadel
|
pub mod noop;
|
||||||
|
pub mod zitadel;
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ZitadelConfig {
|
|
||||||
auth_url: String,
|
|
||||||
client_id: String,
|
|
||||||
client_secret: String,
|
|
||||||
redirect_url: String,
|
|
||||||
token_url: String,
|
|
||||||
authority_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>,
|
|
||||||
authority_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(),
|
|
||||||
authority_url: authority_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,
|
|
||||||
value.authority_url,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<ZitadelClap> for ZitadelConfig {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
|
|
||||||
fn try_from(value: ZitadelClap) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Self {
|
|
||||||
auth_url: value
|
|
||||||
.auth_url
|
|
||||||
.ok_or(anyhow::anyhow!("auth_url was not set"))?,
|
|
||||||
client_id: value
|
|
||||||
.client_id
|
|
||||||
.ok_or(anyhow::anyhow!("client_id was not set"))?,
|
|
||||||
client_secret: value
|
|
||||||
.client_secret
|
|
||||||
.ok_or(anyhow::anyhow!("client_secret was not set"))?,
|
|
||||||
redirect_url: value
|
|
||||||
.redirect_url
|
|
||||||
.ok_or(anyhow::anyhow!("redirect_url was not set"))?,
|
|
||||||
token_url: value
|
|
||||||
.token_url
|
|
||||||
.ok_or(anyhow::anyhow!("token_url was not set"))?,
|
|
||||||
authority_url: value
|
|
||||||
.authority_url
|
|
||||||
.ok_or(anyhow::anyhow!("authority_url was not set"))?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl OAuthClient for ZitadelOAuthClient {
|
|
||||||
async fn get_token(&self) -> anyhow::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
async fn authorize_url(&self) -> anyhow::Result<Url> {
|
|
||||||
let (auth_url, _csrf_token) = self
|
|
||||||
.client
|
|
||||||
.authorize_url(CsrfToken::new_random)
|
|
||||||
.add_scope(Scope::new("identify".to_string()))
|
|
||||||
.add_scope(Scope::new("openid".to_string()))
|
|
||||||
.url();
|
|
||||||
|
|
||||||
Ok(auth_url)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn exchange(&self, code: &str) -> anyhow::Result<String> {
|
|
||||||
let token = self
|
|
||||||
.client
|
|
||||||
.exchange_code(AuthorizationCode::new(code.to_string()))
|
|
||||||
.request_async(async_http_client)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(token.access_token().secret().clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
20
crates/nefarious-login/src/oauth/noop.rs
Normal file
20
crates/nefarious-login/src/oauth/noop.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
use oauth2::url::Url;
|
||||||
|
|
||||||
|
use super::OAuthClient;
|
||||||
|
|
||||||
|
#[derive(clap::Args, Clone)]
|
||||||
|
pub struct NoopOAuthClient;
|
||||||
|
#[async_trait]
|
||||||
|
impl OAuthClient for NoopOAuthClient {
|
||||||
|
async fn get_token(&self) -> anyhow::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
async fn authorize_url(&self) -> anyhow::Result<Url> {
|
||||||
|
Ok(Url::parse("http://localhost:3000/auth/zitadel").unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn exchange(&self, _code: &str) -> anyhow::Result<String> {
|
||||||
|
Ok(String::new())
|
||||||
|
}
|
||||||
|
}
|
129
crates/nefarious-login/src/oauth/zitadel.rs
Normal file
129
crates/nefarious-login/src/oauth/zitadel.rs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
impl From<ZitadelConfig> for OAuth {
|
||||||
|
fn from(value: ZitadelConfig) -> Self {
|
||||||
|
Self::new_zitadel(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use oauth2::{
|
||||||
|
basic::BasicClient, reqwest::async_http_client, url::Url, AuthUrl, AuthorizationCode, ClientId,
|
||||||
|
ClientSecret, CsrfToken, RedirectUrl, Scope, TokenResponse, TokenUrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::login::config::ZitadelClap;
|
||||||
|
|
||||||
|
use super::{OAuth, OAuthClient};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ZitadelConfig {
|
||||||
|
auth_url: String,
|
||||||
|
client_id: String,
|
||||||
|
client_secret: String,
|
||||||
|
redirect_url: String,
|
||||||
|
token_url: String,
|
||||||
|
authority_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>,
|
||||||
|
authority_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(),
|
||||||
|
authority_url: authority_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,
|
||||||
|
value.authority_url,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<ZitadelClap> for ZitadelConfig {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: ZitadelClap) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
auth_url: value
|
||||||
|
.auth_url
|
||||||
|
.ok_or(anyhow::anyhow!("auth_url was not set"))?,
|
||||||
|
client_id: value
|
||||||
|
.client_id
|
||||||
|
.ok_or(anyhow::anyhow!("client_id was not set"))?,
|
||||||
|
client_secret: value
|
||||||
|
.client_secret
|
||||||
|
.ok_or(anyhow::anyhow!("client_secret was not set"))?,
|
||||||
|
redirect_url: value
|
||||||
|
.redirect_url
|
||||||
|
.ok_or(anyhow::anyhow!("redirect_url was not set"))?,
|
||||||
|
token_url: value
|
||||||
|
.token_url
|
||||||
|
.ok_or(anyhow::anyhow!("token_url was not set"))?,
|
||||||
|
authority_url: value
|
||||||
|
.authority_url
|
||||||
|
.ok_or(anyhow::anyhow!("authority_url was not set"))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl OAuthClient for ZitadelOAuthClient {
|
||||||
|
async fn get_token(&self) -> anyhow::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
async fn authorize_url(&self) -> anyhow::Result<Url> {
|
||||||
|
let (auth_url, _csrf_token) = self
|
||||||
|
.client
|
||||||
|
.authorize_url(CsrfToken::new_random)
|
||||||
|
.add_scope(Scope::new("identify".to_string()))
|
||||||
|
.add_scope(Scope::new("openid".to_string()))
|
||||||
|
.url();
|
||||||
|
|
||||||
|
Ok(auth_url)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn exchange(&self, code: &str) -> anyhow::Result<String> {
|
||||||
|
let token = self
|
||||||
|
.client
|
||||||
|
.exchange_code(AuthorizationCode::new(code.to_string()))
|
||||||
|
.request_async(async_http_client)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(token.access_token().secret().clone())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user