Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 40 additions & 20 deletions bin/core/src/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use database::mungos::mongodb::bson::doc;
use komodo_client::entities::{komodo_timestamp, user::User};
use reqwest::StatusCode;
use serde::Deserialize;
use serror::AddStatusCode;
use serror::{AddStatusCode, AddStatusCodeError};

use crate::{
helpers::query::get_user,
Expand Down Expand Up @@ -37,17 +37,15 @@ pub async fn auth_request(
mut req: Request,
next: Next,
) -> serror::Result<Response> {
let user = authenticate_check_enabled(&headers)
.await
.status_code(StatusCode::UNAUTHORIZED)?;
let user = authenticate_check_enabled(&headers).await?;
req.extensions_mut().insert(user);
Ok(next.run(req).await)
}

#[instrument(level = "debug")]
pub async fn get_user_id_from_headers(
headers: &HeaderMap,
) -> anyhow::Result<String> {
) -> serror::Result<String> {
match (
headers.get("authorization"),
headers.get("x-api-key"),
Expand All @@ -59,6 +57,7 @@ pub async fn get_user_id_from_headers(
auth_jwt_get_user_id(jwt)
.await
.context("failed to authenticate jwt")
.status_code(StatusCode::UNAUTHORIZED)
}
(None, Some(key), Some(secret)) => {
// USE API KEY / SECRET
Expand All @@ -67,34 +66,44 @@ pub async fn get_user_id_from_headers(
auth_api_key_get_user_id(key, secret)
.await
.context("failed to authenticate api key")
.status_code(StatusCode::UNAUTHORIZED)
}
_ => {
// AUTH FAIL
Err(anyhow!(
"must attach either AUTHORIZATION header with jwt OR pass X-API-KEY and X-API-SECRET"
))
Err(
anyhow!("must attach either AUTHORIZATION header with jwt OR pass X-API-KEY and X-API-SECRET")
.status_code(StatusCode::BAD_REQUEST)
.into()
)
}
}
}

#[instrument(level = "debug")]
pub async fn authenticate_check_enabled(
headers: &HeaderMap,
) -> anyhow::Result<User> {
) -> serror::Result<User> {
let user_id = get_user_id_from_headers(headers).await?;
let user = get_user(&user_id).await?;
let user = get_user(&user_id).await.map_err(serror::Error::from)?;
if user.enabled {
Ok(user)
} else {
Err(anyhow!("user not enabled"))
Err(
serror::Error::from(
anyhow!("user not enabled")
.status_code(StatusCode::FORBIDDEN)
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is not consistent with the rest

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll adjust the others too so that it's consistent. I just left them as they were at first because the adjustment caused errors in the websocket file.

)
}
}

#[instrument(level = "debug")]
pub async fn auth_jwt_get_user_id(
jwt: &str,
) -> anyhow::Result<String> {
let claims: JwtClaims = jwt_client().decode(jwt)?;
let claims: JwtClaims = jwt_client()
.decode(jwt)
.context("failed to decode jwt")?;
if claims.exp > unix_timestamp_ms() {
Ok(claims.id)
} else {
Expand All @@ -105,8 +114,11 @@ pub async fn auth_jwt_get_user_id(
#[instrument(level = "debug")]
pub async fn auth_jwt_check_enabled(
jwt: &str,
) -> anyhow::Result<User> {
let user_id = auth_jwt_get_user_id(jwt).await?;
) -> serror::Result<User> {
let user_id = auth_jwt_get_user_id(jwt)
.await
.context("failed to get user id from jwt")
.status_code(StatusCode::UNAUTHORIZED)?;
check_enabled(user_id).await
}

Expand All @@ -130,7 +142,7 @@ pub async fn auth_api_key_get_user_id(
// secret matches
Ok(key.user_id)
} else {
// secret mismatch
// secret mismatch
Err(anyhow!("invalid api secret"))
}
}
Expand All @@ -139,17 +151,25 @@ pub async fn auth_api_key_get_user_id(
pub async fn auth_api_key_check_enabled(
key: &str,
secret: &str,
) -> anyhow::Result<User> {
let user_id = auth_api_key_get_user_id(key, secret).await?;
) -> serror::Result<User> {
let user_id = auth_api_key_get_user_id(key, secret)
.await
.context("failed to get user id from api key")
.status_code(StatusCode::UNAUTHORIZED)?;
check_enabled(user_id).await
}

#[instrument(level = "debug")]
async fn check_enabled(user_id: String) -> anyhow::Result<User> {
let user = get_user(&user_id).await?;
async fn check_enabled(user_id: String) -> serror::Result<User> {
let user = get_user(&user_id).await.map_err(serror::Error::from)?;
if user.enabled {
Ok(user)
} else {
Err(anyhow!("user not enabled"))
Err(
serror::Error::from(
anyhow!("user not enabled")
.status_code(StatusCode::FORBIDDEN)
)
)
}
}
4 changes: 2 additions & 2 deletions bin/core/src/ws/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ async fn ws_login(
Err(e) => {
let _ = socket
.send(Message::text(format!(
"failed to authenticate user using jwt | {e:#}"
"failed to authenticate user using jwt | {e:?}"
)))
.await;
let _ = socket.close().await;
Expand All @@ -89,7 +89,7 @@ async fn ws_login(
Err(e) => {
let _ = socket
.send(Message::text(format!(
"failed to authenticate user using api keys | {e:#}"
"failed to authenticate user using api keys | {e:?}"
)))
.await;
let _ = socket.close().await;
Expand Down