| name | auth-architecture |
| description | LiteLLM-RS Authentication Architecture. Covers JWT + API Key + RBAC multi-method auth, DashMap-backed rate limiting, the actix-web middleware pipeline, and credential management (gw- prefixed keys, HMAC hashing). Use when adding auth methods, debugging JWT/API-key validation, implementing RBAC permission checks, or tuning rate limiting and auth configuration. |
Authentication Architecture Guide
Overview
AuthSystem (src/auth/system.rs) composes three subsystems behind one authenticate() entry point:
pub struct AuthSystem {
config: Arc<AuthConfig>,
storage: Arc<StorageLayer>,
jwt: Arc<JwtHandler>,
api_key: Arc<ApiKeyHandler>,
rbac: Arc<RbacSystem>,
}
AuthSystem::authenticate(auth_method, context) -> Result<AuthResult> dispatches on
AuthMethod::{Jwt, ApiKey, Session, None} (src/auth/types.rs). Session auth is a
stub that always rejects ("Session authentication is not yet implemented").
Semantic rejections return AuthResult { success: false, error: Some(..) };
infrastructure failures return Err(GatewayError).
Middleware pipeline
Wired in src/server/http.rs (actix runs wraps in reverse registration order, so
the request path is outermost-first):
RequestIdMiddleware -> AuditMiddleware -> IpAccessMiddleware -> CORS/Metrics
-> AuthMiddleware (src/server/middleware/auth.rs)
-> RateLimitMiddleware (src/server/middleware/rate_limit.rs)
-> SecurityHeadersMiddleware -> handler
AuthMiddleware per request: public-route bypass → fail-closed check when both
auth methods are disabled (allow_anonymous gate) → brute-force lockout via
AuthRateLimiter → credential extraction → authentication → endpoint/operation
authorization → insert User / ApiKey into request extensions.
Credential Extraction
extract_auth_method_with_api_key_header (src/server/middleware/helpers.rs)
resolves credentials in this priority order:
Authorization: Bearer <jwt> → AuthMethod::Jwt
Authorization: ApiKey <key> → AuthMethod::ApiKey
Authorization: gw-... (raw key, no scheme) → AuthMethod::ApiKey
- Configured API key header (
auth.api_key_header, default Authorization)
X-API-Key fallback (when the configured header differs)
session=<id> cookie → AuthMethod::Session
There is no Bearer sk- form: gateway keys are gw- prefixed, and a raw
sk-... value matches nothing.
API Key Authentication
Key generation and hashing
Keys are generated by generate_api_key() in src/utils/auth/crypto/keys.rs:
a fixed gw prefix plus 32 alphanumeric characters (gw-<32 chars>, 35 total).
They are hashed — never stored in plaintext:
pub fn generate_api_key() -> String;
pub fn hash_api_key(api_key: &str, hmac_secret: Option<&str>) -> String;
pub fn extract_api_key_prefix(api_key: &str) -> String;
hash_api_key computes HMAC-SHA256 when api_key_hmac_secret is configured,
otherwise plain SHA-256. Argon2 is used only for user passwords
(src/utils/auth/crypto/password.rs), never for API keys.
Handler
ApiKeyHandler::new(storage: Arc<StorageLayer>, hmac_secret: Option<String>)
stores keys through the database layer and looks them up by full hash
(find_api_key_by_hash) — there is no prefix lookup.
impl ApiKeyHandler {
pub async fn create_key(&self, user_id: Option<Uuid>, team_id: Option<Uuid>,
name: String, permissions: Vec<String>) -> Result<(ApiKey, String)>;
pub async fn verify_key(&self, raw_key: &str) -> Result<Option<(ApiKey, Option<User>)>>;
pub async fn verify_key_detailed(&self, raw_key: &str) -> Result<ApiKeyVerification>;
}
Verification rejects inactive or expired keys and keys whose owner user is
missing/inactive; it refreshes last_used_at throttled to once per 5 minutes
(LAST_USED_THROTTLE) via an in-memory DashMap<Uuid, Instant> cache.
Names must be 1–255 chars without control characters; permissions must be from
VALID_PERMISSIONS (creation.rs): *, system.admin, analytics.read,
api.chat, api.embeddings, api.images, and dotted read/write/delete grants
on users, teams, api_keys (e.g. users.read, api_keys.delete).
Management lives on the same handler: revoke_key, list_user_keys,
update_permissions, update_expiration, regenerate_key (returns a new raw
key), cleanup_expired_keys (src/auth/api_key/management.rs).
JWT Authentication
Claims
Single role: String (not a role list), plus token identity fields
(src/auth/jwt/types.rs):
pub struct Claims {
pub sub: Uuid,
pub iat: u64, pub exp: u64,
pub iss: String,
pub aud: String,
pub jti: String,
pub role: String,
pub permissions: Vec<String>,
pub team_id: Option<Uuid>,
pub session_id: Option<String>,
pub token_type: TokenType,
}
Handler
JwtHandler::new(config: &AuthConfig) builds HS256 signing keys from
jwt_secret; lifetime comes from jwt_expiration. There is no configurable
audience field — audiences are hard-coded per token kind.
impl JwtHandler {
pub async fn create_access_token(&self, user_id: Uuid, role: String,
permissions: Vec<String>, team_id: Option<Uuid>, session_id: Option<Uuid>)
-> Result<String>;
pub async fn create_refresh_token(&self, user_id: Uuid,
session_id: Option<String>) -> Result<String>;
pub async fn create_token_pair(...) -> Result<TokenPair>;
pub async fn verify_access_token(&self, token: &str) -> Result<Claims>;
pub async fn verify_refresh_token(&self, token: &str) -> Result<Uuid>;
}
For both public creation methods, team_id must currently be None; passing Some(...)
returns BadRequest("Active team selection requires verified membership").
Team-scoped access tokens and token pairs are created only through the crate-private
create_access_token_for_verified_team / create_token_pair_for_verified_team paths
after active membership has been verified.
verify_access_token enforces aud == "api" and rejects unknown team-scope
versions; verify_refresh_token enforces aud == "refresh" plus
token_type == Refresh. JWT decode failures map to
GatewayError::Auth("JWT error: ...").
References
- reference/middleware-pipeline.md — AuthMiddleware wiring, brute-force lockout, route-level permission checks
- reference/rbac.md — Permission/Role structs, RbacSystem checks, role inheritance, default roles
- reference/rate-limiting.md — DashMap RateLimiter strategies, Redis backend, rate-limit key policy
- reference/configuration.md — flat
auth: YAML surface, validation rules, top-level rate_limit: section
- reference/security-best-practices.md — secret policy, HMAC key hashing, redaction, audit events, key lifecycle
- reference/error-types.md — GatewayError variants used across the auth stack and their HTTP mappings