Skip to content

Commit

Permalink
Allow to cache discovery endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Timshel committed Jul 22, 2024
1 parent aa16971 commit fa05a38
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@
# SSO_MASTER_PASSWORD_POLICY='{"enforceOnLogin":false,"minComplexity":3,"minLength":12,"requireLower":false,"requireNumbers":false,"requireSpecial":false,"requireUpper":false}'
## Use sso only for authentication not the session lifecycle
# SSO_AUTH_ONLY_NOT_SESSION=false
## Client cache for discovery endpoint. Duration in seconds (0 to disable).
# SSO_CLIENT_CACHE_EXPIRATION=0
## Log all the tokens, LOG_LEVEL=debug is required
# SSO_DEBUG_TOKENS=false

Expand Down
1 change: 1 addition & 0 deletions SSO.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The following configurations are available
- `SSO_CLIENT_SECRET` : Client Secret
- `SSO_MASTER_PASSWORD_POLICY`: Optional Master password policy
- `SSO_AUTH_ONLY_NOT_SESSION`: Enable to use SSO only for authentication not session lifecycle
- `SSO_CLIENT_CACHE_EXPIRATION`: Cache calls to the discovery endpoint, duration in seconds, `0` to disable (default `0`);
- `SSO_DEBUG_TOKENS`: Log all tokens (default `false`, `LOG_LEVEL=debug` is required)

The callback url is : `https://your.domain/identity/connect/oidc-signin`
Expand Down
2 changes: 2 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,8 @@ make_config! {
sso_master_password_policy: String, true, option;
/// Use sso only for auth not the session lifecycle
sso_auth_only_not_session: bool, true, def, false;
/// Client cache for discovery endpoint. Duration in seconds (0 or less to disable).
sso_client_cache_expiration: u64, true, def, 0;
/// Log all tokens, LOG_LEVEL=debug is required
sso_debug_tokens: bool, true, def, false;
},
Expand Down
32 changes: 21 additions & 11 deletions src/sso.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use chrono::Utc;
use regex::Regex;
use std::borrow::Cow;
use std::sync::RwLock;
use std::time::Duration;
use url::Url;

Expand Down Expand Up @@ -31,7 +30,10 @@ use crate::{
static AC_CACHE: Lazy<Cache<String, AuthenticatedUser>> =
Lazy::new(|| Cache::builder().max_capacity(1000).time_to_live(Duration::from_secs(10 * 60)).build());

static CLIENT_CACHE: RwLock<Option<CoreClient>> = RwLock::new(None);
static CLIENT_CACHE_KEY: Lazy<String> = Lazy::new(|| "sso-client".to_string());
static CLIENT_CACHE: Lazy<Cache<String, CoreClient>> = Lazy::new(|| {
Cache::builder().max_capacity(1).time_to_live(Duration::from_secs(CONFIG.sso_client_cache_expiration())).build()
});

static SSO_JWT_ISSUER: Lazy<String> = Lazy::new(|| format!("{}|sso", CONFIG.domain_origin()));

Expand Down Expand Up @@ -165,14 +167,17 @@ impl CoreClientExt for CoreClient {

// Simple cache to prevent recalling the discovery endpoint each time
async fn cached() -> ApiResult<CoreClient> {
let cc_client = CLIENT_CACHE.read().ok().and_then(|rw_lock| rw_lock.clone());
match cc_client {
Some(client) => Ok(client),
None => Self::_get_client().await.map(|client| {
let mut cached_client = CLIENT_CACHE.write().unwrap();
*cached_client = Some(client.clone());
client
}),
if CONFIG.sso_client_cache_expiration() > 0 {
match CLIENT_CACHE.get(&*CLIENT_CACHE_KEY) {
Some(client) => Ok(client),
None => Self::_get_client().await.map(|client| {
debug!("Inserting new client in cache");
CLIENT_CACHE.insert(CLIENT_CACHE_KEY.clone(), client.clone());
client
}),
}
} else {
Self::_get_client().await
}
}

Expand Down Expand Up @@ -346,8 +351,13 @@ pub async fn exchange_code(wrapped_code: &str, conn: &mut DbConn) -> ApiResult<U
}

let id_claims = match id_token.claims(&client.vw_id_token_verifier(), &oidc_nonce) {
Err(err) => err!(format!("Could not read id_token claims, {err}")),
Ok(claims) => claims,
Err(err) => {
if CONFIG.sso_client_cache_expiration() > 0 {
CLIENT_CACHE.invalidate(&*CLIENT_CACHE_KEY);
}
err!(format!("Could not read id_token claims, {err}"));
}
};

let email = match id_claims.email() {
Expand Down

0 comments on commit fa05a38

Please sign in to comment.