Skip to content

feat(auth): support SPIFFE JWT-SVID authentication via sub-claim fallback - #4

Closed
Manuthor wants to merge 14 commits into
developfrom
claude/festive-ramanujan-uiufap
Closed

Manuthor wants to merge 14 commits into
developfrom
claude/festive-ramanujan-uiufap

Conversation

@Manuthor

Copy link
Copy Markdown
Owner

Rebased-on-review version of Cosmian#1206: the original PR commits plus fixes for the review findings, based on the current Cosmian/kms develop.

Summary (from Cosmian#1206)

  • Opt-in --jwt-svid-auth / KMS_JWT_SVID_AUTH / [idp_auth] jwt_svid_auth: a validated JWT with no email claim is authenticated via its sub when it is a SPIFFE ID (AuthMethod::JwtSvid). Every provider must set an audience; SVIDs without a non-empty aud are rejected.
  • POST /ui/login_svid for gateway/BFF Web UI sessions, SPIFFE advertised in /ui/auth_method.
  • ckms login spire fetches a JWT-SVID from the local SPIRE Agent Workload API.
  • test:spire-jwt-svid E2E suite, shared .mise/lib/spire_test.sh helpers, docs and ADR.

Review fixes

  • Session fixation: /ui/login_svid now calls session.renew() before storing user_id.
  • SPIFFE ID check: require a non-empty trust domain (bare spiffe:// / spiffe:///path are rejected); tests added.
  • Audit log: handle_jwt logs the actual rejection reason instead of always "no email in JWT" (e.g. SVID missing aud).
  • Clippy: real_validation tests used claims["…"] = …, which fails clippy::indexing_slicing under --tests -D warnings; replaced with a set_claim helper.
  • .pre-commit-config.yaml: removed duplicate ui/src/i18n/locales/fr/ typos exclude.

Not changed (author's call): /ui/login_svid returns 500 when the feature is disabled (consistent with login_as; docs/tests expect it); .mise/tasks/test/README.md (1.7k-line generic test doc) could be split into its own PR.

Test plan

  • cargo test -p cosmian_kms_server --lib --features non-fips -- middlewares::jwt routes::ui_auth jwt_svid auth_wizard — 41 passed (incl. real ES256 signature/issuer/audience/expiry validation)
  • cargo clippy -p cosmian_kms_server -p cosmian_kms_cli_actions --lib --tests --features non-fips -- -D warnings — clean
  • mise run test:spire-jwt-svid (needs Docker + SPIRE; not run here)

🤖 Generated with Claude Code

https://claude.ai/code/session_01Nw1fHzCJJQUGNM3URi77gK


Generated by Claude Code

Manuthor and others added 12 commits September 27, 2026 15:24
- require an audience on every --jwt-auth-provider when --jwt-svid-auth is set
  (startup error) and a non-empty `aud` claim on SVIDs; fail startup when no
  provider is configured; wizard asks for the missing audience
- validate_jwt_svid: async, refreshes the JWKS once and retries, accepts only
  spiffe:// subjects
- advertise "SPIFFE" in /ui/auth_method, keep the JWT method gated as before;
  UI shows a gateway notice when SPIFFE is the only method
- expose the production JWT validation as validate_signed_token and cover it with
  real signature/audience/expiry unit tests
- ckms login spire: accept bare absolute socket paths, reject relative ones
- document /ui/login_svid in openapi.yaml, add jwt_svid_auth to the config
  templates and regenerated docs
- mise: spire-jwt-svid validates for real on Linux (HTTPS JWKS, negative checks),
  macOS falls back to an insecure build; fail-fast auth-verifier build, cleanup
- docs/ADR/changelog aligned with the implemented behaviour (mTLS CN precedence,
  gateway shared-identity caveat)
- /ui/login_svid: renew the session ID before storing user_id to prevent
  session fixation.
- Require a non-empty trust domain in SPIFFE subjects (reject bare
  `spiffe://` and `spiffe:///path`).
- handle_jwt: log the actual rejection reason instead of always
  "no email in JWT" (e.g. missing `aud` on an SVID).
- pre-commit: drop duplicate `ui/src/i18n/locales/fr/` typos exclude.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Nw1fHzCJJQUGNM3URi77gK
`clippy::indexing_slicing` rejects `claims["aud"] = ...` under
`cargo clippy --tests -D warnings`; use a small `set_claim` helper.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Nw1fHzCJJQUGNM3URi77gK
@Manuthor Manuthor closed this Sep 30, 2026
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.

2 participants