1use jsonwebtoken::{DecodingKey, TokenData, Validation};
2use serde::de::DeserializeOwned;
3
4use crate::{Error, JwtDecoder};
5
6#[derive(Clone)]
28pub struct LocalDecoder {
29 keys: Vec<DecodingKey>,
30 validation: Validation,
31}
32
33impl LocalDecoder {
34 pub fn new(keys: Vec<DecodingKey>, validation: Validation) -> Result<Self, Error> {
43 if keys.is_empty() {
44 return Err(Error::Configuration("No decoding keys provided".into()));
45 }
46
47 if validation.algorithms.is_empty() {
48 return Err(Error::Configuration(
49 "Validation algorithm is required".into(),
50 ));
51 }
52
53 if validation.aud.is_none() {
54 return Err(Error::Configuration(
55 "Validation audience is required".into(),
56 ));
57 }
58
59 Ok(Self { keys, validation })
60 }
61
62 pub fn builder() -> LocalDecoderBuilder {
64 LocalDecoderBuilder {
65 keys: None,
66 validation: None,
67 }
68 }
69}
70
71pub struct LocalDecoderBuilder {
73 keys: Option<Vec<DecodingKey>>,
74 validation: Option<Validation>,
75}
76
77impl LocalDecoderBuilder {
78 pub fn keys(mut self, keys: Vec<DecodingKey>) -> Self {
80 self.keys = Some(keys);
81 self
82 }
83
84 pub fn validation(mut self, validation: Validation) -> Self {
86 self.validation = Some(validation);
87 self
88 }
89
90 pub fn build(self) -> Result<LocalDecoder, Error> {
96 let keys = self
97 .keys
98 .ok_or_else(|| Error::Configuration("keys are required".into()))?;
99 let validation = self
100 .validation
101 .ok_or_else(|| Error::Configuration("validation is required".into()))?;
102
103 LocalDecoder::new(keys, validation)
104 }
105}
106
107impl<T> JwtDecoder<T> for LocalDecoder
108where
109 T: for<'de> DeserializeOwned,
110{
111 fn decode<'a>(
112 &'a self,
113 token: &'a str,
114 ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<TokenData<T>, Error>> + Send + 'a>>
115 {
116 Box::pin(async move {
117 let mut last_error: Option<Error> = None;
120 for key in self.keys.iter() {
121 match jsonwebtoken::decode::<T>(token, key, &self.validation) {
122 Ok(token_data) => return Ok(token_data),
123 Err(e) => {
124 tracing::error!("Error decoding token: {}", e);
125 last_error = Some(Error::Jwt(e));
126 }
127 }
128 }
129
130 Err(last_error.unwrap_or_else(|| Error::Configuration("No keys available".into())))
131 })
132 }
133}