mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 17:19:15 +08:00
refactor(router): appstate as trait in authentication (#588)
This commit is contained in:
@ -29,16 +29,19 @@ where
|
|||||||
pub struct ApiKeyAuth;
|
pub struct ApiKeyAuth;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AuthenticateAndFetch<storage::MerchantAccount, AppState> for ApiKeyAuth {
|
impl<A> AuthenticateAndFetch<storage::MerchantAccount, A> for ApiKeyAuth
|
||||||
|
where
|
||||||
|
A: AppStateInfo + Sync,
|
||||||
|
{
|
||||||
async fn authenticate_and_fetch(
|
async fn authenticate_and_fetch(
|
||||||
&self,
|
&self,
|
||||||
request_headers: &HeaderMap,
|
request_headers: &HeaderMap,
|
||||||
state: &AppState,
|
state: &A,
|
||||||
) -> RouterResult<storage::MerchantAccount> {
|
) -> RouterResult<storage::MerchantAccount> {
|
||||||
let api_key =
|
let api_key =
|
||||||
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
||||||
state
|
state
|
||||||
.store
|
.store()
|
||||||
.find_merchant_account_by_api_key(api_key)
|
.find_merchant_account_by_api_key(api_key)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::Unauthorized)
|
.change_context(errors::ApiErrorResponse::Unauthorized)
|
||||||
@ -50,15 +53,19 @@ impl AuthenticateAndFetch<storage::MerchantAccount, AppState> for ApiKeyAuth {
|
|||||||
pub struct AdminApiAuth;
|
pub struct AdminApiAuth;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AuthenticateAndFetch<(), AppState> for AdminApiAuth {
|
impl<A> AuthenticateAndFetch<(), A> for AdminApiAuth
|
||||||
|
where
|
||||||
|
A: AppStateInfo + Sync,
|
||||||
|
{
|
||||||
async fn authenticate_and_fetch(
|
async fn authenticate_and_fetch(
|
||||||
&self,
|
&self,
|
||||||
request_headers: &HeaderMap,
|
request_headers: &HeaderMap,
|
||||||
state: &AppState,
|
state: &A,
|
||||||
) -> RouterResult<()> {
|
) -> RouterResult<()> {
|
||||||
let admin_api_key =
|
let admin_api_key =
|
||||||
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
get_api_key(request_headers).change_context(errors::ApiErrorResponse::Unauthorized)?;
|
||||||
if admin_api_key != state.conf.secrets.admin_api_key {
|
let conf = state.conf();
|
||||||
|
if admin_api_key != conf.secrets.admin_api_key {
|
||||||
Err(report!(errors::ApiErrorResponse::Unauthorized)
|
Err(report!(errors::ApiErrorResponse::Unauthorized)
|
||||||
.attach_printable("Admin Authentication Failure"))?;
|
.attach_printable("Admin Authentication Failure"))?;
|
||||||
}
|
}
|
||||||
@ -115,11 +122,14 @@ struct JwtAuthPayloadFetchUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AuthenticateAndFetch<(), AppState> for JWTAuth {
|
impl<A> AuthenticateAndFetch<(), A> for JWTAuth
|
||||||
|
where
|
||||||
|
A: AppStateInfo + Sync,
|
||||||
|
{
|
||||||
async fn authenticate_and_fetch(
|
async fn authenticate_and_fetch(
|
||||||
&self,
|
&self,
|
||||||
request_headers: &HeaderMap,
|
request_headers: &HeaderMap,
|
||||||
state: &AppState,
|
state: &A,
|
||||||
) -> RouterResult<()> {
|
) -> RouterResult<()> {
|
||||||
let mut token = get_jwt(request_headers)?;
|
let mut token = get_jwt(request_headers)?;
|
||||||
token = strip_jwt_token(token)?;
|
token = strip_jwt_token(token)?;
|
||||||
@ -133,17 +143,20 @@ struct JwtAuthPayloadFetchMerchantAccount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl AuthenticateAndFetch<storage::MerchantAccount, AppState> for JWTAuth {
|
impl<A> AuthenticateAndFetch<storage::MerchantAccount, A> for JWTAuth
|
||||||
|
where
|
||||||
|
A: AppStateInfo + Sync,
|
||||||
|
{
|
||||||
async fn authenticate_and_fetch(
|
async fn authenticate_and_fetch(
|
||||||
&self,
|
&self,
|
||||||
request_headers: &HeaderMap,
|
request_headers: &HeaderMap,
|
||||||
state: &AppState,
|
state: &A,
|
||||||
) -> RouterResult<storage::MerchantAccount> {
|
) -> RouterResult<storage::MerchantAccount> {
|
||||||
let mut token = get_jwt(request_headers)?;
|
let mut token = get_jwt(request_headers)?;
|
||||||
token = strip_jwt_token(token)?;
|
token = strip_jwt_token(token)?;
|
||||||
let payload = decode_jwt::<JwtAuthPayloadFetchMerchantAccount>(token, state)?;
|
let payload = decode_jwt::<JwtAuthPayloadFetchMerchantAccount>(token, state)?;
|
||||||
state
|
state
|
||||||
.store
|
.store()
|
||||||
.find_merchant_account_by_merchant_id(&payload.merchant_id)
|
.find_merchant_account_by_merchant_id(&payload.merchant_id)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InvalidJwtToken)
|
.change_context(errors::ApiErrorResponse::InvalidJwtToken)
|
||||||
@ -250,15 +263,16 @@ pub async fn is_ephemeral_auth(
|
|||||||
Ok(Box::new(MerchantIdAuth(ephemeral_key.merchant_id)))
|
Ok(Box::new(MerchantIdAuth(ephemeral_key.merchant_id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_jwt_auth(headers: &HeaderMap) -> bool {
|
pub fn is_jwt_auth(headers: &HeaderMap) -> bool {
|
||||||
headers.get(crate::headers::AUTHORIZATION).is_some()
|
headers.get(crate::headers::AUTHORIZATION).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_jwt<T>(token: &str, state: &AppState) -> RouterResult<T>
|
pub fn decode_jwt<T>(token: &str, state: &impl AppStateInfo) -> RouterResult<T>
|
||||||
where
|
where
|
||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
let secret = state.conf.secrets.jwt_secret.as_bytes();
|
let conf = state.conf();
|
||||||
|
let secret = conf.secrets.jwt_secret.as_bytes();
|
||||||
let key = DecodingKey::from_secret(secret);
|
let key = DecodingKey::from_secret(secret);
|
||||||
decode::<T>(token, &key, &Validation::new(Algorithm::HS256))
|
decode::<T>(token, &key, &Validation::new(Algorithm::HS256))
|
||||||
.map(|decoded| decoded.claims)
|
.map(|decoded| decoded.claims)
|
||||||
@ -266,7 +280,7 @@ where
|
|||||||
.change_context(errors::ApiErrorResponse::InvalidJwtToken)
|
.change_context(errors::ApiErrorResponse::InvalidJwtToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_api_key(headers: &HeaderMap) -> RouterResult<&str> {
|
pub fn get_api_key(headers: &HeaderMap) -> RouterResult<&str> {
|
||||||
headers
|
headers
|
||||||
.get("api-key")
|
.get("api-key")
|
||||||
.get_required_value("api-key")?
|
.get_required_value("api-key")?
|
||||||
@ -276,7 +290,7 @@ fn get_api_key(headers: &HeaderMap) -> RouterResult<&str> {
|
|||||||
.attach_printable("Failed to convert API key to string")
|
.attach_printable("Failed to convert API key to string")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_jwt(headers: &HeaderMap) -> RouterResult<&str> {
|
pub fn get_jwt(headers: &HeaderMap) -> RouterResult<&str> {
|
||||||
headers
|
headers
|
||||||
.get(crate::headers::AUTHORIZATION)
|
.get(crate::headers::AUTHORIZATION)
|
||||||
.get_required_value(crate::headers::AUTHORIZATION)?
|
.get_required_value(crate::headers::AUTHORIZATION)?
|
||||||
@ -286,7 +300,7 @@ fn get_jwt(headers: &HeaderMap) -> RouterResult<&str> {
|
|||||||
.attach_printable("Failed to convert JWT token to string")
|
.attach_printable("Failed to convert JWT token to string")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strip_jwt_token(token: &str) -> RouterResult<&str> {
|
pub fn strip_jwt_token(token: &str) -> RouterResult<&str> {
|
||||||
token
|
token
|
||||||
.strip_prefix("Bearer ")
|
.strip_prefix("Bearer ")
|
||||||
.ok_or_else(|| errors::ApiErrorResponse::InvalidJwtToken.into())
|
.ok_or_else(|| errors::ApiErrorResponse::InvalidJwtToken.into())
|
||||||
|
|||||||
@ -64,7 +64,7 @@ pub mod error_parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn custom_json_error_handler(err: JsonPayloadError, _req: &HttpRequest) -> Error {
|
pub fn custom_json_error_handler(err: JsonPayloadError, _req: &HttpRequest) -> Error {
|
||||||
actix_web::error::Error::from(CustomJsonError { err })
|
actix_web::error::Error::from(CustomJsonError { err })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user