use log::{debug, error};
use openidconnect::{
AdditionalClaims, AdditionalProviderMetadata, Client, EndpointMaybeSet,
EndpointNotSet, EndpointSet, ExtraTokenFields, IdTokenClaims,
IdTokenFields, ProviderMetadata, StandardErrorResponse,
StandardTokenResponse, UserInfoClaims,
core::{
CoreAuthDisplay, CoreAuthPrompt, CoreClaimName, CoreClaimType,
CoreClientAuthMethod, CoreErrorResponseType, CoreGenderClaim,
CoreGrantType, CoreJsonWebKey,
CoreJweContentEncryptionAlgorithm, CoreJweKeyManagementAlgorithm,
CoreJwsSigningAlgorithm, CoreResponseMode, CoreResponseType,
CoreRevocableToken, CoreRevocationErrorResponse,
CoreSubjectIdentifierType, CoreTokenIntrospectionResponse,
CoreTokenType,
}
};
use serde::{Deserialize, Serialize};
use crate::commons::{error::Error, KrillResult};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CustomerDefinedAdditionalClaims(serde_json::Value);
impl AdditionalClaims for CustomerDefinedAdditionalClaims {}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CustomerDefinedExtraTokenFields(serde_json::Value);
impl ExtraTokenFields for CustomerDefinedExtraTokenFields {}
pub type FlexibleTokenResponse = StandardTokenResponse<
IdTokenFields<
CustomerDefinedAdditionalClaims,
CustomerDefinedExtraTokenFields,
CoreGenderClaim,
CoreJweContentEncryptionAlgorithm,
CoreJwsSigningAlgorithm,
>,
CoreTokenType,
>;
pub type FlexibleClient<
HasAuthUrl = EndpointSet,
HasDeviceAuthUrl = EndpointNotSet,
HasIntrospectionUrl = EndpointNotSet,
HasRevocationUrl = EndpointNotSet,
HasTokenUrl = EndpointMaybeSet,
HasUserInfoUrl = EndpointMaybeSet,
> = Client<
CustomerDefinedAdditionalClaims,
CoreAuthDisplay,
CoreGenderClaim,
CoreJweContentEncryptionAlgorithm,
CoreJsonWebKey,
CoreAuthPrompt,
StandardErrorResponse<CoreErrorResponseType>,
FlexibleTokenResponse,
CoreTokenIntrospectionResponse,
CoreRevocableToken,
CoreRevocationErrorResponse,
HasAuthUrl,
HasDeviceAuthUrl,
HasIntrospectionUrl,
HasRevocationUrl,
HasTokenUrl,
HasUserInfoUrl,
>;
pub type FlexibleIdTokenClaims =
IdTokenClaims<CustomerDefinedAdditionalClaims, CoreGenderClaim>;
pub type FlexibleUserInfoClaims =
UserInfoClaims<CustomerDefinedAdditionalClaims, CoreGenderClaim>;
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DesiredAdditionalProviderMetadata {
pub end_session_endpoint: Option<String>,
pub revocation_endpoint: Option<String>,
}
impl AdditionalProviderMetadata for DesiredAdditionalProviderMetadata {}
pub type WantedMeta = ProviderMetadata<
DesiredAdditionalProviderMetadata,
CoreAuthDisplay,
CoreClientAuthMethod,
CoreClaimName,
CoreClaimType,
CoreGrantType,
CoreJweContentEncryptionAlgorithm,
CoreJweKeyManagementAlgorithm,
CoreJsonWebKey,
CoreResponseMode,
CoreResponseType,
CoreSubjectIdentifierType,
>;
impl From<openidconnect::url::ParseError> for Error {
fn from(e: openidconnect::url::ParseError) -> Self {
Error::Custom(e.to_string())
}
}
macro_rules! is_supported {
($x:expr, $p:pat) => {{
match $x.iter().any(|v| matches!(v, $p)) {
true => Some(()),
false => None,
}
}};
}
macro_rules! is_supported_opt {
($x:expr, $p:pat) => {{
let empty_vec = Vec::new();
is_supported!($x.unwrap_or_else(|| &empty_vec), $p)
}};
}
macro_rules! is_supported_val {
($x:expr, $v:expr) => {{
match $x.contains(&$v) {
true => Some(()),
false => None,
}
}};
}
macro_rules! is_supported_val_opt {
($x:expr, $v:expr) => {{
let empty_vec = Vec::new();
is_supported_val!($x.unwrap_or_else(|| &empty_vec), $v)
}};
}
pub trait LogOrFail {
fn log_or_fail(self, prop: &str, val: Option<&str>) -> KrillResult<()>;
}
impl<T> LogOrFail for Option<T> {
fn log_or_fail(self, prop: &str, val: Option<&str>) -> KrillResult<()> {
let prop_val_text = match val {
Some(val) => format!("{prop}={val}"),
None => prop.to_string(),
};
match self {
Some(_) => {
debug!(
"OpenID Connect provider has capability {prop_val_text}"
);
Ok(())
}
None => {
let err = format!(
"OpenID Connect provider lacks capability {prop_val_text}"
);
error!("{err}");
Err(Error::Custom(err))
}
}
}
}