feat: get roles associted to api key
This commit is contained in:
+34
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"db_name": "PostgreSQL",
|
||||||
|
"query": "\n SELECT u.id AS user_id, ak.id as key_id, ak.scopes as roles\n FROM auth.api_key ak\n JOIN auth.app_user u ON u.id = ak.created_by\n WHERE ak.key_hash = $1\n AND ak.revoked_at IS NULL\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"ordinal": 0,
|
||||||
|
"name": "user_id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 1,
|
||||||
|
"name": "key_id",
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordinal": 2,
|
||||||
|
"name": "roles",
|
||||||
|
"type_info": "TextArray"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hash": "931f64701ca90a159a54dab717b9cb4004548fc2efc7cbcb056e11e2534eb441"
|
||||||
|
}
|
||||||
-28
@@ -1,28 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT u.id AS user_id, ak.id as key_id\n FROM auth.api_key ak\n JOIN auth.app_user u ON u.id = ak.created_by\n WHERE ak.key_hash = $1\n AND ak.revoked_at IS NULL\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "user_id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "key_id",
|
|
||||||
"type_info": "Uuid"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "c0816078de6c25d441752500b9307900ff3d6c7781ebd9c0d8b47031539d8bdf"
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,15 @@
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
pub enum ApiKeyClaimsRoles {
|
||||||
|
Admin,
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ApiKeyClaims {
|
pub struct ApiKeyClaims {
|
||||||
pub sub: Uuid,
|
pub sub: Uuid,
|
||||||
pub api_key_id: Uuid,
|
pub api_key_id: Uuid,
|
||||||
|
pub roles: Vec<ApiKeyClaimsRoles>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use axum::{
|
|||||||
use crate::databases::postgres::{
|
use crate::databases::postgres::{
|
||||||
api_key::update_last_access, user_repository::ensure_user_exists,
|
api_key::update_last_access, user_repository::ensure_user_exists,
|
||||||
};
|
};
|
||||||
use crate::middlewares::auth::apikey::ApiKeyClaims;
|
use crate::middlewares::auth::apikey::{ApiKeyClaims, ApiKeyClaimsRoles};
|
||||||
use crate::middlewares::auth::keycloak::{KeycloakClaims, get_jwks, refresh_jwks, validate_token};
|
use crate::middlewares::auth::keycloak::{KeycloakClaims, get_jwks, refresh_jwks, validate_token};
|
||||||
use crate::state::app_state::AppState;
|
use crate::state::app_state::AppState;
|
||||||
use crate::utils::crypto::hash_key;
|
use crate::utils::crypto::hash_key;
|
||||||
@@ -127,7 +127,7 @@ async fn try_api_key(
|
|||||||
|
|
||||||
let row = sqlx::query!(
|
let row = sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
SELECT u.id AS user_id, ak.id as key_id
|
SELECT u.id AS user_id, ak.id as key_id, ak.scopes as roles
|
||||||
FROM auth.api_key ak
|
FROM auth.api_key ak
|
||||||
JOIN auth.app_user u ON u.id = ak.created_by
|
JOIN auth.app_user u ON u.id = ak.created_by
|
||||||
WHERE ak.key_hash = $1
|
WHERE ak.key_hash = $1
|
||||||
@@ -145,6 +145,17 @@ async fn try_api_key(
|
|||||||
|
|
||||||
tracing::debug!("API key valid, user_id={}", row.user_id);
|
tracing::debug!("API key valid, user_id={}", row.user_id);
|
||||||
|
|
||||||
|
let roles = row
|
||||||
|
.roles
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|r| match r.as_str() {
|
||||||
|
"admin" => Some(ApiKeyClaimsRoles::Admin),
|
||||||
|
"read" => Some(ApiKeyClaimsRoles::Read),
|
||||||
|
"write" => Some(ApiKeyClaimsRoles::Write),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
handle_auth(
|
handle_auth(
|
||||||
state,
|
state,
|
||||||
request,
|
request,
|
||||||
@@ -152,6 +163,7 @@ async fn try_api_key(
|
|||||||
Auth::ApiKey(ApiKeyClaims {
|
Auth::ApiKey(ApiKeyClaims {
|
||||||
sub: row.user_id,
|
sub: row.user_id,
|
||||||
api_key_id: row.key_id,
|
api_key_id: row.key_id,
|
||||||
|
roles,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use rand::RngCore;
|
|||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
|
||||||
use crate::dto::api::{CreateApiKeyRequest, CreateApiKeyResponse};
|
use crate::dto::api::{CreateApiKeyRequest, CreateApiKeyResponse};
|
||||||
|
use crate::middlewares::auth::apikey::ApiKeyClaimsRoles;
|
||||||
use crate::middlewares::auth::middleware::Auth;
|
use crate::middlewares::auth::middleware::Auth;
|
||||||
use crate::state::app_state::AppState;
|
use crate::state::app_state::AppState;
|
||||||
use crate::utils::crypto::hash_key;
|
use crate::utils::crypto::hash_key;
|
||||||
@@ -23,15 +24,14 @@ pub async fn create_api_key(
|
|||||||
Extension(claims): Extension<Auth>,
|
Extension(claims): Extension<Auth>,
|
||||||
Json(body): Json<CreateApiKeyRequest>,
|
Json(body): Json<CreateApiKeyRequest>,
|
||||||
) -> Result<Json<CreateApiKeyResponse>, StatusCode> {
|
) -> Result<Json<CreateApiKeyResponse>, StatusCode> {
|
||||||
if matches!(claims, Auth::ApiKey(_)) {
|
if matches!(&claims, Auth::ApiKey(api_key) if !api_key.roles.contains(&ApiKeyClaimsRoles::Admin))
|
||||||
|
{
|
||||||
return Err(StatusCode::FORBIDDEN);
|
return Err(StatusCode::FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
let raw_key = generate_api_key();
|
let raw_key = generate_api_key();
|
||||||
let key_hash = hash_key(&raw_key);
|
let key_hash = hash_key(&raw_key);
|
||||||
|
|
||||||
dbg!(&claims);
|
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO auth.api_key (key_hash, name, created_by, scopes)
|
INSERT INTO auth.api_key (key_hash, name, created_by, scopes)
|
||||||
|
|||||||
Reference in New Issue
Block a user