actix-surreal/framework/src/auth/jwt.rs
2024-07-24 13:22:50 +02:00

95 lines
2.2 KiB
Rust

use super::OAuthUser;
use jwks_client_update::{jwt::Jwt, keyset::KeyStore};
pub trait Bearer {
fn token(&self) -> &str;
}
#[cfg(feature = "actix")]
pub mod actix_bearer_auth {
use actix_web_httpauth::extractors::bearer::BearerAuth;
pub struct ActixBearerAuth {
bearer: BearerAuth,
}
impl From<BearerAuth> for ActixBearerAuth {
fn from(value: BearerAuth) -> Self {
Self { bearer: value }
}
}
impl Into<BearerAuth> for ActixBearerAuth {
fn into(self) -> BearerAuth {
self.bearer
}
}
impl super::Bearer for ActixBearerAuth {
fn token(&self) -> &str {
self.bearer.token()
}
}
}
#[cfg(feature = "actix")]
pub use actix_bearer_auth::ActixBearerAuth;
pub struct JWT {
pub headers: serde_json::Value,
pub claims: serde_json::Value,
}
impl From<Jwt> for JWT {
fn from(value: Jwt) -> Self {
Self {
headers: value.header().into().unwrap(),
claims: value.payload().into().unwrap(),
}
}
}
impl JWT {
pub fn get_expiry_date(&self) -> Option<chrono::DateTime<chrono::Utc>> {
let ts = self.claims.get("exp")?.as_i64()?;
chrono::DateTime::from_timestamp(ts, 0)
}
pub fn get_claim(&self, key: &str) -> Option<&serde_json::Value> {
self.claims.get(key)
}
pub fn get_claim_str(&self, key: &str) -> Option<&str> {
self.get_claim(key)?.as_str()
}
pub fn get_user_id(&self) -> Option<&str> {
self.get_claim_str("sub")
}
pub fn get_session_id(&self) -> Option<&str> {
self.get_claim_str("sid")
}
}
pub struct JWKS {
pub store: KeyStore,
}
impl From<KeyStore> for JWKS {
fn from(value: KeyStore) -> Self {
Self { store: value }
}
}
impl JWKS {
pub async fn new_from(url: String) -> Result<Self, jwks_client_update::error::Error> {
Ok(Self {
store: KeyStore::new_from(url).await?,
})
}
pub fn auth_from_bearer<T: Bearer>(
&self,
bearer: T,
) -> Result<OAuthUser, jwks_client_update::error::Error> {
self.store
.verify(bearer.token())
.map(|v| OAuthUser::from(&JWT::from(v)))
}
}