The effGen API server validates Bearer JWTs on every non-public endpoint. Tokens are issued by any standard OIDC provider (Auth0, Keycloak, Google, Azure AD, etc.).
| Environment variable | Default | Description |
|---|---|---|
EFFGEN_OIDC_ISSUER |
(required in prod) | Token issuer URL, e.g. https://your-tenant.auth0.com/ |
EFFGEN_OIDC_CLIENT_ID |
(required in prod) | Expected aud claim in JWTs |
EFFGEN_OIDC_JWKS_URI |
auto-discovered | JWKS endpoint; omit to use OIDC discovery |
EFFGEN_API_KEY |
(unset) | Static API key — a simpler shared-secret alternative to OIDC |
EFFGEN_API_KEY_ROLES |
admin |
Comma-separated RBAC roles granted to a valid API key |
EFFGEN_DEV_MODE |
0 |
Set to 1 to disable auth with a loud warning |
EFFGEN_METRICS_AUTH |
0 |
Set to 1 to require auth on /metrics |
For deployments that don't run an OIDC provider, set EFFGEN_API_KEY to a
shared secret. Clients then present it as either header:
curl -H "Authorization: Bearer $EFFGEN_API_KEY" http://127.0.0.1:8000/v1/models
curl -H "X-API-Key: $EFFGEN_API_KEY" http://127.0.0.1:8000/v1/modelsThe key is compared in constant time and maps to the roles in
EFFGEN_API_KEY_ROLES (default admin). When neither EFFGEN_API_KEY, OIDC,
nor EFFGEN_DEV_MODE=1 is set, effgen serve mints and prints an ephemeral
key at startup, so the server is never unauthenticated by default.
/health/healthz,/ready,/livez,/readyz/openapi.json,/docs,/redoc(API schema only — no data)/metrics(unlessEFFGEN_METRICS_AUTH=1)
EFFGEN_DEV_MODE=1 uvicorn effgen.server.app:create_app --factoryA loud warning is printed to stderr. Never use EFFGEN_DEV_MODE=1 in
production. In dev mode all requests are treated as the dev-user principal
with the admin role.
- Create an API in Auth0 with identifier
https://effgen.api. - Set environment variables:
export EFFGEN_OIDC_ISSUER=https://your-tenant.auth0.com/
export EFFGEN_OIDC_CLIENT_ID=https://effgen.api
# JWKS auto-discovered from /.well-known/openid-configuration- Obtain a token via the M2M flow:
TOKEN=$(curl -s -X POST "https://your-tenant.auth0.com/oauth/token" \
-H "Content-Type: application/json" \
-d '{"client_id":"<M2M_CLIENT_ID>","client_secret":"<SECRET>",
"audience":"https://effgen.api","grant_type":"client_credentials"}' \
| jq -r '.access_token')
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/whoamiexport EFFGEN_OIDC_ISSUER=https://keycloak.example.com/realms/myrealm
export EFFGEN_OIDC_CLIENT_ID=effgen-api
# Keycloak exposes JWKS at {issuer}/protocol/openid-connect/certs
export EFFGEN_OIDC_JWKS_URI=https://keycloak.example.com/realms/myrealm/protocol/openid-connect/certsAdd a roles claim mapper to the Keycloak client to embed role names in the
JWT. effGen reads the roles claim (or scope) from the token.
effGen reads:
{
"sub": "user-id",
"iss": "https://your-issuer/",
"aud": "your-client-id",
"exp": 1234567890,
"roles": ["researcher", "admin"],
"email": "user@example.com"
}If roles is absent, the scope claim (space-separated) is used instead.
from effgen.server.auth import verify_jwt, TokenPayload
payload: TokenPayload = verify_jwt(
raw_token,
issuer="https://your-issuer/",
client_id="your-client-id",
jwks_uri="https://your-issuer/.well-known/jwks.json",
)
print(payload.sub, payload.roles)from effgen.server.auth import AuthMiddleware
app = FastAPI()
app.add_middleware(
AuthMiddleware,
issuer="https://your-issuer/",
client_id="your-client-id",
# jwks_uri auto-discovered if omitted
)After the middleware runs, request.state.user is a TokenPayload.
- Tokens are validated against the JWKS public keys fetched from the IdP.
- The JWKS is cached for 1 hour to reduce latency.
- Expired tokens are always rejected.
- Audience and issuer mismatches are always rejected.
- The
Authorizationheader value is never written to logs or audit records.