kanidmd_lib/idm/
mod.rs

1//! The Identity Management components that are layered on top of the [QueryServer](crate::server::QueryServer). These allow
2//! rich and expressive events and transformations that are lowered into the correct/relevant
3//! actions in the [QueryServer](crate::server::QueryServer). Generally this is where "Identity Management" policy and code
4//! is implemented.
5
6pub mod account;
7pub(crate) mod accountpolicy;
8pub mod application;
9pub(crate) mod applinks;
10pub mod audit;
11pub(crate) mod authsession;
12pub mod credupdatesession;
13pub mod delayed;
14pub mod event;
15pub mod group;
16pub mod identityverification;
17pub mod ldap;
18pub mod oauth2;
19pub(crate) mod radius;
20pub(crate) mod reauth;
21pub mod scim;
22pub mod server;
23pub mod serviceaccount;
24
25use crate::prelude::OperationError;
26use crate::server::identity::Source;
27use compact_jwt::JwsCompact;
28use crypto_glue::s256::Sha256Output;
29use kanidm_lib_crypto::x509_cert::Certificate;
30use kanidm_proto::{
31    internal::UserAuthToken,
32    v1::{AuthAllowed, AuthIssueSession, AuthMech},
33};
34use std::fmt;
35
36pub enum AuthState {
37    Choose(Vec<AuthMech>),
38    Continue(Vec<AuthAllowed>),
39    Denied(String),
40    Success(Box<JwsCompact>, AuthIssueSession),
41}
42
43impl fmt::Debug for AuthState {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        match self {
46            AuthState::Choose(mechs) => write!(f, "AuthState::Choose({mechs:?})"),
47            AuthState::Continue(allow) => write!(f, "AuthState::Continue({allow:?})"),
48            AuthState::Denied(reason) => write!(f, "AuthState::Denied({reason:?})"),
49            AuthState::Success(_token, issue) => write!(f, "AuthState::Success({issue:?})"),
50        }
51    }
52}
53
54#[derive(Debug, Clone, Default)]
55pub(crate) enum PreValidatedTokenStatus {
56    #[default]
57    None,
58    Valid(Box<UserAuthToken>),
59    NotAuthenticated,
60    SessionExpired,
61}
62
63#[derive(Debug, Clone)]
64pub struct ClientAuthInfo {
65    pub(crate) source: Source,
66    pub(crate) client_cert: Option<ClientCertInfo>,
67    pub(crate) bearer_token: Option<JwsCompact>,
68    pub(crate) basic_authz: Option<String>,
69    /// we store the prevalidated
70    pre_validated_token: PreValidatedTokenStatus,
71}
72
73impl ClientAuthInfo {
74    pub fn new(
75        source: Source,
76        client_cert: Option<ClientCertInfo>,
77        bearer_token: Option<JwsCompact>,
78        basic_authz: Option<String>,
79    ) -> Self {
80        Self {
81            source,
82            client_cert,
83            bearer_token,
84            basic_authz,
85            pre_validated_token: Default::default(),
86        }
87    }
88
89    pub fn bearer_token(&self) -> Option<&JwsCompact> {
90        self.bearer_token.as_ref()
91    }
92
93    pub fn pre_validated_uat(&self) -> Result<&UserAuthToken, OperationError> {
94        match &self.pre_validated_token {
95            PreValidatedTokenStatus::Valid(uat) => Ok(uat),
96            PreValidatedTokenStatus::None => Err(OperationError::AU0008ClientAuthInfoPrevalidation),
97            PreValidatedTokenStatus::NotAuthenticated => Err(OperationError::NotAuthenticated),
98            PreValidatedTokenStatus::SessionExpired => Err(OperationError::SessionExpired),
99        }
100    }
101
102    pub(crate) fn set_pre_validated_uat(&mut self, status: PreValidatedTokenStatus) {
103        self.pre_validated_token = status
104    }
105}
106
107#[derive(Debug, Clone)]
108pub struct ClientCertInfo {
109    pub public_key_s256: Sha256Output,
110    pub certificate: Certificate,
111}
112
113#[cfg(test)]
114impl ClientAuthInfo {
115    fn none() -> Self {
116        ClientAuthInfo {
117            source: Source::Internal,
118            client_cert: None,
119            bearer_token: None,
120            basic_authz: None,
121            pre_validated_token: Default::default(),
122        }
123    }
124}
125
126#[cfg(test)]
127impl From<Source> for ClientAuthInfo {
128    fn from(value: Source) -> ClientAuthInfo {
129        ClientAuthInfo {
130            source: value,
131            client_cert: None,
132            bearer_token: None,
133            basic_authz: None,
134            pre_validated_token: Default::default(),
135        }
136    }
137}
138
139#[cfg(test)]
140impl From<JwsCompact> for ClientAuthInfo {
141    fn from(value: JwsCompact) -> ClientAuthInfo {
142        ClientAuthInfo {
143            source: Source::Internal,
144            client_cert: None,
145            bearer_token: Some(value),
146            basic_authz: None,
147            pre_validated_token: Default::default(),
148        }
149    }
150}
151
152#[cfg(test)]
153impl From<ClientCertInfo> for ClientAuthInfo {
154    fn from(value: ClientCertInfo) -> ClientAuthInfo {
155        ClientAuthInfo {
156            source: Source::Internal,
157            client_cert: Some(value),
158            bearer_token: None,
159            basic_authz: None,
160            pre_validated_token: Default::default(),
161        }
162    }
163}
164
165#[cfg(test)]
166impl From<&str> for ClientAuthInfo {
167    fn from(value: &str) -> ClientAuthInfo {
168        ClientAuthInfo {
169            source: Source::Internal,
170            client_cert: None,
171            bearer_token: None,
172            basic_authz: Some(value.to_string()),
173            pre_validated_token: Default::default(),
174        }
175    }
176}
177
178#[cfg(test)]
179impl ClientAuthInfo {
180    fn encode_basic(id: &str, secret: &str) -> ClientAuthInfo {
181        use base64::{engine::general_purpose, Engine as _};
182        let value = format!("{id}:{secret}");
183        let value = general_purpose::STANDARD.encode(&value);
184        ClientAuthInfo {
185            source: Source::Internal,
186            client_cert: None,
187            bearer_token: None,
188            basic_authz: Some(value),
189            pre_validated_token: Default::default(),
190        }
191    }
192}