mirror of
https://github.com/TECHNOFAB11/jwt-authorizer.git
synced 2025-12-15 01:13:52 +01:00
chore: fmt
This commit is contained in:
parent
ec02b70a99
commit
d8fb138d46
8 changed files with 86 additions and 78 deletions
|
|
@ -5,7 +5,8 @@ use serde::de::DeserializeOwned;
|
|||
|
||||
use crate::{
|
||||
error::{AuthError, InitError},
|
||||
jwks::{key_store_manager::KeyStoreManager, KeySource}, Refresh,
|
||||
jwks::{key_store_manager::KeyStoreManager, KeySource},
|
||||
Refresh,
|
||||
};
|
||||
|
||||
pub trait ClaimsChecker<C> {
|
||||
|
|
@ -66,7 +67,10 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn from(key_source_type: &KeySourceType, claims_checker: Option<FnClaimsChecker<C>>) -> Result<Authorizer<C>, InitError> {
|
||||
pub(crate) fn from(
|
||||
key_source_type: &KeySourceType,
|
||||
claims_checker: Option<FnClaimsChecker<C>>,
|
||||
) -> Result<Authorizer<C>, InitError> {
|
||||
let key = match key_source_type {
|
||||
KeySourceType::RSA(path) => DecodingKey::from_rsa_pem(&read_data(path.as_str())?)?,
|
||||
KeySourceType::EC(path) => DecodingKey::from_ec_der(&read_data(path.as_str())?),
|
||||
|
|
@ -81,7 +85,11 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn from_jwks_url(url: &str, claims_checker: Option<FnClaimsChecker<C>>, refresh: Refresh) -> Result<Authorizer<C>, InitError> {
|
||||
pub(crate) fn from_jwks_url(
|
||||
url: &str,
|
||||
claims_checker: Option<FnClaimsChecker<C>>,
|
||||
refresh: Refresh,
|
||||
) -> Result<Authorizer<C>, InitError> {
|
||||
let key_store_manager = KeyStoreManager::new(url, refresh);
|
||||
Ok(Authorizer {
|
||||
key_source: KeySource::KeyStoreSource(key_store_manager),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use axum::{
|
||||
body::{self, BoxBody, Empty},
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response}, body::{self, Empty, BoxBody},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use http::header;
|
||||
use jsonwebtoken::Algorithm;
|
||||
|
|
@ -47,7 +48,7 @@ pub enum AuthError {
|
|||
InvalidClaims(),
|
||||
}
|
||||
|
||||
fn response_wwwauth(status: StatusCode, bearer: &str) -> Response<BoxBody> {
|
||||
fn response_wwwauth(status: StatusCode, bearer: &str) -> Response<BoxBody> {
|
||||
let mut res = Response::new(body::boxed(Empty::new()));
|
||||
*res.status_mut() = status;
|
||||
let h = if bearer.is_empty() {
|
||||
|
|
@ -60,7 +61,7 @@ fn response_wwwauth(status: StatusCode, bearer: &str) -> Response<BoxBody> {
|
|||
res
|
||||
}
|
||||
|
||||
fn response_500() -> Response<BoxBody> {
|
||||
fn response_500() -> Response<BoxBody> {
|
||||
let mut res = Response::new(body::boxed(Empty::new()));
|
||||
*res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
|
||||
|
|
@ -71,38 +72,44 @@ fn response_500() -> Response<BoxBody> {
|
|||
impl IntoResponse for AuthError {
|
||||
fn into_response(self) -> Response {
|
||||
let resp = match self {
|
||||
AuthError::JwksRefreshError(err) => {
|
||||
AuthError::JwksRefreshError(err) => {
|
||||
tracing::error!("AuthErrors::JwksRefreshError: {}", err);
|
||||
response_500()
|
||||
},
|
||||
AuthError::InvalidKey(err) => {
|
||||
tracing::error!("AuthErrors::InvalidKey: {}", err);
|
||||
}
|
||||
AuthError::InvalidKey(err) => {
|
||||
tracing::error!("AuthErrors::InvalidKey: {}", err);
|
||||
response_500()
|
||||
},
|
||||
}
|
||||
AuthError::JwksSerialisationError(err) => {
|
||||
tracing::error!("AuthErrors::JwksSerialisationError: {}", err);
|
||||
tracing::error!("AuthErrors::JwksSerialisationError: {}", err);
|
||||
response_500()
|
||||
},
|
||||
}
|
||||
AuthError::InvalidKeyAlg(err) => {
|
||||
debug!("AuthErrors::InvalidKeyAlg: {:?}", err);
|
||||
response_wwwauth(StatusCode::UNAUTHORIZED, "error=\"invalid_token\", error_description=\"invalid key algorithm\"")
|
||||
},
|
||||
response_wwwauth(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"error=\"invalid_token\", error_description=\"invalid key algorithm\"",
|
||||
)
|
||||
}
|
||||
AuthError::InvalidKid(err) => {
|
||||
debug!("AuthErrors::InvalidKid: {}", err);
|
||||
response_wwwauth(StatusCode::UNAUTHORIZED, "error=\"invalid_token\", error_description=\"invalid kid\"")
|
||||
},
|
||||
response_wwwauth(
|
||||
StatusCode::UNAUTHORIZED,
|
||||
"error=\"invalid_token\", error_description=\"invalid kid\"",
|
||||
)
|
||||
}
|
||||
AuthError::InvalidToken(err) => {
|
||||
debug!("AuthErrors::InvalidToken: {}", err);
|
||||
response_wwwauth(StatusCode::UNAUTHORIZED, "error=\"invalid_token\"")
|
||||
},
|
||||
}
|
||||
AuthError::MissingToken() => {
|
||||
debug!("AuthErrors::MissingToken");
|
||||
response_wwwauth(StatusCode::UNAUTHORIZED, "")
|
||||
},
|
||||
}
|
||||
AuthError::InvalidClaims() => {
|
||||
debug!("AuthErrors::InvalidClaims");
|
||||
response_wwwauth(StatusCode::FORBIDDEN, "error=\"insufficient_scope\"")
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
resp
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use crate::error::AuthError;
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum RefreshStrategy {
|
||||
|
||||
/// refresh periodicaly
|
||||
Interval,
|
||||
|
||||
|
|
@ -37,7 +36,7 @@ pub struct Refresh {
|
|||
|
||||
impl Default for Refresh {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
Self {
|
||||
strategy: RefreshStrategy::KeyNotFound,
|
||||
refresh_interval: Duration::from_secs(600),
|
||||
minimal_refresh_interval: Duration::from_secs(30),
|
||||
|
|
@ -81,17 +80,15 @@ impl KeyStoreManager {
|
|||
let mut ks_gard = kstore.lock().await;
|
||||
let key = match self.refresh.strategy {
|
||||
RefreshStrategy::Interval => {
|
||||
if ks_gard.should_refresh(self.refresh.refresh_interval) && ks_gard.can_refresh(self.refresh.minimal_refresh_interval, self.refresh.retry_interval) {
|
||||
if ks_gard.should_refresh(self.refresh.refresh_interval)
|
||||
&& ks_gard.can_refresh(self.refresh.minimal_refresh_interval, self.refresh.retry_interval)
|
||||
{
|
||||
ks_gard.refresh(&self.key_url, &[]).await?;
|
||||
}
|
||||
if let Some(ref kid) = header.kid {
|
||||
ks_gard
|
||||
.find_kid(kid)
|
||||
.ok_or_else(|| AuthError::InvalidKid(kid.to_owned()))?
|
||||
ks_gard.find_kid(kid).ok_or_else(|| AuthError::InvalidKid(kid.to_owned()))?
|
||||
} else {
|
||||
ks_gard
|
||||
.find_alg(&header.alg)
|
||||
.ok_or(AuthError::InvalidKeyAlg(header.alg))?
|
||||
ks_gard.find_alg(&header.alg).ok_or(AuthError::InvalidKeyAlg(header.alg))?
|
||||
}
|
||||
}
|
||||
RefreshStrategy::KeyNotFound => {
|
||||
|
|
@ -101,11 +98,8 @@ impl KeyStoreManager {
|
|||
jwk
|
||||
} else if ks_gard.can_refresh(self.refresh.minimal_refresh_interval, self.refresh.retry_interval) {
|
||||
ks_gard.refresh(&self.key_url, &[("kid", kid)]).await?;
|
||||
ks_gard
|
||||
.find_kid(kid)
|
||||
.ok_or_else(|| AuthError::InvalidKid(kid.to_owned()))?
|
||||
ks_gard.find_kid(kid).ok_or_else(|| AuthError::InvalidKid(kid.to_owned()))?
|
||||
} else {
|
||||
|
||||
return Err(AuthError::InvalidKid(kid.to_owned()));
|
||||
}
|
||||
} else {
|
||||
|
|
@ -119,8 +113,7 @@ impl KeyStoreManager {
|
|||
&self.key_url,
|
||||
&[(
|
||||
"alg",
|
||||
&serde_json::to_string(&header.alg)
|
||||
.map_err(|_| AuthError::InvalidKeyAlg(header.alg))?,
|
||||
&serde_json::to_string(&header.alg).map_err(|_| AuthError::InvalidKeyAlg(header.alg))?,
|
||||
)],
|
||||
)
|
||||
.await?;
|
||||
|
|
@ -131,19 +124,15 @@ impl KeyStoreManager {
|
|||
return Err(AuthError::InvalidKeyAlg(header.alg));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
RefreshStrategy::NoRefresh => {
|
||||
if ks_gard.load_time.is_none() {
|
||||
ks_gard.refresh(&self.key_url, &[]).await?;
|
||||
}
|
||||
if let Some(ref kid) = header.kid {
|
||||
ks_gard
|
||||
.find_kid(kid)
|
||||
.ok_or_else(|| AuthError::InvalidKid(kid.to_owned()))?
|
||||
ks_gard.find_kid(kid).ok_or_else(|| AuthError::InvalidKid(kid.to_owned()))?
|
||||
} else {
|
||||
ks_gard
|
||||
.find_alg(&header.alg)
|
||||
.ok_or(AuthError::InvalidKeyAlg(header.alg))?
|
||||
ks_gard.find_alg(&header.alg).ok_or(AuthError::InvalidKeyAlg(header.alg))?
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -228,8 +217,8 @@ mod tests {
|
|||
Mock, MockServer, ResponseTemplate,
|
||||
};
|
||||
|
||||
use crate::{RefreshStrategy, Refresh};
|
||||
use crate::jwks::key_store_manager::{KeyStore, KeyStoreManager};
|
||||
use crate::{Refresh, RefreshStrategy};
|
||||
|
||||
#[test]
|
||||
fn keystore_should_refresh() {
|
||||
|
|
@ -252,7 +241,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn keystore_can_refresh() {
|
||||
|
||||
// FAIL, NO LOAD
|
||||
let ks = KeyStore {
|
||||
jwks: jsonwebtoken::jwk::JwkSet { keys: vec![] },
|
||||
|
|
@ -343,7 +331,11 @@ mod tests {
|
|||
|
||||
let ksm = KeyStoreManager::new(
|
||||
&mock_server.uri(),
|
||||
Refresh {strategy: RefreshStrategy::Interval, refresh_interval: Duration::from_secs(3000), ..Default::default()}
|
||||
Refresh {
|
||||
strategy: RefreshStrategy::Interval,
|
||||
refresh_interval: Duration::from_secs(3000),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let r = ksm.get_key(&Header::new(Algorithm::EdDSA)).await;
|
||||
assert!(r.is_ok());
|
||||
|
|
@ -368,7 +360,11 @@ mod tests {
|
|||
|
||||
let mut ksm = KeyStoreManager::new(
|
||||
&mock_server.uri(),
|
||||
Refresh {strategy: RefreshStrategy::KeyNotFound, ..Default::default()});
|
||||
Refresh {
|
||||
strategy: RefreshStrategy::KeyNotFound,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
// STEP 1: initial (lazy) reloading
|
||||
let r = ksm.get_key(&build_header("key-ed", Algorithm::EdDSA)).await;
|
||||
|
|
@ -440,7 +436,11 @@ mod tests {
|
|||
|
||||
let ksm = KeyStoreManager::new(
|
||||
&mock_server.uri(),
|
||||
Refresh {strategy: RefreshStrategy::NoRefresh, ..Default::default()});
|
||||
Refresh {
|
||||
strategy: RefreshStrategy::NoRefresh,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
// STEP 1: initial (lazy) reloading
|
||||
let r = ksm.get_key(&build_header("key-ed", Algorithm::EdDSA)).await;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use axum::body::BoxBody;
|
||||
use axum::http::Request;
|
||||
use axum::response::{Response, IntoResponse};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use futures_core::ready;
|
||||
use futures_util::future::BoxFuture;
|
||||
use headers::authorization::Bearer;
|
||||
|
|
@ -14,10 +14,10 @@ use std::task::{Context, Poll};
|
|||
use tower_layer::Layer;
|
||||
use tower_service::Service;
|
||||
|
||||
use crate::{AuthError, RefreshStrategy};
|
||||
use crate::authorizer::{Authorizer, FnClaimsChecker, KeySourceType};
|
||||
use crate::error::InitError;
|
||||
use crate::jwks::key_store_manager::Refresh;
|
||||
use crate::{AuthError, RefreshStrategy};
|
||||
|
||||
/// Authorizer Layer builder
|
||||
///
|
||||
|
|
@ -118,11 +118,11 @@ where
|
|||
KeySourceType::RSA(_) | KeySourceType::EC(_) | KeySourceType::ED(_) | KeySourceType::Secret(_) => {
|
||||
Arc::new(Authorizer::from(key_source_type, self.claims_checker.clone())?)
|
||||
}
|
||||
KeySourceType::Jwks(url) => {
|
||||
Arc::new(
|
||||
Authorizer::from_jwks_url(
|
||||
url.as_str(), self.claims_checker.clone(), self.refresh.unwrap_or_default())?)
|
||||
}
|
||||
KeySourceType::Jwks(url) => Arc::new(Authorizer::from_jwks_url(
|
||||
url.as_str(),
|
||||
self.claims_checker.clone(),
|
||||
self.refresh.unwrap_or_default(),
|
||||
)?),
|
||||
}
|
||||
} else {
|
||||
return Err(InitError::BuilderError(
|
||||
|
|
@ -162,16 +162,14 @@ where
|
|||
Box::pin(async move {
|
||||
if let Some(bearer) = bearer_o {
|
||||
match authorizer.check_auth(bearer.token()).await {
|
||||
Ok(token_data) => {
|
||||
Ok(token_data) => {
|
||||
// Set `token_data` as a request extension so it can be accessed by other
|
||||
// services down the stack.
|
||||
request.extensions_mut().insert(token_data);
|
||||
|
||||
|
||||
Ok(request)
|
||||
},
|
||||
Err(err) => {
|
||||
Err(err.into_response())
|
||||
}
|
||||
Err(err) => Err(err.into_response()),
|
||||
}
|
||||
} else {
|
||||
Err(AuthError::MissingToken().into_response())
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use jsonwebtoken::TokenData;
|
|||
use serde::de::DeserializeOwned;
|
||||
|
||||
pub use self::error::AuthError;
|
||||
pub use layer::JwtAuthorizer;
|
||||
pub use jwks::key_store_manager::{Refresh, RefreshStrategy};
|
||||
pub use layer::JwtAuthorizer;
|
||||
|
||||
pub mod authorizer;
|
||||
pub mod error;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue