shared/utils/crypto/
jwt.rs1use base64::Engine;
2use base64::prelude::BASE64_URL_SAFE_NO_PAD;
3use jsonwebtoken::errors::ErrorKind;
4use jsonwebtoken::{DecodingKey, EncodingKey};
5use serde::de::DeserializeOwned;
6
7use crate::application::model::Claims;
8use crate::config::JwtConfig;
9use crate::domain::model::SigningKey;
10use crate::error::{AuthError, CoreError, Result, TokenErrorType};
11
12#[derive(Clone)]
13pub struct JwtSigner {
14 jwt_config: JwtConfig,
15 private: String,
16 pub signing_key: SigningKey,
17}
18
19impl JwtSigner {
20 pub fn new(private: &str, signing_key: &SigningKey, jwt_config: &JwtConfig) -> Self {
21 Self {
22 jwt_config: jwt_config.clone(),
23 private: private.into(),
24 signing_key: signing_key.clone(),
25 }
26 }
27}
28
29impl JwtSigner {
30 fn load_keys(&self) -> (Result<EncodingKey>, Result<DecodingKey>) {
31 let prv_key = BASE64_URL_SAFE_NO_PAD.decode(&self.private).unwrap();
32 let pub_key = BASE64_URL_SAFE_NO_PAD
33 .decode(&self.signing_key.public_key)
34 .unwrap();
35
36 match self.signing_key.algorithm.as_str() {
37 "EdDSA" => (
38 EncodingKey::from_ed_pem(&prv_key).map_err(Into::into),
39 DecodingKey::from_ed_pem(&pub_key).map_err(Into::into),
40 ),
41 "ES256" | "ES384" => (
42 EncodingKey::from_ec_pem(&prv_key).map_err(Into::into),
43 DecodingKey::from_ec_pem(&pub_key).map_err(Into::into),
44 ),
45 "RS256" | "RS384" | "RS512" | "PS256" | "PS384" | "PS512" => (
46 EncodingKey::from_rsa_pem(&prv_key).map_err(Into::into),
47 DecodingKey::from_rsa_pem(&pub_key).map_err(Into::into),
48 ),
49 &_ => (
50 EncodingKey::from_rsa_pem(&prv_key).map_err(Into::into),
51 DecodingKey::from_rsa_pem(&pub_key).map_err(Into::into),
52 ),
53 }
54 }
55
56 pub fn encode(&self, claims: Claims) -> Result<String> {
57 let mut header = jsonwebtoken::Header::new(self.jwt_config.algorithm.clone().into());
58 header.kid = Some(self.signing_key.kid.clone());
59
60 let encoding_secret = self.load_keys().0?;
63
64 let token = jsonwebtoken::encode(&header, &claims, &encoding_secret)?;
65 Ok(token)
66 }
67
68 pub fn decode<C: DeserializeOwned>(&self, token: &str) -> Result<C> {
69 let mut validation =
70 jsonwebtoken::Validation::new(self.jwt_config.algorithm.clone().into());
71 validation.set_audience(&[self.jwt_config.clone().audience]);
72 validation.set_issuer(&[self.jwt_config.clone().issuer]);
73
74 let decoding_key = self.load_keys().1?;
75 jsonwebtoken::decode::<C>(&token, &decoding_key, &validation)
76 .map(|token_data| token_data.claims)
77 .map_err(|e| match e.kind() {
78 ErrorKind::InvalidSignature => {
79 CoreError::Unauthenticated(AuthError::TokenInvalidSignature {
80 token_type: TokenErrorType::Token,
81 })
82 }
83 ErrorKind::ExpiredSignature => {
84 CoreError::Unauthenticated(AuthError::TokenExpired {
85 token_type: TokenErrorType::Token,
86 expired_at: chrono::Utc::now(),
87 })
88 }
89 ErrorKind::InvalidAudience => {
90 CoreError::Unauthenticated(AuthError::TokenInvalidAudience {
91 token_type: TokenErrorType::Token,
92 })
93 }
94 ErrorKind::InvalidIssuer => {
95 CoreError::Unauthenticated(AuthError::TokenInvalidIssuer {
96 token_type: TokenErrorType::Token,
97 })
98 }
99 ErrorKind::InvalidAlgorithm | ErrorKind::MissingAlgorithm => {
100 CoreError::Unauthenticated(AuthError::TokenInvalidAlgorithm {
101 token_type: TokenErrorType::Token,
102 })
103 }
104 _ => CoreError::Unauthenticated(AuthError::TokenInvalid {
105 token_type: TokenErrorType::Token,
106 }),
107 })
108 }
109}