twa_jwks/
lib.rs

1#![forbid(unsafe_code)]
2
3use jwt::Jwt;
4use keyset::KeyStore;
5use std::sync::Arc;
6use thiserror::Error as ThisError;
7use tokio::sync::RwLock;
8use tracing::error;
9
10pub mod error;
11pub mod jwt;
12pub mod keyset;
13
14#[cfg(feature = "actix-web")]
15pub mod actix_web;
16
17#[cfg(feature = "axum")]
18pub mod axum;
19
20#[derive(ThisError, Debug)]
21pub enum Error {
22    #[error("jwks_client: {0}")]
23    Jwks(error::Error),
24
25    #[error("{0}")]
26    Unknown(String),
27}
28
29impl From<error::Error> for Error {
30    fn from(e: error::Error) -> Self {
31        Error::Jwks(e)
32    }
33}
34
35/// /// ```rust
36/// # tokio_test::block_on(async {
37/// let jwks_client = JwksClient::new("http://127.0.0.1:4456/.well-known/jwks.json").await.unwrap();
38/// # }
39/// ```
40#[derive(Clone)]
41pub struct JwksClient {
42    inner: Arc<RwLock<KeyStore>>,
43    insecure: bool,
44}
45
46impl JwksClient {
47    pub async fn new<U: Into<String>>(url: U) -> Result<Self, Error> {
48        Self::build(Some(url)).await
49    }
50
51    pub async fn insecure() -> Result<Self, Error> {
52        Self::build(None::<String>).await
53    }
54
55    pub async fn build<U: Into<String>>(url: Option<U>) -> Result<Self, Error> {
56        match url {
57            Some(url) => {
58                let store = KeyStore::new_from(url.into()).await?;
59
60                Ok(Self {
61                    inner: Arc::new(RwLock::new(store)),
62                    insecure: false,
63                })
64            }
65            _ => {
66                let store = KeyStore::new();
67
68                Ok(Self {
69                    inner: Arc::new(RwLock::new(store)),
70                    insecure: true,
71                })
72            }
73        }
74    }
75
76    pub async fn verify(&self, token: &str) -> Result<Jwt, error::Error> {
77        let read = self.inner.read().await;
78
79        if self.insecure {
80            return read.decode(token);
81        }
82
83        if read.should_refresh().unwrap_or(false) {
84            drop(read);
85
86            let mut guard = self.inner.write().await;
87            guard.load_keys().await?;
88
89            drop(guard);
90        }
91
92        let read = self.inner.read().await;
93
94        read.verify(token)
95    }
96}