diff --git a/libs/utils/src/auth.rs b/libs/utils/src/auth.rs index 4fa85346ad..a57dbff5de 100644 --- a/libs/utils/src/auth.rs +++ b/libs/utils/src/auth.rs @@ -9,14 +9,26 @@ use std::path::Path; use anyhow::Result; use jsonwebtoken::{ - decode, encode, Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation, + decode, encode, Algorithm, Algorithm::*, DecodingKey, EncodingKey, Header, TokenData, + Validation, }; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; use crate::id::TenantId; -const JWT_ALGORITHM: Algorithm = Algorithm::RS256; +/// Algorithms accepted during validation. +/// +/// Accept all RSA-based algorithms. We pass this list to jsonwebtoken::decode, +/// which checks that the algorithm in the token is one of these. +/// +/// XXX: It also fails the validation if there are any algorithms in this list that belong +/// to different family than the token's algorithm. In other words, we can *not* list any +/// non-RSA algorithms here, or the validation always fails with InvalidAlgorithm error. +const ACCEPTED_ALGORITHMS: &[Algorithm] = &[RS256, RS384, RS512]; + +/// Algorithm to use when generating a new token in [`encode_from_key_file`] +const ENCODE_ALGORITHM: Algorithm = Algorithm::RS256; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "lowercase")] @@ -33,6 +45,7 @@ pub enum Scope { SafekeeperData, } +/// JWT payload. See docs/authentication.md for the format #[serde_as] #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Claims { @@ -55,7 +68,8 @@ pub struct JwtAuth { impl JwtAuth { pub fn new(decoding_key: DecodingKey) -> Self { - let mut validation = Validation::new(JWT_ALGORITHM); + let mut validation = Validation::default(); + validation.algorithms = ACCEPTED_ALGORITHMS.into(); // The default 'required_spec_claims' is 'exp'. But we don't want to require // expiration. validation.required_spec_claims = [].into(); @@ -86,5 +100,5 @@ impl std::fmt::Debug for JwtAuth { // this function is used only for testing purposes in CLI e g generate tokens during init pub fn encode_from_key_file(claims: &Claims, key_data: &[u8]) -> Result { let key = EncodingKey::from_rsa_pem(key_data)?; - Ok(encode(&Header::new(JWT_ALGORITHM), claims, &key)?) + Ok(encode(&Header::new(ENCODE_ALGORITHM), claims, &key)?) }