User Request
Add client-level configuration to select JWT signature algorithms for ID tokens and access tokens. Must support ES384. Avoid env vars; configuration must live on the OAuth/OIDC Client model. Multiple clients under the same tenant should be able to use different algorithms concurrently.
Researcher Spec
Models and flows
- Clients: Prisma
model Client with clientId (OIDC client_id). Token issuance obtains client via consumeAuthorizationCode(...) and issueTokensFromCode(...).
- Tokens: Both
id_token and access_token are JWTs currently signed with RS256.
- Keys:
TenantKey persists per-tenant signing keys (private encrypted, public JWKS), currently RS256-only.
Proposed changes
-
Client model fields (Prisma):
- Add enum:
enum JwtSigningAlg { RS256 PS256 ES256 ES384 }
- Add fields:
idTokenSignedResponseAlg JwtSigningAlg?
accessTokenSigningAlg JwtSigningAlg?
- Validation: accept only supported enum values.
-
Algorithm resolution (issuance):
- id token alg =
client.idTokenSignedResponseAlg ?? RS256.
- access token alg =
client.accessTokenSigningAlg ?? id token alg.
-
Key management per (tenant, alg):
- Maintain one ACTIVE key per
(tenantId, alg); auto-generate on first use.
- Update key-service to:
getActiveKey(tenantId, alg)
ensureActiveKeyForAlg(tenantId, alg)
rotateKeyForAlg(tenantId, alg) using generateKeyPair(alg, { extractable: true }).
- JWKS publishes all ACTIVE and ROTATED keys across algorithms.
-
Signing and verification:
- Token issuance: set JWT header
{ alg: resolvedAlg, kid } and import JWK with that alg.
- Verification (e.g., userinfo-service): decode header, use
header.alg to importJWK and verify; reject unsupported/missing alg.
-
Discovery:
- Advertise full supported list (including ES384) in
id_token_signing_alg_values_supported.
Files to update
prisma/schema.prisma: add enum, client fields; index on TenantKey(tenantId, alg, status).
src/server/services/key-service.ts: per-tenant+alg active key functions.
src/server/services/token-service.ts: resolve algs per client; ensure key; sign with resolved algs.
src/server/services/userinfo-service.ts: verify using JWT header alg.
src/server/services/discovery-service.ts: advertise supported list.
src/server/services/client-service.ts + src/app/admin/actions.ts + client admin UI: add update/display for new fields.
- Tests: extend OIDC flow and unit tests for ES384 and multi-client algs.
Acceptance Criteria
- Client model holds
id_token_signed_response_alg and access_token_signing_alg (stored as enum fields).
- ES384 works for both tokens when configured; default remains RS256.
- Tenants can have ACTIVE keys per algorithm; JWKS publishes multiple keys; verification uses header
alg.
- Discovery lists supported algorithms including ES384.
- Tests cover two clients in one tenant using different algs concurrently.
User Request
Add client-level configuration to select JWT signature algorithms for ID tokens and access tokens. Must support ES384. Avoid env vars; configuration must live on the OAuth/OIDC Client model. Multiple clients under the same tenant should be able to use different algorithms concurrently.
Researcher Spec
Models and flows
model ClientwithclientId(OIDCclient_id). Token issuance obtainsclientviaconsumeAuthorizationCode(...)andissueTokensFromCode(...).id_tokenandaccess_tokenare JWTs currently signed with RS256.TenantKeypersists per-tenant signing keys (private encrypted, public JWKS), currently RS256-only.Proposed changes
Client model fields (Prisma):
enum JwtSigningAlg { RS256 PS256 ES256 ES384 }Algorithm resolution (issuance):
client.idTokenSignedResponseAlg ?? RS256.client.accessTokenSigningAlg ?? id token alg.Key management per (tenant, alg):
(tenantId, alg); auto-generate on first use.getActiveKey(tenantId, alg)ensureActiveKeyForAlg(tenantId, alg)rotateKeyForAlg(tenantId, alg)usinggenerateKeyPair(alg, { extractable: true }).Signing and verification:
{ alg: resolvedAlg, kid }and import JWK with thatalg.header.algtoimportJWKand verify; reject unsupported/missing alg.Discovery:
id_token_signing_alg_values_supported.Files to update
prisma/schema.prisma: add enum, client fields; index onTenantKey(tenantId, alg, status).src/server/services/key-service.ts: per-tenant+alg active key functions.src/server/services/token-service.ts: resolve algs per client; ensure key; sign with resolved algs.src/server/services/userinfo-service.ts: verify using JWT header alg.src/server/services/discovery-service.ts: advertise supported list.src/server/services/client-service.ts+src/app/admin/actions.ts+ client admin UI: add update/display for new fields.Acceptance Criteria
id_token_signed_response_algandaccess_token_signing_alg(stored as enum fields).alg.