Skip to content

OIDC high security level with JWE/JWS#24

Merged
guimard merged 16 commits intomasterfrom
oidc-high-security
Feb 3, 2026
Merged

OIDC high security level with JWE/JWS#24
guimard merged 16 commits intomasterfrom
oidc-high-security

Conversation

@guimard
Copy link
Member

@guimard guimard commented Feb 3, 2026

No description provided.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements high-security OIDC features by adding JWE (JSON Web Encryption) and JWS (JSON Web Signing) support to the CrowdSieve dashboard. The implementation enables encrypted ID tokens from OIDC providers and supports back-channel logout functionality through signed tokens.

Changes:

  • Added comprehensive JWE/JWS key management system with automatic rotation support
  • Implemented JWKS endpoint (/api/jwks) for publishing public encryption and signing keys
  • Extended Helm charts with OIDC configuration options for JWE/JWS, including key algorithms and rotation settings
  • Added extensive test coverage for key generation, rotation, and JWKS publication

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
dashboard/lib/oidc/keys.ts New module implementing JWE/JWS key management with rotation, caching, and persistence
dashboard/lib/oidc/client.ts Integrated JWE decryption into OIDC client configuration
dashboard/app/api/jwks/route.ts New API endpoint exposing public keys for OIDC providers
dashboard/middleware.ts Added /api/jwks to public paths for OIDC provider access
tests/oidc.test.ts Added comprehensive tests for JWE/JWS key management and rotation
helm/crowdsieve/values.yaml Added OIDC JWS/JWE configuration options with algorithm and rotation settings
helm/crowdsieve/templates/secret.yaml Added OIDC secret management with auto-generated session secrets
helm/crowdsieve/templates/deployment.yaml Added environment variables for JWS/JWE configuration
helm/crowdsieve/README.md Added comprehensive documentation for OIDC with JWE/JWS setup
.env.example Added JWE configuration examples

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

guimard and others added 3 commits February 3, 2026 13:54
- Add encryption key management (generate, store, cache)
- Add JWKS endpoint (/api/jwks) to publish public encryption key
- Enable JWE decryption in OIDC client via enableDecryptingResponses()
- Add 7 tests for JWE key management

The OIDC provider can now encrypt ID tokens using CrowdSieve's
public key, providing end-to-end encryption for sensitive claims.

Configuration:
  JWE_ENABLED=true
  JWE_KEYS_PATH=./data/jwe-keys.json (optional, for persistence)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@guimard guimard force-pushed the oidc-high-security branch from fed9f08 to fa35c2e Compare February 3, 2026 12:55
guimard and others added 11 commits February 3, 2026 13:58
- Fix BUG: keys.privateKey -> keys.current.privateKey in client.ts
- Use crypto.randomBytes() instead of Math.random() for key IDs
- Add init promise lock to prevent race conditions in key initialization
- Fix JWKS endpoint to check both JWS and JWE enabled
- Add rotation check to getEncryptionKeys() (was only in getSigningKeys)
- Handle partial key sets (only JWS or only JWE enabled)
- Fix saveKeysToFile to work with partial key sets
- Fix forceRotation condition for partial key sets
- Update comment about key rotation default (no default, not 30 days)
- Fix Helm values.yaml comment: "pod restart" -> "Helm upgrade"
- Fix Helm secret to always include client-secret key
- Document JWS variables in .env.example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When JWS_KEY_ALG or JWE_KEY_ALG environment variables are changed after
keys have been generated, the stored keys become incompatible. Now:

- Store algorithm with keys in the JSON file
- Detect algorithm mismatches on load
- Regenerate keys automatically with a warning
- Prevents cryptic deserialization errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
jose v6 no longer exports KeyLike type. Use CryptoKey from jose types instead.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document CrowdSieve endpoints (callback, JWKS, back-channel logout)
- List supported algorithms for JWS, JWE, and key sizes
- Add step-by-step Keycloak setup example
- Add issuer URL formats for common providers (Auth0, Okta, Google, Azure AD)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add LemonLDAP::NG configuration example before Keycloak
- Include Manager configuration steps and JWE/JWS setup
- Add LemonLDAP::NG to provider issuer URLs table

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Back-channel logout uses the OIDC provider's JWKS to verify
the logout token, not CrowdSieve's JWS keys. It's always
available when OIDC is enabled.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
JWS (private_key_jwt):
- Use signed JWT assertion for client authentication instead of client_secret
- When JWS_ENABLED=true, clientSecret is ignored with a warning
- Public signing keys published at /api/jwks for provider verification

JWE:
- Support decryption of both ID tokens AND back-channel logout tokens
- Detect JWE (5 parts) vs JWS (3 parts) automatically
- Try all available decryption keys (current + previous)

Documentation:
- Clarify JWS is for private_key_jwt auth, not back-channel logout
- Add private_key_jwt setup instructions for LemonLDAP::NG and Keycloak
- Update .env.example with correct descriptions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create doc/oidc-authentication.md with comprehensive OIDC guide
- Cover JWS (private_key_jwt), JWE, back-channel logout
- Include provider setup examples (LemonLDAP::NG, Keycloak)
- Add OIDC feature to README.md Features section
- Add quick start section in README.md Configuration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Clearer chronological representation of the auth flow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The browser-based redirect flow correctly shows:
- Dashboard redirects user to provider
- User authenticates at provider
- Provider redirects user back with auth code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

guimard and others added 2 commits February 3, 2026 14:42
openid-client v6 requires PrivateKeyJwt() to be passed as 4th argument
to discovery(), not as a parameter to authorizationCodeGrant().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- jwks/route.ts: JWS is for private_key_jwt auth, not back-channel logout
- values.yaml: Add EdDSA to JWS algorithms list
- values.yaml: Fix JWE algorithms (remove A256KW, consistent with docs)
- .env.example: Use jwks.json filename (consistent with Helm deployment)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@guimard guimard merged commit 87df87c into master Feb 3, 2026
9 checks passed
@guimard guimard deleted the oidc-high-security branch February 3, 2026 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant