Skip to main content

axum_jwt/
decode.rs

1use {
2    axum_core::extract::FromRef,
3    jsonwebtoken::{DecodingKey, TokenData, Validation},
4    serde::de::DeserializeOwned,
5    std::{fmt, ops::Deref, sync::Arc},
6};
7
8/// A decoder for JSON Web Tokens (JWTs).
9///
10/// To extract a JWT value from a request header, this decoder must be provided
11/// to the [router] using the [`with_state`] method.
12///
13/// [router]: https://docs.rs/axum/latest/axum/struct.Router.html
14/// [`with_state`]: https://docs.rs/axum/latest/axum/struct.Router.html#method.with_state
15///
16/// # Examples
17///
18/// You can pass the decoder directly:
19///
20/// ```
21/// use {
22///     axum::{Router, routing},
23///     axum_jwt::{Claims, Decoder, jsonwebtoken::DecodingKey},
24///     serde::Deserialize,
25/// };
26///
27/// #[derive(Deserialize)]
28/// struct User {
29///     sub: String,
30/// }
31///
32/// async fn hello(Claims(u): Claims<User>) -> String {
33///     format!("Hello, {}!", u.sub)
34/// }
35///
36/// let decoder = Decoder::from_key(DecodingKey::from_secret(b"secret"));
37///
38/// let app = Router::new()
39///     .route("/", routing::get(hello))
40///     .with_state(decoder);
41/// # let _: Router = app;
42/// ```
43///
44/// If the application needs to store additional state, you can define a custom
45/// type that contains the decoder. You'll also need the application state to
46/// be cheap to clone, so it makes sense to wrap it in an [`Arc`]. In this
47/// case, you can provide the decoder by implementing the [`AsRef`] trait for
48/// your custom state.
49///
50/// ```
51/// # use {
52/// #     axum::{Router, routing},
53/// #     axum_jwt::{Decoder, jsonwebtoken::DecodingKey},
54/// #     std::sync::{Arc, Mutex},
55/// # };
56/// # struct User;
57/// struct App {
58///     decoder: Decoder,
59///     users_online: Mutex<Vec<User>>,
60/// }
61///
62/// impl AsRef<Decoder> for App {
63///     fn as_ref(&self) -> &Decoder {
64///         &self.decoder
65///     }
66/// }
67///
68/// let decoder = Decoder::from_key(DecodingKey::from_secret(b"secret"));
69///
70/// # async fn hello() {}
71/// let app = Router::new()
72///     .route("/", routing::get(hello))
73///     .with_state(Arc::new(App {
74///         decoder,
75///         users_online: Mutex::default(),
76///     }));
77/// # let _: Router = app;
78/// ```
79#[derive(Clone)]
80pub struct Decoder(Arc<Inner>);
81
82impl Decoder {
83    /// Creates a decoder from the provided decoding key.
84    pub fn from_key(key: DecodingKey) -> Self {
85        Self(Arc::new(Inner {
86            keys: vec![key],
87            validation: Validation::default(),
88        }))
89    }
90
91    /// Creates a decoder from the provided decoding key and validation.
92    pub fn new(key: DecodingKey, validation: Validation) -> Self {
93        Self(Arc::new(Inner {
94            keys: vec![key],
95            validation,
96        }))
97    }
98
99    /// Creates a decoder from the provided decoding keys and validation.
100    ///
101    /// If the given vector is empty, this constructor will return `None`.
102    pub fn with_keys(keys: Vec<DecodingKey>, validation: Validation) -> Option<Self> {
103        if keys.is_empty() {
104            None
105        } else {
106            Some(Self(Arc::new(Inner { keys, validation })))
107        }
108    }
109
110    /// Returns a slice of decoding keys.
111    pub fn keys(&self) -> &[DecodingKey] {
112        &self.0.keys
113    }
114
115    /// Returns a reference to the validation.
116    pub fn validation(&self) -> &Validation {
117        &self.0.validation
118    }
119
120    pub(crate) fn decode<T>(&self, token: &str) -> Result<TokenData<T>, jsonwebtoken::errors::Error>
121    where
122        T: DeserializeOwned,
123    {
124        let decoder = &*self.0;
125        let mut err = None;
126        for key in &decoder.keys {
127            match jsonwebtoken::decode(token, key, &decoder.validation) {
128                Ok(data) => return Ok(data),
129                Err(e) => err = Some(e),
130            }
131        }
132
133        Err(err.expect("take error"))
134    }
135}
136
137impl fmt::Debug for Decoder {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        f.debug_struct("Decoder")
140            .field("keys", &"..")
141            .field("validation", &self.0.validation)
142            .finish()
143    }
144}
145
146impl<P> FromRef<P> for Decoder
147where
148    P: Deref<Target: AsRef<Self>>,
149{
150    fn from_ref(p: &P) -> Self {
151        p.as_ref().clone()
152    }
153}
154
155struct Inner {
156    keys: Vec<DecodingKey>,
157    validation: Validation,
158}