danube_core/jwt.rs
1//! Shared JWT types and utilities for Danube authentication.
2//!
3//! This module provides the canonical `Claims` structure and helper functions
4//! for creating and validating JWTs. Used by both `danube-broker` (validation)
5//! and `danube-admin` (offline token generation).
6
7use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
8use serde::{Deserialize, Serialize};
9
10/// JWT claims used by Danube for authentication.
11///
12/// The `sub` field is the principal name (e.g. "my-app"), and `principal_type`
13/// determines how the broker maps the identity (e.g. "service_account", "user").
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct Claims {
16 /// Token issuer (e.g. "danube-auth")
17 pub iss: String,
18 /// Expiration time (seconds since UNIX epoch)
19 pub exp: u64,
20 /// Subject — the principal name
21 pub sub: String,
22 /// Principal type: "service_account", "user", or "broker_internal"
23 pub principal_type: String,
24 /// Principal name (same as `sub` by convention)
25 pub principal_name: String,
26}
27
28/// Create a signed JWT from the given claims.
29pub fn create_token(
30 claims: &Claims,
31 jwt_secret: &str,
32) -> Result<String, jsonwebtoken::errors::Error> {
33 encode(
34 &Header::default(),
35 claims,
36 &EncodingKey::from_secret(jwt_secret.as_ref()),
37 )
38}
39
40/// Validate a JWT and return the decoded claims.
41pub fn validate_token(
42 token: &str,
43 jwt_secret: &str,
44) -> Result<Claims, jsonwebtoken::errors::Error> {
45 let validation = Validation::default();
46 let token_data = decode::<Claims>(
47 token,
48 &DecodingKey::from_secret(jwt_secret.as_ref()),
49 &validation,
50 )?;
51 Ok(token_data.claims)
52}
53
54/// Extract the bearer token from an "Authorization: Bearer <token>" header value.
55pub fn parse_bearer_token(header_value: &str) -> Option<&str> {
56 header_value
57 .strip_prefix("Bearer ")
58 .or_else(|| header_value.strip_prefix("bearer "))
59}