From 850bab9a0a14626fae4daca623b398d0c11c21b4 Mon Sep 17 00:00:00 2001 From: cduvray Date: Wed, 6 Sep 2023 08:09:14 +0200 Subject: [PATCH 1/2] refactor: internal renaming (simplifications) - AsyncAuthorizationLayer -> AuthorizationLayer - AsyncAuthorizationService -> AuthorizationService - AsyncAuthorizer (trait) -> Authorize --- jwt-authorizer/src/authorizer.rs | 28 ++++++++++----------- jwt-authorizer/src/layer.rs | 42 ++++++++++++++++---------------- jwt-authorizer/tests/tests.rs | 6 ++--- jwt-authorizer/tests/tonic.rs | 6 ++--- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/jwt-authorizer/src/authorizer.rs b/jwt-authorizer/src/authorizer.rs index abb0d92..b3182b7 100644 --- a/jwt-authorizer/src/authorizer.rs +++ b/jwt-authorizer/src/authorizer.rs @@ -9,7 +9,7 @@ use serde::de::DeserializeOwned; use crate::{ error::{AuthError, InitError}, jwks::{key_store_manager::KeyStoreManager, KeyData, KeySource}, - layer::{self, AsyncAuthorizationLayer, JwtSource}, + layer::{self, AuthorizationLayer, JwtSource}, oidc, Refresh, RegisteredClaims, }; @@ -237,15 +237,15 @@ pub trait IntoLayer where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer; + fn into_layer(self) -> AuthorizationLayer; } impl IntoLayer for Vec> where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer { - AsyncAuthorizationLayer::new(self.into_iter().map(Arc::new).collect()) + fn into_layer(self) -> AuthorizationLayer { + AuthorizationLayer::new(self.into_iter().map(Arc::new).collect()) } } @@ -253,8 +253,8 @@ impl IntoLayer for Vec>> where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer { - AsyncAuthorizationLayer::new(self.into_iter().collect()) + fn into_layer(self) -> AuthorizationLayer { + AuthorizationLayer::new(self.into_iter().collect()) } } @@ -262,8 +262,8 @@ impl IntoLayer for [Authorizer; N] where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer { - AsyncAuthorizationLayer::new(self.into_iter().map(Arc::new).collect()) + fn into_layer(self) -> AuthorizationLayer { + AuthorizationLayer::new(self.into_iter().map(Arc::new).collect()) } } @@ -271,8 +271,8 @@ impl IntoLayer for [Arc>; N] where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer { - AsyncAuthorizationLayer::new(self.into_iter().collect()) + fn into_layer(self) -> AuthorizationLayer { + AuthorizationLayer::new(self.into_iter().collect()) } } @@ -280,8 +280,8 @@ impl IntoLayer for Authorizer where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer { - AsyncAuthorizationLayer::new(vec![Arc::new(self)]) + fn into_layer(self) -> AuthorizationLayer { + AuthorizationLayer::new(vec![Arc::new(self)]) } } @@ -289,8 +289,8 @@ impl IntoLayer for Arc> where C: Clone + DeserializeOwned + Send, { - fn into_layer(self) -> AsyncAuthorizationLayer { - AsyncAuthorizationLayer::new(vec![self]) + fn into_layer(self) -> AuthorizationLayer { + AuthorizationLayer::new(vec![self]) } } diff --git a/jwt-authorizer/src/layer.rs b/jwt-authorizer/src/layer.rs index a8b8fb5..1ea2864 100644 --- a/jwt-authorizer/src/layer.rs +++ b/jwt-authorizer/src/layer.rs @@ -183,12 +183,12 @@ where /// Build axum layer #[deprecated(since = "0.10.0", note = "please use `IntoLayer::into_layer()` instead")] - pub async fn layer(self) -> Result, InitError> { + pub async fn layer(self) -> Result, InitError> { let val = self.validation.unwrap_or_default(); let auth = Arc::new( Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await?, ); - Ok(AsyncAuthorizationLayer::new(vec![auth])) + Ok(AuthorizationLayer::new(vec![auth])) } pub async fn build(self) -> Result, InitError> { @@ -199,7 +199,7 @@ where } /// Trait for authorizing requests. -pub trait AsyncAuthorizer { +pub trait Authorize { type RequestBody; type Future: Future, AuthError>>; @@ -209,7 +209,7 @@ pub trait AsyncAuthorizer { fn authorize(&self, request: Request) -> Self::Future; } -impl AsyncAuthorizer for AsyncAuthorizationService +impl Authorize for AuthorizationService where B: Send + Sync + 'static, C: Clone + DeserializeOwned + Send + Sync + 'static, @@ -256,34 +256,34 @@ where // -------------- Layer ----------------- #[derive(Clone)] -pub struct AsyncAuthorizationLayer +pub struct AuthorizationLayer where C: Clone + DeserializeOwned + Send, { auths: Vec>>, } -impl AsyncAuthorizationLayer +impl AuthorizationLayer where C: Clone + DeserializeOwned + Send, { - pub fn new(auths: Vec>>) -> AsyncAuthorizationLayer { + pub fn new(auths: Vec>>) -> AuthorizationLayer { Self { auths } } } -impl Layer for AsyncAuthorizationLayer +impl Layer for AuthorizationLayer where C: Clone + DeserializeOwned + Send + Sync, { - type Service = AsyncAuthorizationService; + type Service = AuthorizationService; fn layer(&self, inner: S) -> Self::Service { - AsyncAuthorizationService::new(inner, self.auths.clone()) + AuthorizationService::new(inner, self.auths.clone()) } } -// ---------- AsyncAuthorizationService -------- +// ---------- AuthorizationService -------- /// Source of the bearer token #[derive(Clone)] @@ -301,7 +301,7 @@ pub enum JwtSource { } #[derive(Clone)] -pub struct AsyncAuthorizationService +pub struct AuthorizationService where C: Clone + DeserializeOwned + Send + Sync, { @@ -309,7 +309,7 @@ where pub auths: Vec>>, } -impl AsyncAuthorizationService +impl AuthorizationService where C: Clone + DeserializeOwned + Send + Sync, { @@ -328,19 +328,19 @@ where } } -impl AsyncAuthorizationService +impl AuthorizationService where C: Clone + DeserializeOwned + Send + Sync, { /// Authorize requests using a custom scheme. /// /// The `Authorization` header is required to have the value provided. - pub fn new(inner: S, auths: Vec>>) -> AsyncAuthorizationService { + pub fn new(inner: S, auths: Vec>>) -> AuthorizationService { Self { inner, auths } } } -impl Service> for AsyncAuthorizationService +impl Service> for AuthorizationService where ReqBody: Send + Sync + 'static, S: Service> + Clone, @@ -370,7 +370,7 @@ where } #[pin_project] -/// Response future for [`AsyncAuthorizationService`]. +/// Response future for [`AuthorizationService`]. pub struct ResponseFuture where S: Service>, @@ -378,7 +378,7 @@ where C: Clone + DeserializeOwned + Send + Sync + 'static, { #[pin] - state: State< as AsyncAuthorizer>::Future, S::Future>, + state: State< as Authorize>::Future, S::Future>, service: S, } @@ -433,7 +433,7 @@ where mod tests { use crate::{authorizer::Authorizer, IntoLayer, JwtAuthorizer, RegisteredClaims}; - use super::AsyncAuthorizationLayer; + use super::AuthorizationLayer; #[tokio::test] async fn auth_into_layer() { @@ -447,7 +447,7 @@ mod tests { let auth1 = JwtAuthorizer::from_secret("aaa").build().await.unwrap(); let auth2 = JwtAuthorizer::from_secret("bbb").build().await.unwrap(); - let layer: AsyncAuthorizationLayer = [auth1, auth2].into_layer(); + let layer: AuthorizationLayer = [auth1, auth2].into_layer(); assert_eq!(2, layer.auths.len()); } @@ -456,7 +456,7 @@ mod tests { let auth1 = JwtAuthorizer::from_secret("aaa").build().await.unwrap(); let auth2 = JwtAuthorizer::from_secret("bbb").build().await.unwrap(); - let layer: AsyncAuthorizationLayer = vec![auth1, auth2].into_layer(); + let layer: AuthorizationLayer = vec![auth1, auth2].into_layer(); assert_eq!(2, layer.auths.len()); } diff --git a/jwt-authorizer/tests/tests.rs b/jwt-authorizer/tests/tests.rs index 9ef8ea0..f2a89b6 100644 --- a/jwt-authorizer/tests/tests.rs +++ b/jwt-authorizer/tests/tests.rs @@ -14,7 +14,7 @@ mod tests { use http::{header, HeaderValue}; use jwt_authorizer::{ authorizer::Authorizer, - layer::{AsyncAuthorizationLayer, JwtSource}, + layer::{AuthorizationLayer, JwtSource}, validation::Validation, IntoLayer, JwtAuthorizer, JwtClaims, }; @@ -28,7 +28,7 @@ mod tests { sub: String, } - async fn app(layer: AsyncAuthorizationLayer) -> Router { + async fn app(layer: AuthorizationLayer) -> Router { Router::new().route("/public", get(|| async { "hello" })).route( "/protected", get(|JwtClaims(user): JwtClaims| async move { format!("hello: {}", user.sub) }).layer( @@ -48,7 +48,7 @@ mod tests { } async fn proteced_request_with_header_and_layer( - layer: AsyncAuthorizationLayer, + layer: AuthorizationLayer, header_name: &str, header_value: &str, ) -> Response { diff --git a/jwt-authorizer/tests/tonic.rs b/jwt-authorizer/tests/tonic.rs index da499a8..733eefc 100644 --- a/jwt-authorizer/tests/tonic.rs +++ b/jwt-authorizer/tests/tonic.rs @@ -3,7 +3,7 @@ use std::{sync::Once, task::Poll}; use axum::body::HttpBody; use futures_core::future::BoxFuture; use http::header::AUTHORIZATION; -use jwt_authorizer::{layer::AsyncAuthorizationService, IntoLayer, JwtAuthorizer}; +use jwt_authorizer::{layer::AuthorizationService, IntoLayer, JwtAuthorizer}; use serde::{Deserialize, Serialize}; use tonic::{server::UnaryService, transport::NamedService, IntoRequest, Status}; use tower::{buffer::Buffer, Service}; @@ -82,7 +82,7 @@ impl NamedService for GreeterServer { async fn app( jwt_auth: JwtAuthorizer, expected_sub: String, -) -> AsyncAuthorizationService>, User> { +) -> AuthorizationService>, User> { let layer = jwt_auth.build().await.unwrap().into_layer(); tonic::transport::Server::builder() .layer(layer) @@ -144,7 +144,7 @@ where } async fn make_protected_request( - app: AsyncAuthorizationService, + app: AuthorizationService, bearer: Option<&str>, message: &str, ) -> Result, Status> From 4a3077fa3a2cc5f5cf7c32835680b652f512a81d Mon Sep 17 00:00:00 2001 From: cduvray Date: Thu, 7 Sep 2023 07:23:35 +0200 Subject: [PATCH 2/2] refactor: extract JwtAuthorizer in builder.rs - JwtAuthorizer is in fact a builder, it may be renamed in future --- jwt-authorizer/src/builder.rs | 190 ++++++++++++++++++++++++++++++++++ jwt-authorizer/src/layer.rs | 188 +-------------------------------- jwt-authorizer/src/lib.rs | 3 +- 3 files changed, 194 insertions(+), 187 deletions(-) create mode 100644 jwt-authorizer/src/builder.rs diff --git a/jwt-authorizer/src/builder.rs b/jwt-authorizer/src/builder.rs new file mode 100644 index 0000000..a67ab3e --- /dev/null +++ b/jwt-authorizer/src/builder.rs @@ -0,0 +1,190 @@ +use std::sync::Arc; + +use serde::de::DeserializeOwned; + +use crate::{ + authorizer::{FnClaimsChecker, KeySourceType}, + error::InitError, + layer::{AuthorizationLayer, JwtSource}, + Authorizer, Refresh, RefreshStrategy, RegisteredClaims, Validation, +}; + +/// Authorizer Layer builder +/// +/// - initialisation of the Authorizer from jwks, rsa, ed, ec or secret +/// - can define a checker (jwt claims check) +pub struct JwtAuthorizer +where + C: Clone + DeserializeOwned, +{ + key_source_type: KeySourceType, + refresh: Option, + claims_checker: Option>, + validation: Option, + jwt_source: JwtSource, +} + +/// authorization layer builder +impl JwtAuthorizer +where + C: Clone + DeserializeOwned + Send + Sync, +{ + /// Builds Authorizer Layer from a OpenId Connect discover metadata + pub fn from_oidc(issuer: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::Discovery(issuer.to_string()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a JWKS endpoint + pub fn from_jwks_url(url: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::Jwks(url.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a RSA PEM file + pub fn from_rsa_pem(path: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::RSA(path.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from an RSA PEM raw text + pub fn from_rsa_pem_text(text: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::RSAString(text.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a EC PEM file + pub fn from_ec_pem(path: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::EC(path.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a EC PEM raw text + pub fn from_ec_pem_text(text: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::ECString(text.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a EC PEM file + pub fn from_ed_pem(path: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::ED(path.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a EC PEM raw text + pub fn from_ed_pem_text(text: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::EDString(text.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Builds Authorizer Layer from a secret phrase + pub fn from_secret(secret: &str) -> JwtAuthorizer { + JwtAuthorizer { + key_source_type: KeySourceType::Secret(secret.to_owned()), + refresh: Default::default(), + claims_checker: None, + validation: None, + jwt_source: JwtSource::AuthorizationHeader, + } + } + + /// Refreshes configuration for jwk store + pub fn refresh(mut self, refresh: Refresh) -> JwtAuthorizer { + if self.refresh.is_some() { + tracing::warn!("More than one refresh configuration found!"); + } + self.refresh = Some(refresh); + self + } + + /// no refresh, jwks will be loaded juste once + pub fn no_refresh(mut self) -> JwtAuthorizer { + if self.refresh.is_some() { + tracing::warn!("More than one refresh configuration found!"); + } + self.refresh = Some(Refresh { + strategy: RefreshStrategy::NoRefresh, + ..Default::default() + }); + self + } + + /// configures token content check (custom function), if false a 403 will be sent. + /// (AuthError::InvalidClaims()) + pub fn check(mut self, checker_fn: fn(&C) -> bool) -> JwtAuthorizer { + self.claims_checker = Some(FnClaimsChecker { checker_fn }); + + self + } + + pub fn validation(mut self, validation: Validation) -> JwtAuthorizer { + self.validation = Some(validation); + + self + } + + /// configures the source of the bearer token + /// + /// (default: AuthorizationHeader) + pub fn jwt_source(mut self, src: JwtSource) -> JwtAuthorizer { + self.jwt_source = src; + + self + } + + /// Build axum layer + #[deprecated(since = "0.10.0", note = "please use `IntoLayer::into_layer()` instead")] + pub async fn layer(self) -> Result, InitError> { + let val = self.validation.unwrap_or_default(); + let auth = Arc::new( + Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await?, + ); + Ok(AuthorizationLayer::new(vec![auth])) + } + + pub async fn build(self) -> Result, InitError> { + let val = self.validation.unwrap_or_default(); + + Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await + } +} diff --git a/jwt-authorizer/src/layer.rs b/jwt-authorizer/src/layer.rs index 1ea2864..83297a3 100644 --- a/jwt-authorizer/src/layer.rs +++ b/jwt-authorizer/src/layer.rs @@ -11,192 +11,8 @@ use std::task::{Context, Poll}; use tower_layer::Layer; use tower_service::Service; -use crate::authorizer::{Authorizer, FnClaimsChecker, KeySourceType}; -use crate::claims::RegisteredClaims; -use crate::error::InitError; -use crate::jwks::key_store_manager::Refresh; -use crate::validation::Validation; -use crate::{AuthError, RefreshStrategy}; - -/// Authorizer Layer builder -/// -/// - initialisation of the Authorizer from jwks, rsa, ed, ec or secret -/// - can define a checker (jwt claims check) -pub struct JwtAuthorizer -where - C: Clone + DeserializeOwned, -{ - key_source_type: KeySourceType, - refresh: Option, - claims_checker: Option>, - validation: Option, - jwt_source: JwtSource, -} - -/// authorization layer builder -impl JwtAuthorizer -where - C: Clone + DeserializeOwned + Send + Sync, -{ - /// Builds Authorizer Layer from a OpenId Connect discover metadata - pub fn from_oidc(issuer: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::Discovery(issuer.to_string()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a JWKS endpoint - pub fn from_jwks_url(url: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::Jwks(url.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a RSA PEM file - pub fn from_rsa_pem(path: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::RSA(path.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from an RSA PEM raw text - pub fn from_rsa_pem_text(text: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::RSAString(text.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a EC PEM file - pub fn from_ec_pem(path: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::EC(path.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a EC PEM raw text - pub fn from_ec_pem_text(text: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::ECString(text.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a EC PEM file - pub fn from_ed_pem(path: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::ED(path.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a EC PEM raw text - pub fn from_ed_pem_text(text: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::EDString(text.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Builds Authorizer Layer from a secret phrase - pub fn from_secret(secret: &str) -> JwtAuthorizer { - JwtAuthorizer { - key_source_type: KeySourceType::Secret(secret.to_owned()), - refresh: Default::default(), - claims_checker: None, - validation: None, - jwt_source: JwtSource::AuthorizationHeader, - } - } - - /// Refreshes configuration for jwk store - pub fn refresh(mut self, refresh: Refresh) -> JwtAuthorizer { - if self.refresh.is_some() { - tracing::warn!("More than one refresh configuration found!"); - } - self.refresh = Some(refresh); - self - } - - /// no refresh, jwks will be loaded juste once - pub fn no_refresh(mut self) -> JwtAuthorizer { - if self.refresh.is_some() { - tracing::warn!("More than one refresh configuration found!"); - } - self.refresh = Some(Refresh { - strategy: RefreshStrategy::NoRefresh, - ..Default::default() - }); - self - } - - /// configures token content check (custom function), if false a 403 will be sent. - /// (AuthError::InvalidClaims()) - pub fn check(mut self, checker_fn: fn(&C) -> bool) -> JwtAuthorizer { - self.claims_checker = Some(FnClaimsChecker { checker_fn }); - - self - } - - pub fn validation(mut self, validation: Validation) -> JwtAuthorizer { - self.validation = Some(validation); - - self - } - - /// configures the source of the bearer token - /// - /// (default: AuthorizationHeader) - pub fn jwt_source(mut self, src: JwtSource) -> JwtAuthorizer { - self.jwt_source = src; - - self - } - - /// Build axum layer - #[deprecated(since = "0.10.0", note = "please use `IntoLayer::into_layer()` instead")] - pub async fn layer(self) -> Result, InitError> { - let val = self.validation.unwrap_or_default(); - let auth = Arc::new( - Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await?, - ); - Ok(AuthorizationLayer::new(vec![auth])) - } - - pub async fn build(self) -> Result, InitError> { - let val = self.validation.unwrap_or_default(); - - Authorizer::build(self.key_source_type, self.claims_checker, self.refresh, val, self.jwt_source).await - } -} +use crate::authorizer::Authorizer; +use crate::AuthError; /// Trait for authorizing requests. pub trait Authorize { diff --git a/jwt-authorizer/src/lib.rs b/jwt-authorizer/src/lib.rs index 1940777..b5cd5ca 100644 --- a/jwt-authorizer/src/lib.rs +++ b/jwt-authorizer/src/lib.rs @@ -6,12 +6,13 @@ use serde::de::DeserializeOwned; pub use self::error::AuthError; pub use authorizer::{Authorizer, IntoLayer}; +pub use builder::JwtAuthorizer; pub use claims::{NumericDate, OneOrArray, RegisteredClaims}; pub use jwks::key_store_manager::{Refresh, RefreshStrategy}; -pub use layer::JwtAuthorizer; pub use validation::Validation; pub mod authorizer; +pub mod builder; pub mod claims; pub mod error; pub mod jwks;