Skip to content

feat(proxy): add optional OIDC access token audience validation - #3466

Open
zerox80 wants to merge 5 commits into
opencloud-eu:mainfrom
zerox80:codex/oidc-audiences
Open

feat(proxy): add optional OIDC access token audience validation#3466
zerox80 wants to merge 5 commits into
opencloud-eu:mainfrom
zerox80:codex/oidc-audiences

Conversation

@zerox80

@zerox80 zerox80 commented Sep 5, 2026

Copy link
Copy Markdown

Description

Add optional OIDC access token audience validation through PROXY_OIDC_AUDIENCES or oidc.audiences in proxy.yaml. The list defaults to empty for compatibility. When configured, a token must contain at least one exact, case-sensitive match in its aud claim. Missing, empty, malformed and nonmatching audiences are rejected.

The signed access token is checked before every Userinfo cache lookup, so existing cache entries cannot bypass a changed audience policy. Cache misses reuse the verification result, and cache hits still avoid extra Userinfo requests. The proxy rejects audience configuration with verification disabled and logs one startup warning when audience validation is off.

The documentation includes ENV and YAML examples, IdP setup requirements and a recommendation to enable the check in production. A separate commit fixes seven existing version annotation typos found by the annotation check.

Related Issue

Fixes #3456

Motivation and Context

When an IdP serves several applications, OpenCloud can currently accept an otherwise valid access token issued for another application. This gives administrators an explicit way to restrict tokens to OpenCloud without breaking existing IdP configurations by default.

How Has This Been Tested?

Tested on Ubuntu WSL with Go 1.25.9 and GCC, using the vendored dependencies.

  • go test -mod=vendor -race -count=1 ./pkg/oidc/... ./services/proxy/... passed.
  • make test passed with a local OpenSearch 2 instance.
  • .make/check-env-var-annotations.sh passed.
  • make ci-golangci-lint completed. The repository has existing lint findings; a separate run against this diff reported no new findings.

The new tests use locally generated keys and an HTTP test IdP with discovery, JWKS and Userinfo endpoints. They cover both skip_user_info settings, cached tokens after policy changes, expiry, logout invalidation, ENV/YAML precedence and the startup warning. They also retain signature, issuer, nbf and AD FS issuer checks. No external IdP is needed.

GPT 6 Astra was used as a supporting tool for the implementation and tests.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Technical debt
  • Tests only (no source changes)

Checklist

  • Code changes
  • Unit tests added
  • Acceptance tests added
  • Documentation added

HTTP integration tests are included in the Go suite. The Behat acceptance suite was not extended.

@codacy-production

codacy-production Bot commented Sep 5, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 88 complexity

Metric Results
Complexity 88

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@zerox80

zerox80 commented Sep 5, 2026

Copy link
Copy Markdown
Author

Do you think a small performance benchmark for the cache-hit path would be useful here, given that the access token now needs to be verified even on cache hits?

@zerox80

zerox80 commented Sep 5, 2026

Copy link
Copy Markdown
Author

I did a small performance investigation of the audience-enabled cache-hit path.

The additional cost is dominated by the required JWT signature verification. Audience-enabled cache hits were around 99 µs/op compared to around 8 µs/op without per-hit verification.

I looked into avoiding repeated verification through policy-scoped caching, but that would weaken the current behavior around JWKS key removal/replacement and would also require broader cache/logout invalidation changes, so I kept that out of this PR.

I did find one small safe optimization in the existing verification path: avoiding the second full JWT parse after successful verification. In controlled serial benchmarks this reduced audience-enabled cache-hit time by about 5–7% and saves 1,088 B / 22 allocations per hit, while leaving the audience-disabled path unchanged.

Full affected package tests and race tests pass.

@zerox80
zerox80 force-pushed the codex/oidc-audiences branch from 5847b9e to bf738a1 Compare September 5, 2026 16:17
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.

Allow configuring valid audiences

1 participant