Authentication
JWT Authentication
How CoreSDK verifies JWTs and extracts user context.
JWT Authentication
CoreSDK supports RS256, ES256, and PS256 JWT verification with automatic JWKS key rotation. Verification happens in the sidecar (Python/Go/TS) or in-process (Rust).
Configuration
Set via coresdk.toml or env vars:
[sdk]
sidecar_addr = "[::1]:50051"
tenant_id = "acme-corp"
fail_mode = "open"# Point to your IdP JWKS endpoint
export CORESDK_JWKS_URL=https://your-idp.com/.well-known/jwks.json
export CORESDK_FAIL_MODE=closed # deny on sidecar error in productionfrom coresdk import CoreSDKClient, SDKConfig
_sdk = CoreSDKClient(SDKConfig(
sidecar_addr="[::1]:50051",
tenant_id="acme-corp",
fail_mode="open",
))use coresdk_engine::{Engine, EngineConfig};
let engine = Engine::from_env()?;
// CORESDK_JWKS_URL=https://your-idp.com/.well-known/jwks.jsonOr explicit config:
let engine = Engine::new(EngineConfig {
jwks_url: Some("https://your-idp.com/.well-known/jwks.json".into()),
tenant_id: "acme-corp".into(),
fail_mode: coresdk_engine::FailMode::Open,
..Default::default()
})?;Supported algorithms
| Algorithm | Key type | Notes |
|---|---|---|
| RS256 | RSA 2048+ | Most common; Auth0/Okta default |
| ES256 | ECDSA P-256 | Faster; Clerk default |
| PS256 | RSA-PSS | FIPS-compatible |
How verification works
- Middleware extracts
Authorization: Bearer <token> - JWT header parsed →
kidextracted - JWKS fetched from
CORESDK_JWKS_URL(cached, refreshed on unknownkid) - Signature verified against matching JWK
- Claims validated:
exp,iat,nbf(clock skew: 30s) - Claims stored on
request.state.coresdk_user(FastAPI),g.claims(Flask),request.coresdk_claims(Django)
JWKS keys are cached in memory with ArcSwap (lock-free reads on hot path). Key rotation is zero-downtime — unknown kid triggers a JWKS refresh.
Claims extracted
{
"sub": "alice",
"tenant_id": "acme-corp",
"roles": ["viewer", "editor"],
"email": "alice@acme.com",
"exp": 1234567890
}Custom claims from your IdP are included as-is. The tenant_id claim is required for multi-tenancy.
Fail modes
fail_mode | Sidecar unreachable | Invalid token |
|---|---|---|
open | Allow, claims = None | Deny (401) |
closed | Deny (503) | Deny (401) |
CORESDK_FAIL_MODE=open # development — allow on sidecar error
CORESDK_FAIL_MODE=closed # production — deny on any auth failureValidate a token manually
decision = _sdk.validate_token("eyJ...")
if decision.allowed:
print(decision.claims) # {"sub": "alice", "tenant_id": ...}
else:
print(decision.reason) # "token-expired", "fail-open", etc.Without a real IdP (development)
Without CORESDK_JWKS_URL, the sidecar accepts any bearer token in fail_mode="open".
You can pass any string as the token and get back allowed=True with claims=None.
curl -H "Authorization: Bearer alice-token" http://localhost:8000/me
# → 200 with {"sub": "anonymous"} (fail-open)