PEP - Policy Enforcement Point
A Rust library providing OIDC (OpenID Connect) authentication and authorization functionality for both client-side web applications and resource server API protection.
Features
-
oidc-client: OIDC client functionality for web applications- Authorization code flow with PKCE
- Token exchange
- OIDC discovery document handling
- State and nonce generation
-
oidc-resource-server: JWT validation for API protection- JWT token validation with JWKS
- Configurable validation options (skip issuer/audience validation)
- Automatic key rotation handling
- Caching for performance
-
axum(optional): Axum web framework integrationJwtClaimsExtractorfor easy claims extraction in handlersextract_bearer_tokenutility for Authorization header parsing
-
Development Mode: Built-in support for local development
DevConfig.create_dev_claims()for mock JWT claims
Installation
Add this to your Cargo.toml:
[]
# Full OIDC support (client + resource server)
= { = "0.1", = ["oidc"] }
# Or enable specific features
= { = "0.1", = ["oidc-resource-server"] }
# With Axum integration (requires axum 0.8+)
= { = "0.1", = ["oidc-resource-server", "axum"] }
# With configuration file parsing support
= { = "0.1", = ["oidc", "config"] }
# With RFC 9728 Protected Resource Metadata
= { = "0.1", = ["rfc9728"] }
# Full-featured
= { = "0.1", = ["oidc", "axum", "config", "rfc9728"] }
Usage
Resource Server (JWT Validation)
use ResourceServerClient;
use JwtValidationOptions;
async
OIDC Client (Web Authentication Flow)
use OidcClient;
use OidcClientConfig;
async
Axum Integration
When using the axum feature with Axum 0.8+:
use ;
use ;
async
let app = new
.route;
Development Mode
Create mock JWT claims for local development without a real OIDC provider:
use DevConfig;
// Create dev config
let dev_config = DevConfig ;
// Generate mock claims
let claims = dev_config.create_dev_claims;
// Or use the convenience constructor
let dev = enabled;
let claims = dev.create_dev_claims;
assert_eq!;
assert_eq!;
Feature Flags
| Feature | Description |
|---|---|
oidc |
Enables both oidc-client and oidc-resource-server |
oidc-client |
OIDC client for web authentication flows |
oidc-resource-server |
JWT validation for API protection |
axum |
Axum 0.8+ integration (extractors, utilities) |
config |
TOML configuration file parsing support |
rfc9728 |
RFC 9728 Protected Resource Metadata support |
RFC 9728: Protected Resource Metadata
PEP supports RFC 9728 for publishing OAuth 2.0 Protected Resource Metadata. This allows resource servers to advertise their authentication requirements at a well-known endpoint.
Basic Usage
use ;
use Router;
let prm_config = PrmConfig ;
let app = new
.route
.with_state;
Configuration
Add to your config.toml:
[]
= "https://aether.tanbal.com"
= ["https://idm.tanbal.com"]
= "https://idm.tanbal.com/oauth2/openid/aether-api/public_key.jwk"
= ["openid", "profile", "email"]
= ["header"]
= "Aether MCP Server"
= "https://aether.tanbal.com/docs"
Example Response
When clients request GET /.well-known/oauth-protected-resource, they receive:
MCP Client Auto-Discovery
MCP clients (like VS Code) can use PRM to automatically discover authentication requirements:
- Client connects to
https://aether.tanbal.com/sse - Client fetches
https://aether.tanbal.com/.well-known/oauth-protected-resource - PRM tells client to use
https://idm.tanbal.comas the authorization server - Client initiates OAuth flow with discovered configuration
This enables zero-configuration authentication for MCP clients.
JWT Claims Structure
The JwtClaims struct provides access to standard OIDC claims:
Error Handling
PEP uses a custom PepError type with HTTP status code support:
use ;
Configuration
PEP can be configured using OIDC and Development settings. The config feature provides utilities for loading configuration from TOML files.
Configuration File Format
Create a config.toml file:
# OIDC configuration for authentication and resource server protection
[]
= "kanidm"
= "https://idm.example.com"
= "your-client-id"
= "your-client-secret"
= "https://your-app.com/auth/callback"
= "S256"
= "openid email profile offline_access"
# Local development configuration
[]
= false # Set to true to bypass real OIDC and use mock claims
= "developer@example.com"
= "Local Developer"
= "developer"
Loading Configuration (requires config feature)
use load_config;
async
A sample configuration file is available at config-sample.toml.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.