From bf92aea1bbd64d69d9dd326737803166499a0709 Mon Sep 17 00:00:00 2001 From: Evann Regnault Date: Tue, 16 Jul 2024 19:20:30 +0200 Subject: [PATCH] Fixed query parameters and dynamic Client ID --- src/main.rs | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/main.rs b/src/main.rs index efcef04..2916f9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{convert::Infallible, env, error::Error, net::SocketAddr, str::FromStr}; +use std::{collections::HashMap, convert::Infallible, env, error::Error, net::SocketAddr, str::FromStr}; use redis::Commands; use base64::prelude::*; use hmac::{digest::generic_array::functional::FunctionalSequence, Hmac, Mac}; @@ -31,18 +31,12 @@ struct KeycloakToken { #[serde(rename_all = "camelCase")] pub struct DecodedJWT { #[serde(rename = "resource_access")] - pub resource_access: Option, + pub resource_access: HashMap, } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ResourceAccess { - pub couchdb: Option, -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Couchdb { +pub struct Roles { pub roles: Vec, } @@ -80,7 +74,7 @@ impl KeycloakToken { } fn decode_token(&self) -> Result> { - let data = self.access_token.split(".").skip(1).next(); + let data = self.access_token.split('.').nth(1); if data.is_none() { return Err("Invalid JWT".into()); } @@ -92,13 +86,10 @@ impl KeycloakToken { impl DecodedJWT { /// Creates the user struct from the JWT Token fn get_user(self, name: String) -> User { - let roles = match self.resource_access { + let roles = match self.resource_access.get(&env::var("KEYCLOAK_CLIENT_ID").unwrap()) { None => vec![], - Some(ra) => { - match ra.couchdb { - None => vec![], - Some(cdb) => cdb.roles - } + Some(roles) => { + roles.roles.clone() } }; User { @@ -191,9 +182,9 @@ async fn authenticate_keycloak(username: String, password: String) -> Result) -> Option<(String, String)> { let auth_value = req.headers().get("authorization")?; - let b64_auth = auth_value.to_str().unwrap_or("").split(" ").skip(1).next()?; + let b64_auth = auth_value.to_str().unwrap_or("").split(' ').nth(1)?; let decoded_auth = String::from_utf8(BASE64_STANDARD.decode(b64_auth.as_bytes()).unwrap_or(vec![])).unwrap(); - if let [username, password] = &decoded_auth.split(":").map(String::from).collect::>()[..] { + if let [username, password] = &decoded_auth.split(':').map(String::from).collect::>()[..] { Some((username.to_string(), password.to_string())) } else { None @@ -215,14 +206,13 @@ fn error_response((status_code, msg) : (u16, String)) -> Response { .unwrap() } -async fn handle(old_req: Request) -> Result, hyper::Error> { +async fn handle(mut req: Request) -> Result, hyper::Error> { let client = Client::new(); // Build proxied Request - let mut req = Request::from(old_req); - let path = req.uri().path(); + let path = req.uri().path_and_query(); *req.uri_mut() = - Uri::from_str(format!("http://{}:{}{}", env::var("COUCHDB_HOST").unwrap(), env::var("COUCHDB_PORT").unwrap(), path.to_string()).as_str()).unwrap(); + Uri::from_str(format!("http://{}:{}{}", env::var("COUCHDB_HOST").unwrap(), env::var("COUCHDB_PORT").unwrap(), path.unwrap()).as_str()).unwrap(); if req.method() == Method::OPTIONS { return client.request(req).await @@ -257,7 +247,6 @@ async fn handle(old_req: Request) -> Result, hyper::Error> Err(x) => Err(x), } } - #[tokio::main] async fn main() { let make_service = make_service_fn(|_| async { Ok::<_, Infallible>(service_fn(handle)) });