diff --git a/README.md b/README.md index 35b5dda..e131ce1 100644 --- a/README.md +++ b/README.md @@ -50,13 +50,35 @@ All configuration is done through `values.yaml`. Key sections: ### Core Settings -| Parameter | Description | Default | -| -------------------- | --------------------------------------------- | ------------------------------ | -| `replicaCount` | Number of replicas (must be 1 for SQLite) | `1` | -| `image.repository` | Container image | `ghcr.io/go-authgate/authgate` | -| `image.tag` | Image tag (defaults to chart appVersion) | `""` | -| `server.baseUrl` | Public URL for OAuth redirects (**required**) | `""` | -| `server.environment` | `production` or `development` | `"production"` | +| Parameter | Description | Default | +| ---------------------- | --------------------------------------------- | ------------------------------ | +| `replicaCount` | Number of replicas (must be 1 for SQLite) | `1` | +| `image.repository` | Container image | `ghcr.io/go-authgate/authgate` | +| `image.tag` | Image tag (defaults to chart appVersion) | `""` | +| `server.baseUrl` | Public URL for OAuth redirects (**required**) | `""` | +| `server.environment` | `production` or `development` | `"production"` | +| `server.enableSwagger` | Expose Swagger UI (development only) | `false` | + +### JWT + +| Parameter | Description | Default | +| ------------------------ | ------------------------------------------------------ | --------- | +| `jwt.signingAlgorithm` | `HS256`, `RS256`, or `ES256` | `"HS256"` | +| `jwt.expiration` | Access token lifetime | `"10h"` | +| `jwt.audience` | `aud` claim values (list; empty omits the claim) | `[]` | +| `jwt.domain` | Server-attested `_domain` claim (empty omits) | `""` | +| `jwt.privateClaimPrefix` | Namespace prefix for AuthGate-emitted private claims | `"extra"` | + +### OAuth Flow + +| Parameter | Description | Default | +| ----------------------------- | ------------------------------------------------------ | ------- | +| `authCode.pkceRequired` | Force PKCE for all public clients | `false` | +| `authCode.strictRedirectURIs` | Require redirect URIs to be loopback or HTTPS | `false` | +| `extraClaims.enabled` | Allow caller-supplied `extra_claims` on `/oauth/token` | `true` | +| `extraClaims.maxRawSize` | Max raw payload size in bytes (0 disables) | `4096` | +| `extraClaims.maxKeys` | Max number of claim keys (0 disables) | `16` | +| `extraClaims.maxValSize` | Max bytes per claim value (0 disables) | `512` | ### Database diff --git a/templates/configmap.yaml b/templates/configmap.yaml index 61d230b..2aa74b9 100644 --- a/templates/configmap.yaml +++ b/templates/configmap.yaml @@ -9,6 +9,7 @@ data: SERVER_ADDR: {{ .Values.server.addr | quote }} BASE_URL: {{ .Values.server.baseUrl | quote }} ENVIRONMENT: {{ .Values.server.environment | quote }} + ENABLE_SWAGGER: {{ .Values.server.enableSwagger | quote }} {{- if and .Values.server.tls.certFile .Values.server.tls.keyFile }} TLS_CERT_FILE: {{ .Values.server.tls.certFile | quote }} TLS_KEY_FILE: {{ .Values.server.tls.keyFile | quote }} @@ -38,6 +39,13 @@ data: JWT_EXPIRATION: {{ .Values.jwt.expiration | quote }} JWT_EXPIRATION_JITTER: {{ .Values.jwt.expirationJitter | quote }} JWT_EXPIRATION_MAX: {{ .Values.jwt.maxExpiration | quote }} + JWT_PRIVATE_CLAIM_PREFIX: {{ .Values.jwt.privateClaimPrefix | quote }} + {{- if .Values.jwt.audience }} + JWT_AUDIENCE: {{ .Values.jwt.audience | join "," | quote }} + {{- end }} + {{- if .Values.jwt.domain }} + JWT_DOMAIN: {{ .Values.jwt.domain | quote }} + {{- end }} # Session SESSION_MAX_AGE: {{ .Values.session.maxAge | quote }} @@ -184,6 +192,13 @@ data: AUTH_CODE_EXPIRATION: {{ .Values.authCode.expiration | quote }} PKCE_REQUIRED: {{ .Values.authCode.pkceRequired | quote }} CONSENT_REMEMBER: {{ .Values.authCode.consentRemember | quote }} + STRICT_REDIRECT_URIS: {{ .Values.authCode.strictRedirectURIs | quote }} + + # Extra Claims + EXTRA_CLAIMS_ENABLED: {{ .Values.extraClaims.enabled | quote }} + EXTRA_CLAIMS_MAX_RAW_SIZE: {{ .Values.extraClaims.maxRawSize | quote }} + EXTRA_CLAIMS_MAX_KEYS: {{ .Values.extraClaims.maxKeys | quote }} + EXTRA_CLAIMS_MAX_VAL_SIZE: {{ .Values.extraClaims.maxValSize | quote }} # Dynamic Client Registration ENABLE_DYNAMIC_CLIENT_REGISTRATION: {{ .Values.dynamicClientRegistration.enabled | quote }} diff --git a/values.yaml b/values.yaml index 4c66856..523c0ff 100644 --- a/values.yaml +++ b/values.yaml @@ -24,6 +24,10 @@ server: # -- Environment mode: "production" or "development" # production: session cookies require HTTPS, stricter security headers environment: "production" + # -- Enable Swagger UI at GET /swagger/*any (no auth middleware). Exposes the + # full API surface including admin endpoints. Do NOT enable on public-facing + # instances; intended for development only. + enableSwagger: false # -- TLS / HTTPS (optional). When both certFile and keyFile are set, # AuthGate serves HTTPS on server.addr. Mount the PEM files into the pod via # extraVolumes/extraVolumeMounts and point these paths at the mounted location. @@ -141,6 +145,21 @@ jwt: # -- Hard cap on any token profile's access TTL. Startup fails if a profile # exceeds this limit. maxExpiration: "24h" + # -- "aud" claim values for issued access/refresh tokens. List form: a single + # entry serializes as a string, multiple as an array. Leave empty ([]) to omit + # the "aud" claim entirely. + # Example: audience: ["https://api.example.com", "https://admin.example.com"] + audience: [] + # -- Server-attested "_domain" claim emitted on every JWT + # (default key: extra_domain). Identifies which AuthGate deployment minted a + # token. Must be 1-64 chars of letters/digits/underscore/dot/hyphen, starting + # and ending with a letter or digit. Empty → claim omitted. + domain: "" + # -- Namespace prefix AuthGate prepends (with an underscore separator) to every + # AuthGate-emitted private claim (domain, project, service_account). Default + # "extra" yields extra_domain, extra_project, extra_service_account. Must match + # ^[a-zA-Z][a-zA-Z0-9_]*$, 1-15 chars, no trailing underscore. + privateClaimPrefix: "extra" # ============================================================ # Session Configuration @@ -341,6 +360,23 @@ authCode: expiration: "10m" pkceRequired: false consentRemember: true + # -- Require redirect URIs to be loopback or HTTPS (OAuth 2.1 §1.5 / MCP). + strictRedirectURIs: false + +# ============================================================ +# Extra Claims (caller-supplied JWT claims via extra_claims on /oauth/token) +# ============================================================ +# Reserved JWT/OIDC keys are always rejected regardless of these limits. +# Custom claims are NOT persisted — callers must re-supply them on every refresh. +extraClaims: + # -- Enable the extra_claims parameter on /oauth/token + enabled: true + # -- Max raw size of the extra_claims payload in bytes (0 disables the check) + maxRawSize: 4096 + # -- Max number of extra claim keys (0 disables the check) + maxKeys: 16 + # -- Max size per claim value in bytes (0 disables the check) + maxValSize: 512 # ============================================================ # Dynamic Client Registration (RFC 7591)