feat: with clap example
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
32d8030f24
commit
89acf8c343
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -520,7 +520,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
"clap",
|
"clap 4.4.6",
|
||||||
"nefarious-login",
|
"nefarious-login",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@ -660,6 +660,18 @@ dependencies = [
|
|||||||
"inout",
|
"inout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"axum",
|
||||||
|
"clap 4.4.6",
|
||||||
|
"nefarious-login",
|
||||||
|
"tokio",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.4.6"
|
version = "4.4.6"
|
||||||
@ -1876,7 +1888,7 @@ dependencies = [
|
|||||||
"axum",
|
"axum",
|
||||||
"axum-extra 0.7.7",
|
"axum-extra 0.7.7",
|
||||||
"axum-sessions",
|
"axum-sessions",
|
||||||
"clap",
|
"clap 4.4.6",
|
||||||
"oauth2",
|
"oauth2",
|
||||||
"openidconnect",
|
"openidconnect",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
|
@ -88,7 +88,7 @@ impl Auth for ZitadelAuthService {
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
headers,
|
headers,
|
||||||
Url::parse("http://localhost:3000/dash/home")
|
Url::parse("http://localhost:3001/authed")
|
||||||
.context("failed to parse login_authorized zitadel return url")?,
|
.context("failed to parse login_authorized zitadel return url")?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -50,11 +50,8 @@ pub mod config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(clap::Args, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(clap::Args, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[group(requires_all = ["auth_url", "client_id", "client_secret", "redirect_url", "token_url", "authority_url"])]
|
#[group(requires_all = ["client_id", "client_secret", "redirect_url", "authority_url"])]
|
||||||
pub struct ZitadelClap {
|
pub struct ZitadelClap {
|
||||||
#[arg(env = "ZITADEL_AUTH_URL", long = "zitadel-auth-url")]
|
|
||||||
pub auth_url: Option<String>,
|
|
||||||
|
|
||||||
#[arg(env = "ZITADEL_CLIENT_ID", long = "zitadel-client-id")]
|
#[arg(env = "ZITADEL_CLIENT_ID", long = "zitadel-client-id")]
|
||||||
pub client_id: Option<String>,
|
pub client_id: Option<String>,
|
||||||
|
|
||||||
@ -66,9 +63,6 @@ pub mod config {
|
|||||||
|
|
||||||
#[arg(env = "ZITADEL_AUTHORITY_URL", long = "zitadel-authority-url")]
|
#[arg(env = "ZITADEL_AUTHORITY_URL", long = "zitadel-authority-url")]
|
||||||
pub authority_url: Option<String>,
|
pub authority_url: Option<String>,
|
||||||
|
|
||||||
#[arg(env = "ZITADEL_TOKEN_URL", long = "zitadel-token-url")]
|
|
||||||
pub token_url: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<AuthClap> for OAuth {
|
impl TryFrom<AuthClap> for OAuth {
|
||||||
@ -85,11 +79,6 @@ pub mod config {
|
|||||||
impl AuthClap {
|
impl AuthClap {
|
||||||
pub fn merge(&mut self, config: AuthConfigFile) -> &mut Self {
|
pub fn merge(&mut self, config: AuthConfigFile) -> &mut Self {
|
||||||
if let Some(zitadel) = config.zitadel {
|
if let Some(zitadel) = config.zitadel {
|
||||||
if let Some(auth_url) = zitadel.auth_url {
|
|
||||||
if self.zitadel.auth_url.is_some() {
|
|
||||||
_ = self.zitadel.auth_url.replace(auth_url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(client_id) = zitadel.client_id {
|
if let Some(client_id) = zitadel.client_id {
|
||||||
if self.zitadel.client_id.is_some() {
|
if self.zitadel.client_id.is_some() {
|
||||||
_ = self.zitadel.client_id.replace(client_id);
|
_ = self.zitadel.client_id.replace(client_id);
|
||||||
@ -110,11 +99,6 @@ pub mod config {
|
|||||||
_ = self.zitadel.authority_url.replace(authority_url);
|
_ = self.zitadel.authority_url.replace(authority_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(token_url) = zitadel.token_url {
|
|
||||||
if self.zitadel.token_url.is_some() {
|
|
||||||
_ = self.zitadel.token_url.replace(token_url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -78,10 +78,14 @@ impl TryFrom<ZitadelClap> for ZitadelConfig {
|
|||||||
type Error = anyhow::Error;
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
fn try_from(value: ZitadelClap) -> Result<Self, Self::Error> {
|
fn try_from(value: ZitadelClap) -> Result<Self, Self::Error> {
|
||||||
|
let authority_url = value
|
||||||
|
.authority_url
|
||||||
|
.ok_or(anyhow::anyhow!("authority_url was not set"))?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
auth_url: value
|
auth_url: format!("{}/oauth/v2/authorize", &authority_url),
|
||||||
.auth_url
|
token_url: format!("{}/oauth/v2/token", &authority_url),
|
||||||
.ok_or(anyhow::anyhow!("auth_url was not set"))?,
|
authority_url,
|
||||||
client_id: value
|
client_id: value
|
||||||
.client_id
|
.client_id
|
||||||
.ok_or(anyhow::anyhow!("client_id was not set"))?,
|
.ok_or(anyhow::anyhow!("client_id was not set"))?,
|
||||||
@ -91,12 +95,6 @@ impl TryFrom<ZitadelClap> for ZitadelConfig {
|
|||||||
redirect_url: value
|
redirect_url: value
|
||||||
.redirect_url
|
.redirect_url
|
||||||
.ok_or(anyhow::anyhow!("redirect_url was not set"))?,
|
.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"))?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,15 @@ use axum::{
|
|||||||
use nefarious_login::{
|
use nefarious_login::{
|
||||||
auth::AuthService,
|
auth::AuthService,
|
||||||
axum::{AuthController, UserFromSession},
|
axum::{AuthController, UserFromSession},
|
||||||
|
introspection::IntrospectionService,
|
||||||
|
login::{
|
||||||
|
config::{AuthEngine, ZitadelClap},
|
||||||
|
AuthClap,
|
||||||
|
},
|
||||||
|
oauth::OAuth,
|
||||||
|
session::{PostgresqlSessionClap, SessionBackend, SessionService},
|
||||||
};
|
};
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct AppState {
|
struct AppState {
|
||||||
@ -18,10 +26,33 @@ struct AppState {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
tracing_subscriber::fmt().init();
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
|
.init();
|
||||||
|
|
||||||
// Change to zitadel test instance
|
let auth = AuthClap {
|
||||||
let auth_service = AuthService::new_noop();
|
engine: AuthEngine::Zitadel,
|
||||||
|
session_backend: SessionBackend::Postgresql,
|
||||||
|
zitadel: ZitadelClap {
|
||||||
|
authority_url: Some("https://personal-wxuujs.zitadel.cloud".into()),
|
||||||
|
client_id: Some("237412977047895154@nefarious-test".into()),
|
||||||
|
client_secret: Some(
|
||||||
|
"rWwDi8gjNOyuMFKoOjNSlhjcVZ1B25wDh6HsDL27f0g2Hb0xGbvEf0WXFY2akOlL".into(),
|
||||||
|
),
|
||||||
|
redirect_url: Some("http://localhost:3001/auth/authorized".into()),
|
||||||
|
},
|
||||||
|
session: nefarious_login::session::SessionClap {
|
||||||
|
postgresql: PostgresqlSessionClap {
|
||||||
|
conn: Some("postgres://como:somenotverysecurepassword@localhost:5432/como".into()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let auth_service = AuthService::new_zitadel(
|
||||||
|
OAuth::try_from(auth.clone())?,
|
||||||
|
IntrospectionService::new_zitadel(&auth).await?,
|
||||||
|
SessionService::new(&auth).await?,
|
||||||
|
);
|
||||||
|
|
||||||
let state = AppState {
|
let state = AppState {
|
||||||
auth: auth_service.clone(),
|
auth: auth_service.clone(),
|
||||||
@ -35,6 +66,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3001));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3001));
|
||||||
println!("listening on: {addr}");
|
println!("listening on: {addr}");
|
||||||
|
println!("open browser at: http://localhost:3001/auth/zitadel");
|
||||||
axum::Server::bind(&addr)
|
axum::Server::bind(&addr)
|
||||||
.serve(app.into_make_service())
|
.serve(app.into_make_service())
|
||||||
.await
|
.await
|
||||||
|
16
examples/clap/Cargo.toml
Normal file
16
examples/clap/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "clap"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nefarious-login.workspace = true
|
||||||
|
|
||||||
|
tokio.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
|
axum.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
|
||||||
|
tracing-subscriber.workspace = true
|
88
examples/clap/src/main.rs
Normal file
88
examples/clap/src/main.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
extract::{FromRef, State},
|
||||||
|
response::IntoResponse,
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
use clap::Parser;
|
||||||
|
use nefarious_login::{
|
||||||
|
auth::AuthService,
|
||||||
|
axum::{AuthController, UserFromSession},
|
||||||
|
login::AuthClap,
|
||||||
|
session::SessionService,
|
||||||
|
};
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct AppState {
|
||||||
|
auth: AuthService,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Parser)]
|
||||||
|
struct Command {
|
||||||
|
#[clap(flatten)]
|
||||||
|
auth: AuthClap,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
|
.init();
|
||||||
|
|
||||||
|
let cmd = Command::parse_from(vec![
|
||||||
|
"base",
|
||||||
|
"--auth-engine=zitadel",
|
||||||
|
"--zitadel-authority-url=https://personal-wxuujs.zitadel.cloud",
|
||||||
|
"--zitadel-redirect-url=http://localhost:3001/auth/authorized",
|
||||||
|
"--zitadel-client-id=237412977047895154@nefarious-test",
|
||||||
|
"--zitadel-client-secret=rWwDi8gjNOyuMFKoOjNSlhjcVZ1B25wDh6HsDL27f0g2Hb0xGbvEf0WXFY2akOlL",
|
||||||
|
"--session-backend=postgresql",
|
||||||
|
"--session-postgres-conn=postgres://como:somenotverysecurepassword@localhost:5432/como",
|
||||||
|
]);
|
||||||
|
|
||||||
|
let auth = cmd.auth;
|
||||||
|
|
||||||
|
let session_service = SessionService::new(&auth).await?;
|
||||||
|
let auth_service = AuthService::new(&auth, session_service).await?;
|
||||||
|
|
||||||
|
let state = AppState {
|
||||||
|
auth: auth_service.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/unauthed", get(unauthed))
|
||||||
|
.route("/authed", get(authed))
|
||||||
|
.with_state(state)
|
||||||
|
.nest("/auth", AuthController::new_router(auth_service).await?);
|
||||||
|
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3001));
|
||||||
|
println!("listening on: {addr}");
|
||||||
|
println!("open browser at: http://localhost:3001/auth/zitadel");
|
||||||
|
axum::Server::bind(&addr)
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRef<AppState> for AuthService {
|
||||||
|
fn from_ref(input: &AppState) -> Self {
|
||||||
|
input.auth.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn unauthed() -> String {
|
||||||
|
"Hello Unauthorized User".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[axum::debug_handler()]
|
||||||
|
async fn authed(
|
||||||
|
user: UserFromSession,
|
||||||
|
State(_auth_service): State<AuthService>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
format!("Hello authorized user: {:?}", user.user.id)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user