Allow to cache discovery endpoint

This commit is contained in:
Timshel 2024-02-27 17:22:40 +01:00
parent 7117e78fc7
commit 927a9e3e4c
4 changed files with 26 additions and 11 deletions

View File

@ -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
### Debug only, log all the tokens
# SSO_DEBUG_TOKENS=false

1
SSO.md
View File

@ -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 for easier debugging (default `false`)
The callback url is : `https://your.domain/identity/connect/oidc-signin`

View File

@ -636,6 +636,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
sso_debug_tokens: bool, true, def, false;
},

View File

@ -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;
@ -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()));
@ -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
}
}
@ -347,8 +352,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() {