Skip to main content

openauth_core/context/
secrets.rs

1use std::fmt;
2
3use crate::crypto::{JweSecretSource, SecretConfig, SecretSource};
4use crate::error::OpenAuthError;
5use crate::options::OpenAuthOptions;
6
7use super::AuthEnvironment;
8
9pub(super) const DEFAULT_SECRET: &str = "openauth-secret-123456789012345678901";
10
11#[derive(Clone, PartialEq, Eq)]
12pub enum SecretMaterial {
13    Single(String),
14    Rotating(SecretConfig),
15}
16
17impl fmt::Debug for SecretMaterial {
18    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
19        match self {
20            Self::Single(_) => formatter
21                .debug_tuple("Single")
22                .field(&"<redacted>")
23                .finish(),
24            Self::Rotating(config) => formatter.debug_tuple("Rotating").field(config).finish(),
25        }
26    }
27}
28
29impl JweSecretSource for SecretMaterial {
30    fn current_jwe_secret(&self) -> Result<String, OpenAuthError> {
31        match self {
32            Self::Single(secret) => secret.current_jwe_secret(),
33            Self::Rotating(config) => config.current_jwe_secret(),
34        }
35    }
36
37    fn all_jwe_secrets(&self) -> Result<Vec<crate::crypto::jwe::JweSecret>, OpenAuthError> {
38        match self {
39            Self::Single(secret) => secret.all_jwe_secrets(),
40            Self::Rotating(config) => config.all_jwe_secrets(),
41        }
42    }
43}
44
45impl SecretSource for &SecretMaterial {
46    fn encrypt_current(&self, data: &str) -> Result<String, OpenAuthError> {
47        match self {
48            SecretMaterial::Single(secret) => secret.encrypt_current(data),
49            SecretMaterial::Rotating(config) => config.encrypt_current(data),
50        }
51    }
52
53    fn decrypt_payload(&self, data: &str) -> Result<String, OpenAuthError> {
54        match self {
55            SecretMaterial::Single(secret) => secret.decrypt_payload(data),
56            SecretMaterial::Rotating(config) => config.decrypt_payload(data),
57        }
58    }
59}
60
61pub(super) fn resolve_legacy_secret(
62    options: &OpenAuthOptions,
63    environment: &AuthEnvironment,
64) -> Option<String> {
65    options
66        .secret
67        .clone()
68        .or_else(|| environment.openauth_secret.clone())
69}
70
71pub(super) fn validate_secret(secret: &str, production: bool) -> Result<(), OpenAuthError> {
72    if secret.is_empty() {
73        return Err(OpenAuthError::InvalidConfig(
74            "OpenAuth secret is missing".to_owned(),
75        ));
76    }
77    if production && secret == DEFAULT_SECRET {
78        return Err(OpenAuthError::InvalidConfig(
79            "default secret cannot be used in production".to_owned(),
80        ));
81    }
82    Ok(())
83}