use crate::{
error::jwt_error::JWTError,
model::{
claims::JWTClaims,
signing_algorithm::{SigningAlgorithm, SigningKeyLength},
},
};
use std::{cell::RefCell, rc::Rc};
pub trait SignatureValidation {
fn validate(&self, token: String) -> Result<JWTClaims, JWTError>;
}
pub struct SignatureValidator {
validator: Rc<RefCell<dyn SignatureValidation>>,
}
impl SignatureValidator {
pub fn new(
algorithm: SigningAlgorithm,
key_length: SigningKeyLength,
key: String,
) -> Result<Self, JWTError> {
#[cfg(any(feature = "fips", fips))]
{
Ok(SignatureValidator {
validator: Rc::new(RefCell::new(
super::proxy_wasm_validator::ProxyWasmSignatureValidator::new(
algorithm,
key_length,
super::proxy_wasm_validator::Key::Pem(key),
)?,
)),
})
}
#[cfg(not(any(feature = "fips", fips)))]
match algorithm {
SigningAlgorithm::Rsa => Ok(SignatureValidator {
validator: Rc::new(RefCell::new(
super::rsa_validator::RsaSignatureValidator::new(key_length, key)?,
)),
}),
SigningAlgorithm::Es => match key_length {
SigningKeyLength::Len256 => Ok(SignatureValidator {
validator: Rc::new(RefCell::new(super::es_validator::EsSignatureValidator::<
p256::NistP256,
>::new(key_length, key)?)),
}),
SigningKeyLength::Len384 => Ok(SignatureValidator {
validator: Rc::new(RefCell::new(super::es_validator::EsSignatureValidator::<
p384::NistP384,
>::new(key_length, key)?)),
}),
_ => Err(JWTError::InvalidKeyLength(
"Signing key length is invalid for ES algorithm".to_string(),
)),
},
SigningAlgorithm::Hmac => Ok(SignatureValidator {
validator: Rc::new(RefCell::new(
super::hmac_validator::HmacSignatureValidator::new(key_length, key),
)),
}),
}
}
pub fn validate(&self, token: String) -> Result<JWTClaims, JWTError> {
self.validator.borrow().validate(token)
}
}
#[cfg(test)]
pub mod tests {
use crate::error::jwt_error::{JWTError, JWTErrorEnumKind};
pub fn assert_error_kind<T>(validation: &Result<T, JWTError>, kind: JWTErrorEnumKind)
where
T: std::fmt::Debug,
{
assert!(validation.is_err());
assert_eq!(
JWTErrorEnumKind::from(validation.as_ref().unwrap_err()),
kind
);
}
#[cfg(not(any(feature = "fips", fips)))]
mod signature_validator_test {
use crate::model::signing_algorithm::{SigningAlgorithm, SigningKeyLength};
use crate::validator::signature_validator::SignatureValidator;
const RSA_PUBLIC_KEY_PEM_256: &str = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFRZJoSbY3lJmruwlXQM
wiOlr4EtBJHSj7IrCYqx9rFEW+JUwoe5iMZl33D6tUsr1GsG50R7JL2KvxHrj0u6
A3A9beI41XdRfJatugaffroLuZCUYla097uVSQacUSBfBVEsT0TU9MrxBW0HGIXz
dGwuA9GRncgk7kcfPgJLjwzcBBZATVaASO28Rrf6eQ12w0UNJL4XM+/yPyQatbvO
D5KqX8ue2a0uO+7yE8x0A99UMIHYo1zedp+Qr+p0+/5VTWjEZT5I6JGUIMjSVqn0
L0z0WMKJtSdG/CQpZyGnWBz6irOd5xJHAyH7mr02dOJVSXMJXvchCEMMlWghqlqQ
XwIDAQAB
-----END PUBLIC KEY-----";
#[test]
fn validation_success() {
let token: &str = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.e30.AC3VWMTRNDUh2S2MbT3SSzVg4P7BykOCWYSlMRYgh7xUGo4lisfjaTKpqydtoouB-mJaWRtq09rnP1BG1IMLXxPjYNPsVbTvcpktifS_qAnzjLtNpki_a7H1Uxey7mPn6MQf0bzD4inYb_zz7OgPb6U57l8B7kHKhA7vS6-a56zOxDnrZm2pwtNhkoXWBfQ6LiRWjfPOQUED3ep3YZ-BQR5sT3KUNV_nrgi6Qhc1wPOoTbEaLbjCQjnML6jxpJxpXKL2zL8ARHy-avxqtwCiWW3LQ-DQhneEVYzZ79q-8FKD8GcII9g3MCX5MZVmpYS3Z3WPP1Xzb4IVtUUYK6dogg";
let signature_validator = SignatureValidator::new(
SigningAlgorithm::Rsa,
SigningKeyLength::Len256,
RSA_PUBLIC_KEY_PEM_256.to_string(),
)
.unwrap();
let validation = signature_validator.validate(token.to_string());
assert!(validation.is_ok());
}
}
}