Skip to main content

alibi_plugins/sso/
private_key.rs

1//! Application-owned private key material for SSO client authentication.
2use super::Value;
3#[derive(Clone, Default)]
4pub struct SsoPrivateKey {
5    pub private_key_jwk: Option<Value>,
6    pub private_key_pem: Option<String>,
7    pub kid: Option<String>,
8    pub algorithm: Option<String>,
9}
10impl std::fmt::Debug for SsoPrivateKey {
11    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        formatter
13            .debug_struct("SsoPrivateKey")
14            .finish_non_exhaustive()
15    }
16}
17
18impl SsoPrivateKey {
19    pub(super) fn has_material(&self) -> bool {
20        self.private_key_jwk
21            .as_ref()
22            .is_some_and(|key| !key.is_null())
23            || self
24                .private_key_pem
25                .as_deref()
26                .is_some_and(|pem| !pem.is_empty())
27    }
28    pub(super) fn assertion(
29        &self,
30        config: &Value,
31    ) -> Result<crate::oauth::OAuthClientAssertion, String> {
32        let raw_algorithm = config
33            .get("privateKeyAlgorithm")
34            .and_then(Value::as_str)
35            .or(self.algorithm.as_deref());
36        crate::oauth::OAuthPrivateKeyJwtOptions {
37            private_key_jwk: self.private_key_jwk.clone(),
38            private_key_pem: self.private_key_pem.clone(),
39            kid: config
40                .get("privateKeyId")
41                .and_then(Value::as_str)
42                .map(str::to_owned)
43                .or_else(|| self.kid.clone()),
44            algorithm: raw_algorithm
45                .filter(|algorithm| {
46                    crate::oauth::PRIVATE_KEY_JWT_SIGNING_ALGORITHMS.contains(algorithm)
47                })
48                .map(str::to_owned),
49            expires_in: None,
50        }
51        .into_assertion()
52    }
53}
54
55/// Parameters supplied to an application-owned SSO signing-key resolver.
56#[derive(Clone, Debug)]
57pub struct SsoPrivateKeyContext {
58    pub provider_id: String,
59    pub key_id: Option<String>,
60    pub issuer: String,
61}
62#[async_trait::async_trait]
63pub trait SsoPrivateKeyResolver: Send + Sync {
64    async fn resolve(
65        &self,
66        context: SsoPrivateKeyContext,
67    ) -> alibi_core::AuthResult<Option<SsoPrivateKey>>;
68}
69#[derive(Clone)]
70pub struct SsoKeyResolver(pub std::sync::Arc<dyn SsoPrivateKeyResolver>);
71impl std::fmt::Debug for SsoKeyResolver {
72    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        formatter
74            .debug_struct("SsoKeyResolver")
75            .finish_non_exhaustive()
76    }
77}
78
79impl super::SsoPlugin {
80    pub(super) fn private_key_source_configured(&self, provider_id: &str) -> bool {
81        self.config.resolve_private_key.is_some()
82            || self.config.default_providers.iter().any(|provider| {
83                provider.provider_id == provider_id && provider.private_key.is_some()
84            })
85    }
86}