1use crate::error::Result;
2use axum::{
3 extract::{FromRef, FromRequestParts},
4 http::request::Parts,
5 response::{IntoResponse, Response},
6};
7use axum_extra::{
8 headers::{authorization::Bearer, Authorization},
9 TypedHeader,
10};
11use jsonwebtoken::{encode, Algorithm, DecodingKey, EncodingKey, Header};
12use serde::{Deserialize, Serialize};
13
14pub mod error;
15pub mod key;
16
17pub use key::PublicKey;
18
19#[derive(Debug, Deserialize, Serialize)]
21pub struct Claims {
22 pub sub: String,
23 pub exp: usize,
24 pub iat: usize,
25}
26
27impl Claims {
28 pub fn new(sub: String) -> Self {
31 let now = std::time::SystemTime::now();
32 let iat = now.duration_since(std::time::UNIX_EPOCH).unwrap().as_secs() as usize;
33
34 let token_life = std::time::Duration::from_secs(60 * 60 * 24 * 7); let exp = (now + token_life)
36 .duration_since(std::time::UNIX_EPOCH)
37 .unwrap()
38 .as_secs() as usize;
39
40 Self { sub, exp, iat }
41 }
42
43 pub async fn encode(&self, key: &EncodingKey) -> Result<String> {
45 let header = Header::new(Algorithm::RS256);
46 let token = encode(&header, self, key)?;
47
48 Ok(token)
49 }
50
51 pub async fn decode(token: &str, key: &DecodingKey) -> Result<Self> {
52 let validation = jsonwebtoken::Validation::new(Algorithm::RS256);
53 let claims = jsonwebtoken::decode::<Self>(token, key, &validation)?;
54
55 Ok(claims.claims)
56 }
57
58 pub async fn decode_validation(
59 token: &str,
60 key: &DecodingKey,
61 validation: &jsonwebtoken::Validation,
62 ) -> Result<Self> {
63 let claims = jsonwebtoken::decode::<Self>(token, key, validation)?;
64
65 Ok(claims.claims)
66 }
67}
68
69#[axum::async_trait]
70impl<S> FromRequestParts<S> for Claims
71where
72 S: Send + Sync,
73 key::PublicKey: axum::extract::FromRef<S>,
74{
75 type Rejection = Response;
76
77 async fn from_request_parts(
78 parts: &mut Parts,
79 state: &S,
80 ) -> std::result::Result<Self, Self::Rejection> {
81 let TypedHeader(Authorization(token)) =
83 TypedHeader::<Authorization<Bearer>>::from_request_parts(parts, state)
84 .await
85 .map_err(|err| err.into_response())?;
86
87 let key: PublicKey = FromRef::from_ref(state);
89 let key: DecodingKey = FromRef::from_ref(&key);
90 let claims = Claims::decode(token.token(), &key)
91 .await
92 .map_err(|err| err.into_response())?;
93
94 Ok(claims)
95 }
96}