Skip to content

Commit

Permalink
Add getting user profile and finish AuthMiddleware
Browse files Browse the repository at this point in the history
  • Loading branch information
Daelon022 committed May 27, 2024
1 parent d64176a commit 729e643
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ pub static AUDIENCE: &str = "https://someexample.com";
pub static GRANT_TYPE_PASS: &str = "password";
pub static CONTENT_TYPE: &str = "Content-Type";
pub static APPLICATION_JSON: &str = "application/json";
pub static AUTHORIZATION: &str = "Authorization";
pub static ACCESS_TOKEN: &str = "access_token";
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub enum Error {

#[error(transparent)]
AlcoholicJwtValidationError(#[from] alcoholic_jwt::ValidationError),

#[error("Error: {0}")]
StringError(String),
}

pub type Result<T> = std::result::Result<T, Error>;
Expand Down
30 changes: 21 additions & 9 deletions src/middleware/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ use std::sync::Arc;
use std::task::{Context, Poll};
use tokio::sync::RwLock;

pub const AUDIENCE: &str = "https://someexample.com";

#[derive(Debug, Deserialize)]
#[allow(dead_code)]
struct Claims {
aud: String,
azp: String,
exp: i64,
iat: i64,
iss: String,
sub: String,
exp: usize,
}

pub struct AuthMiddleware;
Expand Down Expand Up @@ -73,17 +79,22 @@ where
if let Some(auth_header) = auth_header {
if let Ok(auth_token) = auth_header.to_str() {
if let Some(auth_str) = auth_token.strip_prefix("Bearer ") {
let token = &auth_str[7..];
let token = auth_str;

let decoding_key = decoding_key.read().await;

return match decode::<Claims>(
token,
&decoding_key,
&Validation::new(Algorithm::HS256),
) {
let audience = [AUDIENCE];

let validation = &mut Validation::new(Algorithm::RS256);

validation.set_audience(&audience);

return match decode::<Claims>(token, &decoding_key, validation) {
Ok(_) => service.call(req).await,
Err(_) => Ok(req.into_response(HttpResponse::Unauthorized().finish())),
Err(e) => {
log::error!("Unauthorized access: {}", e);
Ok(req.into_response(HttpResponse::Unauthorized().finish()))
}
};
}
}
Expand All @@ -100,7 +111,8 @@ impl AuthMiddleware {
let mut key_data = Vec::new();
file.read_to_end(&mut key_data)?;

let decoding_key = DecodingKey::from_secret(&key_data);
let decoding_key =
DecodingKey::from_rsa_pem(key_data.as_slice()).expect("Failed to load key");

Ok(decoding_key)
}
Expand Down
44 changes: 40 additions & 4 deletions src/user_flow/account_flow_methods.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::consts::{APPLICATION_JSON, CONTENT_TYPE};
use crate::errors::Result;
use crate::consts::{APPLICATION_JSON, AUTHORIZATION, CONTENT_TYPE};
use crate::errors::{Error, Result};
use crate::services::auth0::Auth0Service;
use crate::user_flow::consts::CHANGE_PASSWORD_URL;
use crate::user_flow::consts::{CHANGE_PASSWORD_URL, GET_PROFILE_URL};
use actix_web::web::Data;
use http::Method;
use reqwest::Client;
Expand All @@ -14,7 +14,7 @@ pub async fn send_request_to_change_pass(
) -> Result<()> {
let client = Client::new();

let url = format!("{}{}", auth0_service.client_url, CHANGE_PASSWORD_URL);
let url = format!("{}/{}", auth0_service.client_url, CHANGE_PASSWORD_URL);

let body = auth0_service
.generate_body_for_change_password(user_id, email)
Expand All @@ -29,3 +29,39 @@ pub async fn send_request_to_change_pass(

Ok(())
}

pub async fn send_request_to_get_profile(
access_token: &str,
auth0_service: Data<Auth0Service>,
) -> Result<String> {
let client = Client::new();

let url = format!("{}/{}", auth0_service.client_url, GET_PROFILE_URL);
log::info!("Requesting profile from URL: {}", &url);

let result = client
.get(&url)
.header(CONTENT_TYPE, "application/json")
.header(AUTHORIZATION, format!("Bearer {}", access_token))
.send()
.await;

match result {
Ok(response) => {
log::info!("Response status: {}", response.status());
if response.status().is_success() {
let body = response.text().await?;
log::info!("Response body: {:?}", body);
Ok(body)
} else {
let error_body = response.text().await?;
log::error!("Error response body: {:?}", error_body);
Err(Error::StringError(error_body))
}
}
Err(e) => {
log::error!("Request failed: {:?}", e);
Err(Error::StringError(e.to_string()))
}
}
}
2 changes: 1 addition & 1 deletion src/user_flow/auth0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub async fn register_user(
) -> crate::errors::Result<()> {
let client = Client::new();

let url = format!("{}{}", auth0_service.client_url, REGISTRATION_URL);
let url = format!("{}/{}", auth0_service.client_url, REGISTRATION_URL);

let body = auth0_service.generate_body_for_registration(
user_id,
Expand Down
1 change: 1 addition & 0 deletions src/user_flow/consts.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub const REGISTRATION_URL: &str = "dbconnections/signup";
pub const LOGIN_URL: &str = "oauth/token";
pub const CHANGE_PASSWORD_URL: &str = "dbconnections/change_password";
pub const GET_PROFILE_URL: &str = "userinfo";
41 changes: 39 additions & 2 deletions src/user_flow/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use crate::actors::messages::{CheckIfRegisteredUser, CheckUser, CreateUser};
use crate::db::postgres_db::DbService;
use crate::models::{RegisteredUserData, UpdatePasswordData, UserData};
use crate::services::auth0::Auth0Service;
use crate::user_flow::account_flow_methods::send_request_to_change_pass;
use crate::user_flow::account_flow_methods::{
send_request_to_change_pass, send_request_to_get_profile,
};
use crate::user_flow::auth0::{get_jwt_user_token, register_user};
use actix::Addr;
use actix_web::web::{Data, Json};
use actix_web::HttpResponse;
use actix_web::{web, HttpRequest, HttpResponse};
use uuid::Uuid;

#[utoipa::path(
Expand Down Expand Up @@ -97,3 +99,38 @@ pub async fn change_password(
Ok(HttpResponse::BadRequest().finish())
}
}

#[utoipa::path(
get,
path = "/profile/{user_id}",
responses(
(status = 200, description = "Successfully get user profile", body = String),
(status = BAD_REQUEST, description = "User not found")
)
)]
pub async fn profile(
auth0_service: Data<Auth0Service>,
db_service: Data<Addr<DbService>>,
req: HttpRequest,
user_id: web::Path<Uuid>,
) -> crate::errors::Result<HttpResponse> {
log::info!("Getting request for profile!");

let if_user = CheckUser {
id: user_id.into_inner(),
};

if !db_service.send(if_user).await?? {
return Ok(HttpResponse::BadRequest().finish());
}

let access_token = req
.headers()
.get("Authorization")
.expect("No Authorization header")
.to_str()
.expect("Invalid Authorization header");

let profile = send_request_to_get_profile(access_token, auth0_service).await?;
Ok(HttpResponse::Ok().body(profile))
}
16 changes: 9 additions & 7 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::db::postgres_db::DbService;
use crate::middleware::auth::AuthMiddleware;
use crate::services::auth0::Auth0Service;
use crate::user_flow::requests::{change_password, login, register};
use crate::user_flow::requests::{change_password, login, profile, register};
use crate::ApiDoc;
use actix::Addr;
use actix_web::web;
Expand Down Expand Up @@ -72,18 +72,20 @@ fn parse_thread_id(id: &ThreadId) -> String {
parsed.unwrap_or(id_str)
}

pub fn configure_routes(cfg: &mut web::ServiceConfig) {
pub fn configure_routes(cfg: &mut ServiceConfig) {
let openapi = ApiDoc::openapi();

cfg.service(
web::scope("/user")
.wrap(AuthMiddleware)
.service(web::resource("/change_password").route(web::post().to(change_password)))
.service(web::resource("/profile/{user_id}").route(web::get().to(profile))),
)
.service(
web::scope("")
.service(web::resource("/login").route(web::post().to(login)))
.service(web::resource("/register").route(web::post().to(register)))
.service(SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-docs/openapi.json", openapi)),
)
.service(
web::scope("/user")
.wrap(AuthMiddleware)
.service(SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-docs/openapi.json", openapi))
.service(web::resource("/change_password").route(web::post().to(change_password))),
);
}
Expand Down

0 comments on commit 729e643

Please sign in to comment.