From a8180ba55b418fb956c666b9d2de0a59d8f09abe Mon Sep 17 00:00:00 2001 From: Paul Z Date: Fri, 20 Oct 2023 00:40:24 +0200 Subject: [PATCH] jwt auth --- Cargo.lock | 26 ++++++++++++-------------- src/error.rs | 21 +++++++++++++++------ src/main.rs | 31 +++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76a6fbd..37fd85e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,19 +181,17 @@ dependencies = [ [[package]] name = "axum_oidc" version = "0.1.0" -source = "git+https://git2.zettoit.eu/pfz4/axum_oidc#89da8cc07fba48a9adcd5821fbc7c527c60ec802" +source = "git+https://git2.zettoit.eu/pfz4/axum_oidc#3b9438d1f3cf58c1edb9f503aea4e6d7783194d2" dependencies = [ "async-trait", "axum", "axum-extra", - "futures-util", "jsonwebtoken", "openidconnect", "reqwest", "serde", "serde_json", "thiserror", - "tower", ] [[package]] @@ -807,9 +805,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "headers" @@ -1006,7 +1004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.2", "serde", ] @@ -1728,9 +1726,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" dependencies = [ "bitflags 2.4.1", "errno", @@ -2114,18 +2112,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -2294,9 +2292,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "log", "pin-project-lite", diff --git a/src/error.rs b/src/error.rs index 81592e2..3630708 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,7 @@ -use axum::{http::StatusCode, response::IntoResponse}; +use axum::{ + http::StatusCode, + response::{IntoResponse, Response}, +}; use log::error; #[derive(Debug, thiserror::Error)] @@ -26,18 +29,24 @@ pub enum Error { #[error("encryption error")] ChaCha, + + #[error("oidc redirect")] + Oidc(Response), } impl IntoResponse for Error { fn into_response(self) -> axum::response::Response { match self { - Self::PhraseInvalid => (StatusCode::BAD_REQUEST, "url is not valid\n"), - Self::BinNotFound => (StatusCode::NOT_FOUND, "bin does not exist\n"), - Self::DataFileExists => (StatusCode::CONFLICT, "bin already contains data\n"), - Self::ParseTtl => (StatusCode::BAD_REQUEST, "invalid ttl class\n"), + Self::PhraseInvalid => (StatusCode::BAD_REQUEST, "url is not valid\n").into_response(), + Self::BinNotFound => (StatusCode::NOT_FOUND, "bin does not exist\n").into_response(), + Self::DataFileExists => { + (StatusCode::CONFLICT, "bin already contains data\n").into_response() + } + Self::ParseTtl => (StatusCode::BAD_REQUEST, "invalid ttl class\n").into_response(), + Self::Oidc(response) => response.into_response(), _ => { error!("{:?}", self); - (StatusCode::INTERNAL_SERVER_ERROR, "internal server error\n") + (StatusCode::INTERNAL_SERVER_ERROR, "internal server error\n").into_response() } } .into_response() diff --git a/src/main.rs b/src/main.rs index 4104328..e05a7c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,11 +12,14 @@ use axum::{ extract::{BodyStream, FromRef, Path, Query, State}, headers::ContentType, http::{header, HeaderMap, StatusCode}, - response::{Html, IntoResponse, Redirect}, + response::{Html, IntoResponse, Redirect, Response}, routing::get, Router, TypedHeader, }; -use axum_oidc::oidc::{self, EmptyAdditionalClaims, OidcApplication, OidcExtractor}; +use axum_oidc::{ + jwt::{Claims, JwtApplication}, + oidc::{self, EmptyAdditionalClaims, OidcApplication, OidcExtractor}, +}; use chacha20::{ cipher::{KeyIvInit, StreamCipher}, ChaCha20, @@ -55,6 +58,7 @@ type HandlerResult = Result; pub struct AppState { application_base: String, oidc_application: OidcApplication, + jwt_application: JwtApplication, data: String, key_salt: KeySalt, id_salt: IdSalt, @@ -67,6 +71,12 @@ impl FromRef for OidcApplication { } } +impl FromRef for JwtApplication { + fn from_ref(input: &AppState) -> Self { + input.jwt_application.clone() + } +} + #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct ExpiryHeapItem { pub expires_at: u64, @@ -101,6 +111,13 @@ async fn main() { .await .expect("Oidc Authentication Client"); + let jwt_application = JwtApplication::new( + issuer.to_string(), + env::var("AUDIENCE").expect("AUDIENCE env var"), + ) + .await + .expect("Jwt Authentication Client"); + let data_path = env::var("DATA_PATH").expect("DATA_PATH env var"); let garbage_collector = GarbageCollector::new(data_path.clone()).await; @@ -109,6 +126,7 @@ async fn main() { let state: AppState = AppState { application_base, oidc_application, + jwt_application, data: data_path, key_salt: KeySalt::from_str(&env::var("KEY_SALT").expect("KEY_SALT env var")) .expect("KEY SALT valid hex"), @@ -133,9 +151,14 @@ async fn main() { async fn get_index( State(app_state): State, - OidcExtractor { claims, .. }: OidcExtractor, + oidc_extractor: Result, axum_oidc::error::Error>, + jwt_claims: Option>, ) -> Result { - let subject = claims.subject().to_string(); + let subject = match (oidc_extractor, jwt_claims) { + (_, Some(claims)) => claims.sub.to_string(), + (Ok(oidc), None) => oidc.claims.subject().to_string(), + (Err(err), None) => return Err(Error::Oidc(err.into_response())), + }; //generate phrase and derive id from it let phrase = Phrase::random();