Skip to content

feat: sign JWTs with RS256, publish public key via JWKS - #20

Merged
braghettos merged 5 commits into
mainfrom
feat/rs256-jwks
Aug 13, 2026
Merged

feat: sign JWTs with RS256, publish public key via JWKS#20
braghettos merged 5 commits into
mainfrom
feat/rs256-jwks

Conversation

@EdmondDantes21

Copy link
Copy Markdown

Summary

  • authn now signs access tokens with an RSA private key (RS256) instead of a shared HMAC secret, and publishes the matching public key as a JWKS at GET /.well-known/jwks.json (new internal/routes/jwks).
  • The private key is mounted from a Secret as a file (--jwt-sign-key-file/JWT_SIGN_KEY_FILE), never injected as an env var, and authn now fails fast at startup if the key/kid is missing or unparseable, instead of silently omitting accessToken per-request.
  • Chart: authn-jwt-signing-key (key private.pem) is mounted as a volume; jwtSignKeySecretName becomes the jwt.{signKeySecretName,signKeySecretKey,mountPath,kid} block. See docs/jwt-jwks.md.
  • Unrelated one-line bugfix, isolated in its own commit: testdata/oauth.yaml's groups RESTAction step now dependsOn userInfo (it reads .token, which only exists after userInfo runs).

Cross-repo dependency

Depends on plumbing PR krateo-platformops/plumbing#21 (adds the RS256/KeyID/JWKS jwtutil API this repo calls). Until that PR is merged and tagged:

  • go.mod is pinned to the plumbing PR's branch-tip commit as a pseudo-version so this branch builds and tests green today.
  • Before merging this PR, once plumbing is tagged (see that PR for the target version), push a follow-up commit here running go get github.com/krateo-platformops/plumbing@<tag> && go mod tidy to replace the pseudo-version — a squash-merge on the plumbing side would otherwise leave this pinned to a commit SHA that stops existing.

Consumers that verify authn's tokens (snowplow) read the public key from the JWKS endpoint added here — see the snowplow and installer PRs for the rest of the chain.

Test plan

  • go build ./... / go test ./... (go/authn), green against the plumbing pseudo-version
  • Re-verify green after the go.mod follow-up once plumbing is tagged

The "groups" step reuses .token, which userInfo's response sets on the shared
step context; without dependsOn the two can run out of order and groups fires
before .token exists.
Pinned to the krateo-platformops/plumbing@feat/rs256-jwks-keysource commit
pending release; re-pin to the tagged version once
krateo-platformops/plumbing#21 is merged and tagged.
authn signs access tokens with an RSA private key (RS256) instead of a shared
HMAC secret, and publishes the matching public key as a JWKS at
GET /.well-known/jwks.json (new internal/routes/jwks package). Every route
that mints a token now carries the key through as PrivateKey+KeyID instead of
a plain SigningKey string.

The private key is read from a mounted file (--jwt-sign-key-file /
JWT_SIGN_KEY_FILE), never from an env var, and authn now fails fast at startup
(before any route is registered) if the key ID or key file is missing or
unparseable — the old design failed silently per-request into a tokenless
response instead.

Chart: the Secret (authn-jwt-signing-key, key private.pem) is mounted as a
volume rather than pulled in via envFrom; jwtSignKeySecretName becomes the
jwt.{signKeySecretName,signKeySecretKey,mountPath,kid} block. Consumers that
verify authn's tokens (snowplow, etc.) get the public key from the JWKS
endpoint, not from a shared Secret — see docs/jwt-jwks.md.
…ard registry

"Reference" isn't a registered OKF type (see .github/DOCS-STANDARD.md's lint-docs
TYPES set); "Integration" is the closest existing fit and matches rbac.md's
precedent for an extension doc. Also list the file in llms.txt alongside rbac.md.
@braghettos
braghettos merged commit c3ba914 into main Aug 13, 2026
14 of 15 checks passed
@braghettos
braghettos deleted the feat/rs256-jwks branch August 13, 2026 17:25
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