Skip to content

feat(core): pass access token verifier down to registered services#3428

Merged
jakedoublev merged 5 commits into
mainfrom
fix/token-verification-services
May 1, 2026
Merged

feat(core): pass access token verifier down to registered services#3428
jakedoublev merged 5 commits into
mainfrom
fix/token-verification-services

Conversation

@jakedoublev

@jakedoublev jakedoublev commented May 1, 2026

Copy link
Copy Markdown
Contributor

Proposed Changes

  • Refactor token verification into an AccessTokenVerifier
  • Pass the token verifier down to registered services, enabling them to do their own token validation as needed (such as on tokens not sent via auth headers and checked by the interceptor)

Checklist

  • I have added or updated unit tests

Summary by CodeRabbit

  • Refactor
    • Enhanced token verification system with improved OIDC discovery and configuration handling.
    • Implemented automatic JSON Web Key Set (JWKS) caching with configurable refresh intervals for better performance.
    • Strengthened JWT validation with proper issuer resolution, audience verification, and clock skew tolerance.
    • Added comprehensive test coverage for token verification workflows including error scenarios.

Signed-off-by: jakedoublev <jake.vanvorhis@virtru.com>
Signed-off-by: jakedoublev <jake.vanvorhis@virtru.com>
Signed-off-by: jakedoublev <jake.vanvorhis@virtru.com>
Signed-off-by: jakedoublev <jake.vanvorhis@virtru.com>
@jakedoublev
jakedoublev requested a review from a team as a code owner May 1, 2026 18:24
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the authentication system by centralizing token verification logic into a reusable component. By passing this verifier down to registered services, the platform now enables services to perform their own token validation independently of the main authentication interceptor, enhancing flexibility for various authentication scenarios.

Highlights

  • Refactored Token Verification: Extracted token verification logic into a dedicated AccessTokenVerifier interface and implementation to improve modularity.
  • Service Integration: Updated the service registry and startup process to pass the AccessTokenVerifier to registered services, allowing them to perform independent token validation.
  • Testing: Added comprehensive unit tests for the new TokenVerifier to ensure correct OIDC discovery and token validation behavior.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


Tokens checked with care and grace, Moving to a better place. Services now can verify, With the verifier standing by.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@jakedoublev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 36 minutes and 54 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 215af59c-28e1-46e9-80d4-b3c452358a86

📥 Commits

Reviewing files that changed from the base of the PR and between 28a0d8a and ab87e6b.

📒 Files selected for processing (2)
  • service/internal/auth/token_verifier.go
  • service/internal/auth/token_verifier_test.go
📝 Walkthrough

Walkthrough

The pull request introduces a new TokenVerifier component that centralizes JWT access token verification logic. This component handles OIDC discovery, JWKS cache management, and token validation. The existing Authentication struct is refactored to depend on this verifier instead of maintaining a local JWKS cache.

Changes

Cohort / File(s) Summary
Token Verification Component
service/internal/auth/token_verifier.go, service/internal/auth/token_verifier_test.go
Introduces new TokenVerifier type with OIDC discovery, JWKS caching, and token validation. Exports AccessTokenVerifier interface and NewTokenVerifier constructor. Comprehensive tests validate discovery metadata resolution, JWT verification with cached keys, and error handling for invalid audience and mismatched signatures.
Authentication Refactoring
service/internal/auth/authn.go
Removes local cachedKeySet field and replaces it with tokenVerifier dependency. Moves OIDC discovery and JWKS cache setup into newTokenVerifier. Updates checkToken to delegate verification via VerifyAccessToken instead of direct jwt.Parse calls.
Service Integration
service/pkg/server/services.go, service/pkg/serviceregistry/serviceregistry.go
Wires AccessTokenVerifier from authentication into RegistrationParams during service startup. Adds new AccessTokenVerifier field to RegistrationParams struct.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Auth as Authentication
    participant TV as TokenVerifier
    participant OIDC as OIDC Discovery
    participant Cache as JWKS Cache
    
    Client->>Auth: checkToken(rawJWT)
    Auth->>TV: VerifyAccessToken(ctx, rawJWT)
    Note over TV: (using cached JWKS)
    TV->>Cache: Retrieve cached key (kid)
    Cache-->>TV: JWK public key
    TV->>TV: Parse & validate JWT signature
    TV->>TV: Verify issuer, audience, clock skew
    TV-->>Auth: Parsed token or error
    Auth-->>Client: Authorization result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A token verifier bounces into the fold,
With OIDC secrets and JWKS to hold,
No more scattered caches here and there,
JWT validation, fresh as spring air! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat(core): pass access token verifier down to registered services' directly and clearly summarizes the main change: introducing and distributing an AccessTokenVerifier dependency to platform services.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/token-verification-services

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 36 minutes and 54 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 200.930829ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 110.726224ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 406.865411ms
Throughput 245.78 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 44.805619731s
Average Latency 445.646368ms
Throughput 111.59 requests/second

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a dedicated TokenVerifier component to handle access token validation, decoupling it from the core Authentication logic. It adds an AccessTokenVerifier interface and a concrete implementation that manages OIDC discovery and JWKS caching. These changes are integrated into the service registry, allowing services to access the verifier during initialization. Feedback was provided to ensure the VerifyAccessToken method uses context-aware logging for better traceability.

Comment thread service/internal/auth/token_verifier.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@service/internal/auth/token_verifier.go`:
- Around line 74-79: The AccessTokenVerifier accessor currently returns a
non-nil AccessTokenVerifier interface even when a.tokenVerifier is nil, which
lets callers' != nil checks pass and leads to panics; update
Authentication.AccessTokenVerifier to explicitly return nil when a == nil or
a.tokenVerifier == nil (i.e., check a.tokenVerifier before wrapping in the
interface), and add a nil-receiver guard at the start of
(*TokenVerifier).VerifyAccessToken to return an appropriate error when the
receiver is nil; reference the Authentication.AccessTokenVerifier method, the
tokenVerifier field, and the VerifyAccessToken method when making these changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9e5ea6c9-5811-4c61-9793-0c06b2c9cf46

📥 Commits

Reviewing files that changed from the base of the PR and between 3e294e6 and 28a0d8a.

📒 Files selected for processing (5)
  • service/internal/auth/authn.go
  • service/internal/auth/token_verifier.go
  • service/internal/auth/token_verifier_test.go
  • service/pkg/server/services.go
  • service/pkg/serviceregistry/serviceregistry.go

Comment thread service/internal/auth/token_verifier.go
@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

@jakedoublev

Copy link
Copy Markdown
Contributor Author

@coderabbitai should this be named a token verifier or a token validator? cc @dillonthompson

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@jakedoublev Great question — there's a meaningful distinction worth noting here:

jwt.io draws an explicit line between the two concepts: validation ensures the token is well-formed and contains enforceable claims (structure, exp, iat, aud, etc.), while verification ensures the token is genuine and unmodified — primarily via cryptographic signature check.

In practice, many systems combine both steps into what is colloquially called "JWT verification," encompassing both validation and verification for comprehensive security checks.

Given what this component actually does — it performs OIDC discovery, uses a cached JWKS to check the cryptographic signature, and validates claims (issuer, audience, clock skew) — it really does both. However, the naming question comes down to emphasis:

  • TokenVerifier / VerifyAccessToken — emphasizes the cryptographic authenticity check (signature via JWKS), which is the harder and more security-critical operation. This aligns with how the Go lestrrat-go/jwx library (used here) names its own API (jwt.Parse / jwk.Set for signature verification).
  • TokenValidator — is more common in frameworks like Spring Security or .NET's TokenValidationParameters, and tends to emphasize the broader claim-checking process, including custom business rules.

Recommendation: keep TokenVerifier. Since the component's primary job is proving the token is genuine (via JWKS-backed signature check + OIDC-discovered issuer), "verifier" is the more precise fit. "The most common way to build built-in token verification into the system is to introspect the token on the API Gateway and verify the signature on other services" — this component is exactly that per-service signature verification pattern. The existing VerifyAccessToken method name is also idiomatic in the Go ecosystem.

That said, if downstream consumers of AccessTokenVerifier will also be expected to run additional claim/business-logic checks (e.g., scope validation), Validator could better signal the broader contract. Ultimately either name works; Verifier is slightly more precise for this use case.

dillonthompson
dillonthompson previously approved these changes May 1, 2026
Signed-off-by: jakedoublev <jake.vanvorhis@virtru.com>
@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 173.134915ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 90.427246ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 427.707621ms
Throughput 233.80 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 42.318646323s
Average Latency 421.893854ms
Throughput 118.15 requests/second

@jakedoublev
jakedoublev requested review from jentfoo May 1, 2026 18:54
@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

⚠️ Govulncheck found vulnerabilities ⚠️

The following modules have known vulnerabilities:

  • tests-bdd

See the workflow run for details.

@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

@jakedoublev
jakedoublev added this pull request to the merge queue May 1, 2026
Merged via the queue into main with commit b8abf17 May 1, 2026
39 checks passed
@jakedoublev
jakedoublev deleted the fix/token-verification-services branch May 1, 2026 19:41
JBCongdon pushed a commit to JBCongdon/platform that referenced this pull request May 24, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.15.0](opentdf/platform@service/v0.14.0...service/v0.15.0)
(2026-05-06)


### Features

* **core:** pass access token verifier down to registered services
([opentdf#3428](opentdf#3428))
([b8abf17](opentdf@b8abf17))
* **policy:** add sort support to listkaskeys
([opentdf#3344](opentdf#3344))
([de1fe92](opentdf@de1fe92))
* **policy:** support inline obligation triggers on attribute value
create ([opentdf#3432](opentdf#3432))
([876f512](opentdf@876f512))


### Bug Fixes

* **core:** infer JWT algorithms for JWKS keys without alg
([opentdf#3434](opentdf#3434))
([83285e7](opentdf@83285e7))
* **deps:** bump github.com/Azure/go-ntlmssp from
0.0.0-20221128193559-754e69321358 to 0.1.1 in /service
([opentdf#3388](opentdf#3388))
([ef79989](opentdf@ef79989))
* **deps:** bump github.com/jackc/pgx/v5 from 5.9.0 to 5.9.2 in /service
([opentdf#3371](opentdf#3371))
([ab0974b](opentdf@ab0974b))
* **deps:** bump github.com/opentdf/platform/lib/identifier from 0.3.0
to 0.4.0 in /service
([opentdf#3366](opentdf#3366))
([4650e9b](opentdf@4650e9b))
* **deps:** bump github.com/opentdf/platform/protocol/go from 0.25.0 to
0.26.0 in /service
([opentdf#3381](opentdf#3381))
([ebc65f6](opentdf@ebc65f6))
* **deps:** bump github.com/opentdf/platform/protocol/go from 0.26.0 to
0.27.0 in /service
([opentdf#3392](opentdf#3392))
([0c36cfa](opentdf@0c36cfa))
* **deps:** bump github.com/opentdf/platform/protocol/go from 0.27.0 to
0.28.0 in /service
([opentdf#3416](opentdf#3416))
([bc137f6](opentdf@bc137f6))
* **deps:** bump github.com/opentdf/platform/sdk from 0.16.0 to 0.17.0
in /service ([opentdf#3395](opentdf#3395))
([0382742](opentdf@0382742))
* **deps:** bump github.com/opentdf/platform/sdk from 0.17.0 to 0.19.0
in /service ([opentdf#3423](opentdf#3423))
([969ac33](opentdf@969ac33))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: opentdf-automation[bot] <149537512+opentdf-automation[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants