From 6744a89922b15e686e89022e795de2afe8a76787 Mon Sep 17 00:00:00 2001 From: Valentin Tolmer Date: Wed, 30 Jun 2021 22:07:23 +0200 Subject: [PATCH] Implement per-user guards for the user details endpoint --- src/infra/auth_service.rs | 29 ++++++++++++++++++++++++++--- src/infra/tcp_api.rs | 11 ++++++++++- src/infra/tcp_server.rs | 4 ---- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/infra/auth_service.rs b/src/infra/auth_service.rs index bffb2b6..d7e4fbe 100644 --- a/src/infra/auth_service.rs +++ b/src/infra/auth_service.rs @@ -340,6 +340,7 @@ where pub async fn token_validator( req: ServiceRequest, credentials: BearerAuth, + admin_required: bool, ) -> Result where Backend: TcpBackendHandler + BackendHandler + 'static, @@ -360,17 +361,39 @@ where if state.jwt_blacklist.read().unwrap().contains(&jwt_hash) { return Err(ErrorUnauthorized("JWT was logged out")); } - let groups = &token.claims().groups; - if groups.contains("lldap_admin") { + let is_admin = token.claims().groups.contains("lldap_admin"); + if is_admin + || (!admin_required && req.match_info().get("user_id") == Some(&token.claims().user)) + { debug!("Got authorized token for user {}", &token.claims().user); Ok(req) } else { Err(ErrorUnauthorized( - "JWT error: User is not in group lldap_admin", + "JWT error: User is not authorized to access this resource", )) } } +pub async fn admin_token_validator( + req: ServiceRequest, + credentials: BearerAuth, +) -> Result +where + Backend: TcpBackendHandler + BackendHandler + 'static, +{ + token_validator::(req, credentials, true).await +} + +pub async fn user_token_validator( + req: ServiceRequest, + credentials: BearerAuth, +) -> Result +where + Backend: TcpBackendHandler + BackendHandler + 'static, +{ + token_validator::(req, credentials, false).await +} + pub fn configure_server(cfg: &mut web::ServiceConfig) where Backend: TcpBackendHandler + LoginHandler + OpaqueHandler + BackendHandler + 'static, diff --git a/src/infra/tcp_api.rs b/src/infra/tcp_api.rs index 97475c3..dd343e0 100644 --- a/src/infra/tcp_api.rs +++ b/src/infra/tcp_api.rs @@ -1,11 +1,13 @@ use crate::{ domain::{error::DomainError, handler::*}, infra::{ + auth_service, tcp_backend_handler::*, tcp_server::{error_to_http_response, AppState}, }, }; use actix_web::{web, HttpRequest, HttpResponse}; +use actix_web_httpauth::middleware::HttpAuthentication; pub(crate) fn error_to_api_response(error: DomainError) -> ApiResult { ApiResult::Right(error_to_http_response(error)) @@ -76,10 +78,17 @@ where }); cfg.app_data(json_config); cfg.service( - web::resource("/user/{user_id}").route(web::get().to(user_details_handler::)), + web::resource("/user/{user_id}") + .route(web::get().to(user_details_handler::)) + .wrap(HttpAuthentication::bearer( + auth_service::user_token_validator::, + )), ); cfg.service( web::scope("/users") + .wrap(HttpAuthentication::bearer( + auth_service::admin_token_validator::, + )) .guard(actix_web::guard::Header("content-type", "application/json")) .service(web::resource("").route(web::post().to(user_list_handler::))) .service( diff --git a/src/infra/tcp_server.rs b/src/infra/tcp_server.rs index a2d0697..0cf950b 100644 --- a/src/infra/tcp_server.rs +++ b/src/infra/tcp_server.rs @@ -11,7 +11,6 @@ use actix_http::HttpServiceBuilder; use actix_server::ServerBuilder; use actix_service::map_config; use actix_web::{dev::AppConfig, web, App, HttpRequest, HttpResponse}; -use actix_web_httpauth::middleware::HttpAuthentication; use anyhow::{Context, Result}; use hmac::{Hmac, NewMac}; use sha2::Sha512; @@ -64,9 +63,6 @@ fn http_config( // API endpoint. .service( web::scope("/api") - .wrap(HttpAuthentication::bearer( - auth_service::token_validator::, - )) .wrap(auth_service::CookieToHeaderTranslatorFactory) .configure(tcp_api::api_config::), )