2023-08-20 00:23:27 +02:00
|
|
|
use anyhow::Context;
|
|
|
|
use axum::extract::FromRef;
|
|
|
|
use openidconnect::IntrospectionUrl;
|
|
|
|
use zitadel::{
|
|
|
|
axum::introspection::IntrospectionStateBuilderError,
|
|
|
|
credentials::Application,
|
|
|
|
oidc::{discovery::discover, introspection::AuthorityAuthentication},
|
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct IntrospectionState {
|
|
|
|
pub(crate) config: IntrospectionConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(clap::Args, Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub struct IntrospectionConfigClap {
|
2023-08-20 01:15:11 +02:00
|
|
|
// #[arg(
|
|
|
|
// env = "ZITADEL_AUTHORITY",
|
|
|
|
// long = "zitadel-authority",
|
|
|
|
// group = "zitadel"
|
|
|
|
// )]
|
|
|
|
pub authority: Option<String>,
|
2023-08-20 00:23:27 +02:00
|
|
|
|
2023-08-20 01:15:11 +02:00
|
|
|
// #[arg(
|
|
|
|
// env = "ZITADEL_CLIENT_ID",
|
|
|
|
// long = "zitadel-client-id",
|
|
|
|
// group = "zitadel"
|
|
|
|
// )]
|
|
|
|
pub client_id: Option<String>,
|
|
|
|
// #[arg(
|
|
|
|
// env = "ZITADEL_CLIENT_SECRET",
|
|
|
|
// long = "zitadel-client-secret",
|
|
|
|
// group = "zitadel"
|
|
|
|
// )]
|
|
|
|
pub client_secret: Option<String>,
|
2023-08-20 00:23:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl IntrospectionConfigClap {
|
|
|
|
async fn try_into(self) -> anyhow::Result<IntrospectionState> {
|
2023-08-20 01:15:11 +02:00
|
|
|
IntrospectionStateBuilder::new(&self.authority.unwrap())
|
|
|
|
.with_basic_auth(&self.client_id.unwrap(), &self.client_secret.unwrap())
|
2023-08-20 00:23:27 +02:00
|
|
|
.build()
|
|
|
|
.await
|
|
|
|
.context("failed to generate an introspection builder")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Configuration that must be inject into the axum application state. Used by the
|
|
|
|
/// [IntrospectionStateBuilder](super::IntrospectionStateBuilder). This struct is also used to create the [IntrospectionState](IntrospectionState)
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct IntrospectionConfig {
|
|
|
|
pub authority: String,
|
|
|
|
pub authentication: AuthorityAuthentication,
|
|
|
|
pub introspection_uri: IntrospectionUrl,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromRef<IntrospectionState> for IntrospectionConfig {
|
|
|
|
fn from_ref(input: &IntrospectionState) -> Self {
|
|
|
|
input.config.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct IntrospectionStateBuilder {
|
|
|
|
authority: String,
|
|
|
|
authentication: Option<AuthorityAuthentication>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Builder for [IntrospectionConfig]
|
|
|
|
impl IntrospectionStateBuilder {
|
|
|
|
pub fn new(authority: &str) -> Self {
|
|
|
|
Self {
|
|
|
|
authority: authority.to_string(),
|
|
|
|
authentication: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_basic_auth(
|
|
|
|
&mut self,
|
|
|
|
client_id: &str,
|
|
|
|
client_secret: &str,
|
|
|
|
) -> &mut IntrospectionStateBuilder {
|
|
|
|
self.authentication = Some(AuthorityAuthentication::Basic {
|
|
|
|
client_id: client_id.to_string(),
|
|
|
|
client_secret: client_secret.to_string(),
|
|
|
|
});
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_jwt_profile(&mut self, application: Application) -> &mut IntrospectionStateBuilder {
|
|
|
|
self.authentication = Some(AuthorityAuthentication::JWTProfile { application });
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn build(&mut self) -> Result<IntrospectionState, IntrospectionStateBuilderError> {
|
|
|
|
let authentication = self
|
|
|
|
.authentication
|
|
|
|
.clone()
|
|
|
|
.ok_or(IntrospectionStateBuilderError::NoAuthSchema)?;
|
|
|
|
|
|
|
|
let metadata = discover(&self.authority)
|
|
|
|
.await
|
|
|
|
.map_err(|source| IntrospectionStateBuilderError::Discovery { source })?;
|
|
|
|
|
|
|
|
let introspection_uri = metadata
|
|
|
|
.additional_metadata()
|
|
|
|
.introspection_endpoint
|
|
|
|
.clone()
|
|
|
|
.ok_or(IntrospectionStateBuilderError::NoIntrospectionUrl)?;
|
|
|
|
|
|
|
|
Ok(IntrospectionState {
|
|
|
|
config: IntrospectionConfig {
|
|
|
|
authority: self.authority.clone(),
|
|
|
|
introspection_uri: introspection_uri,
|
|
|
|
authentication: authentication,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|