refactor(chat): deduplicate JwtManager algorithm/key/validation setup

Extract build_keys_and_validation() private helper that encapsulates
the 20 lines of algorithm parsing, EncodingKey/DecodingKey creation,
and Validation configuration previously duplicated between new() and
with_revocation_store_only().

- Remove with_revocation_store_only() intermediate function
- with_revocation_store() now calls build_keys_and_validation() directly
- with_pool_and_store() delegates to with_revocation_store()

Addresses audit finding D10: code duplication in JwtManager constructors.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
senke 2026-02-11 23:24:39 +01:00
parent e56f63168d
commit 0f41ca80ad

View file

@ -148,8 +148,11 @@ pub struct JwtManager {
}
impl JwtManager {
/// Crée un nouveau gestionnaire JWT
pub fn new(config: SecurityConfig) -> Result<Self> {
/// Parse algorithm, create keys and validation from config.
/// Shared by all constructors to avoid duplication.
fn build_keys_and_validation(
config: &SecurityConfig,
) -> Result<(EncodingKey, DecodingKey, Validation)> {
let algorithm = match config.jwt_algorithm.as_str() {
"HS256" => Algorithm::HS256,
"HS384" => Algorithm::HS384,
@ -168,6 +171,14 @@ impl JwtManager {
validation.set_issuer(&[&config.jwt_issuer]);
validation.set_required_spec_claims(&["exp", "iat", "sub", "aud", "iss", "jti"]);
Ok((encoding_key, decoding_key, validation))
}
/// Crée un nouveau gestionnaire JWT
pub fn new(config: SecurityConfig) -> Result<Self> {
let (encoding_key, decoding_key, validation) =
Self::build_keys_and_validation(&config)?;
Ok(Self {
config,
encoding_key,
@ -191,33 +202,8 @@ impl JwtManager {
config: SecurityConfig,
store: Arc<dyn JwtRevocationStore>,
) -> Result<Self> {
let mut manager = Self::with_revocation_store_only(config, store)?;
manager.db_pool = None;
Ok(manager)
}
/// Version interne avec store seulement
fn with_revocation_store_only(
config: SecurityConfig,
store: Arc<dyn JwtRevocationStore>,
) -> Result<Self> {
let algorithm = match config.jwt_algorithm.as_str() {
"HS256" => Algorithm::HS256,
"HS384" => Algorithm::HS384,
"HS512" => Algorithm::HS512,
"RS256" => Algorithm::RS256,
"RS384" => Algorithm::RS384,
"RS512" => Algorithm::RS512,
_ => return Err(ChatError::configuration_error("Algorithme JWT invalide")),
};
let encoding_key = EncodingKey::from_secret(config.jwt_secret.as_bytes());
let decoding_key = DecodingKey::from_secret(config.jwt_secret.as_bytes());
let mut validation = Validation::new(algorithm);
validation.set_audience(&[&config.jwt_audience]);
validation.set_issuer(&[&config.jwt_issuer]);
validation.set_required_spec_claims(&["exp", "iat", "sub", "aud", "iss", "jti"]);
let (encoding_key, decoding_key, validation) =
Self::build_keys_and_validation(&config)?;
Ok(Self {
config,
@ -236,7 +222,7 @@ impl JwtManager {
pool: PgPool,
store: Arc<dyn JwtRevocationStore>,
) -> Result<Self> {
let mut manager = Self::with_revocation_store_only(config, store)?;
let mut manager = Self::with_revocation_store(config, store)?;
manager.db_pool = Some(pool);
Ok(manager)
}