diff --git a/drasil-hugin/src/protocol/smartcontract/mod.rs b/drasil-hugin/src/protocol/smartcontract/mod.rs index e42c054d..e28c28cb 100644 --- a/drasil-hugin/src/protocol/smartcontract/mod.rs +++ b/drasil-hugin/src/protocol/smartcontract/mod.rs @@ -1,2 +1 @@ pub(crate) mod nft_marketplace; -pub(crate) mod worldmobile; diff --git a/services/heimdallr-v2/src/error.rs b/services/heimdallr-v2/src/error.rs index d4b553c1..5c099328 100644 --- a/services/heimdallr-v2/src/error.rs +++ b/services/heimdallr-v2/src/error.rs @@ -1,7 +1,11 @@ //! This module defines the error types. -use std::io; +use std::{fmt, io}; +use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; +use axum::Json; +use serde_json::json; use thiserror; /// Result an alias for the `Result` type with `self::Error` as error @@ -17,4 +21,47 @@ pub enum Error { /// Improperly configuration errors #[error(transparent)] ConfigError(#[from] config::ConfigError), + + /// This is JWT related errors. + #[error(transparent)] + JwtError(#[from] jsonwebtoken::errors::Error), +} + +/// Authentication errors type. +#[derive(Debug, thiserror::Error)] +pub enum AuthError { + /// This is the error when the credentials do not match. + WrongCredentials, + + /// This is the error when the credential is missing. + MissingCredentials, + + /// This is the error when the credential is invalid. + InvalidToken, +} + +impl IntoResponse for AuthError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + AuthError::WrongCredentials => (StatusCode::UNAUTHORIZED, "wrong credentials"), + AuthError::MissingCredentials => (StatusCode::BAD_REQUEST, "missing credentials"), + AuthError::InvalidToken => (StatusCode::BAD_REQUEST, "invalid token"), + }; + let body = Json(json!({ + "error": error_message, + })); + (status, body).into_response() + } +} + +impl fmt::Display for AuthError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::InvalidToken => "invalid token", + Self::MissingCredentials => "missing token", + Self::WrongCredentials => "wrong credential", + }; + + write!(f, "{s}") + } } diff --git a/services/heimdallr-v2/src/extractor.rs b/services/heimdallr-v2/src/extractor.rs new file mode 100644 index 00000000..39f2d845 --- /dev/null +++ b/services/heimdallr-v2/src/extractor.rs @@ -0,0 +1,2 @@ +//! Extractors module. +mod claims; diff --git a/services/heimdallr-v2/src/extractor/claims.rs b/services/heimdallr-v2/src/extractor/claims.rs new file mode 100644 index 00000000..40b80567 --- /dev/null +++ b/services/heimdallr-v2/src/extractor/claims.rs @@ -0,0 +1,55 @@ +//! Claim extractor +//! +//! This module implements the claim extractor from a bearer token. +use axum::extract::{FromRef, FromRequestParts}; +use axum::headers::authorization::{Authorization, Bearer}; +use axum::http::request::Parts; +use axum::{async_trait, RequestPartsExt, TypedHeader}; +use jsonwebtoken::{decode, Validation}; +use serde::{Deserialize, Serialize}; + +use crate::error::AuthError; +use crate::state::AppState; + +/// Claims represents the claims data from JWT +#[derive(Debug, Deserialize, Serialize)] +#[allow(clippy::missing_docs_in_private_items)] +pub struct Claims { + sub: String, + exp: usize, +} + +impl Claims { + /// Return the customer ID in this claim. + pub fn get_customer_id(&self) -> Result { + self.sub.parse().map_err(|_| AuthError::WrongCredentials) + } +} + +#[async_trait] +impl FromRequestParts for Claims +where + AppState: FromRef, + S: Send + Sync, +{ + type Rejection = AuthError; + + async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + // Extract the token from the authorization header + let TypedHeader(Authorization(bearer)) = parts + .extract::>>() + .await + .map_err(|_| AuthError::MissingCredentials)?; + // Decode the user data + + let app_state = AppState::from_ref(state); + let token_data = decode::( + bearer.token(), + &app_state.jwt_decoding_key, + &Validation::default(), + ) + .map_err(|_| AuthError::InvalidToken)?; + + Ok(token_data.claims) + } +} diff --git a/services/heimdallr-v2/src/lib.rs b/services/heimdallr-v2/src/lib.rs index 1ca62cc8..9c3d240b 100644 --- a/services/heimdallr-v2/src/lib.rs +++ b/services/heimdallr-v2/src/lib.rs @@ -13,5 +13,6 @@ pub mod bootstrap; pub mod error; +mod extractor; pub mod settings; mod state;