Skip to content

feat: sso.oidc jwksUri verify-only mode (cross-service asymmetric JWT, no discovery)#18

Merged
intel352 merged 4 commits into
mainfrom
feat/sso-jwks-uri-verify
Jun 2, 2026
Merged

feat: sso.oidc jwksUri verify-only mode (cross-service asymmetric JWT, no discovery)#18
intel352 merged 4 commits into
mainfrom
feat/sso-jwks-uri-verify

Conversation

@intel352
Copy link
Copy Markdown
Contributor

@intel352 intel352 commented Jun 2, 2026

Adds a jwksUri-only verification mode to sso.oidc so a Workflow app can verify another app's (or any issuer's) ES256/RS256 JWT directly from a published JWKS URL — without OIDC discovery and without a shared secret. This is the enabling primitive for cross-service asymmetric M2M auth (workflow-plugin-auth#41).

What

  • ProviderConfig gains jwksUri + signingAlgorithms. When jwksUri is set, InitProvider builds the verifier via oidc.NewRemoteKeySet + oidc.NewVerifier (skips /.well-known/openid-configuration discovery). The discovery path (jwksUri=="") is unchanged.
  • signingAlgorithms defaults to ["ES256","RS256"]required because go-oidc v3 defaults to RS256-only when SupportedSigningAlgs is empty, which would silently reject ES256 tokens.
  • step.sso_validate_token flows a jwksUri-built verifier unchanged; issuer pinned + audience checked (when clientId set). Verify-only: step.sso_refresh_token/step.sso_token_exchange return a clean "verify-only" error against a jwksUri provider (require the discovery path).

Why

Reuse over rebuild (auth#41): no bespoke IDP — App A issues ES256 via the engine auth.m2m module (+ /oauth/jwks); App B verifies via this mode. Demonstrated end-to-end in workflow-scenarios scenario 102 (next PR).

Tests

6 new tests (accept valid; reject different-key = proves asymmetric; reject aud-mismatch; reject iss-mismatch; default-algs; module init). go test -race ./... green, go build clean, golangci-lint --new-from-rev 0 issues. Discovery path covered by existing unchanged tests.

PR 1 of 3 (auth#41). Design/ADR-0003 in workflow-plugin-auth.

🤖 Generated with Claude Code

intel352 added 3 commits June 2, 2026 07:05
… discovery)

Add JWKSURI + SigningAlgorithms fields to ProviderConfig. When JWKSURI is set,
InitProvider skips OIDC discovery and builds an IDTokenVerifier directly from
the remote JWKS endpoint (oidc.NewRemoteKeySet + oidc.NewVerifier). Enables
cross-service asymmetric JWT verification (e.g. auth.m2m ES256 tokens) without
a shared secret or discovery server. Default algs include ES256+RS256 to avoid
go-oidc v3 RS256-only default rejecting ES256 tokens (cycle-2 F1).

Module config parses jwksUri + signingAlgorithms keys via new getStringSlice
helper. TDD: 6 tests covering accept/reject-wrong-key/aud-mismatch/iss-mismatch/
default-algs/module-init-propagation; confirmed discovery endpoint not hit.
Add provider configuration section to README covering both OIDC discovery
and jwksUri verify-only modes. Table documents issuer/jwksUri/clientId/
signingAlgorithms fields with defaults. Notes the ES256+RS256 default
rationale (go-oidc v3 RS256-only default) and verify-only constraint.
- step.sso_refresh_token + step.sso_token_exchange now return a clean error
  ('provider is verify-only (jwksUri mode)') instead of an opaque empty-endpoint
  oauth2 failure when invoked against a jwksUri (no-discovery) provider.
- remove unused math/big import + misleading suppression from the new test.
Copilot AI review requested due to automatic review settings June 2, 2026 11:11
Copy link
Copy Markdown

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

Adds a jwksUri verify-only mode to the sso.oidc module so the plugin can verify ES256/RS256 JWTs from a remote JWKS URL without performing OIDC discovery. This is the first of three PRs enabling cross-service asymmetric M2M auth (workflow-plugin-auth#41).

Changes:

  • InitProvider branches on cfg.JWKSURI: when set, builds an oidc.IDTokenVerifier directly from oidc.NewRemoteKeySet, defaulting SupportedSigningAlgs to [ES256, RS256] to avoid go-oidc v3's silent RS256-only default.
  • ProviderConfig gains JWKSURI and SigningAlgorithms; parseProviderConfig and a new getStringSlice helper propagate them from the YAML/map config.
  • step.sso_token_exchange and step.sso_refresh_token now return a clean "verify-only" error against jwksUri-mode providers (whose OAuthCfg.Endpoint.TokenURL is empty); step.sso_userinfo was not similarly guarded.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Documents the new jwksUri verify-only mode and field semantics.
internal/oidc.go Adds the JWKS-URI branch in InitProvider and the new JWKSURI/SigningAlgorithms fields on ProviderConfig.
internal/module_oidc.go Wires the two new fields through parseProviderConfig; introduces getStringSlice.
internal/step_token_exchange.go Returns a verify-only error when the provider has no token endpoint.
internal/step_refresh_token.go Same verify-only guard for refresh.
internal/oidc_jwksuri_test.go Adds 6 tests covering accept/reject paths, default algorithms, and module init for jwksUri mode.

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

Comment thread internal/step_token_exchange.go
…s nil Provider)

Copilot: step.sso_userinfo called provider.Provider.UserInfo — nil-panics for a
jwksUri (no-discovery) provider. Same clean verify-only error as refresh/exchange.
@intel352 intel352 merged commit 9e41f88 into main Jun 2, 2026
3 checks passed
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