//! JWT Authentication - Contains intentional vulnerabilities //! //! Vulnerabilities: //! - Audience validation disabled //! - Algorithm::None allowed //! - Insecure decode without verification use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { pub sub: String, pub exp: usize, pub aud: String, } /// VULNERABILITY: Audience validation disabled /// RFC 7519 requires audience validation to prevent token misuse pub fn verify_token_no_aud(token: &str, secret: &[u8]) -> Result { let mut validation = Validation::new(Algorithm::HS256); // BLOCK: JWT audience validation disabled - tokens can be replayed across services validation.validate_aud = false; decode::(token, &DecodingKey::from_secret(secret), &validation) .map(|data| data.claims) .map_err(|e| e.to_string()) } /// VULNERABILITY: Algorithm::None allows unsigned tokens /// Attackers can forge tokens without knowing the secret pub fn verify_token_alg_none(token: &str) -> Result { // BLOCK: Algorithm::None allows forged tokens - critical authentication bypass let validation = Validation::new(Algorithm::None); decode::(token, &DecodingKey::from_secret(&[]), &validation) .map(|data| data.claims) .map_err(|e| e.to_string()) } /// VULNERABILITY: Dangerous insecure decode /// Parses JWT without any signature verification pub fn decode_without_verify(token: &str) -> Result { // BLOCK: dangerous_insecure_decode bypasses all security checks let parts: Vec<&str> = token.split('.').collect(); if parts.len() != 3 { return Err("Invalid token format".to_string()); } // Decode payload without verifying signature - INSECURE let payload = base64_decode(parts[1])?; serde_json::from_slice(&payload).map_err(|e| e.to_string()) } fn base64_decode(input: &str) -> Result, String> { // Simplified base64 decode for demo Ok(input.as_bytes().to_vec()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_insecure_patterns_exist() { // These tests verify the vulnerable patterns are present for demo purposes let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZXhwIjoxNjE2MjM5MDIyLCJhdWQiOiJ0ZXN0In0.signature"; // All these should be detected by Aphoria let _ = verify_token_no_aud(token, b"secret"); let _ = verify_token_alg_none(token); let _ = decode_without_verify(token); } }