Skip to content

Provide RFC 8707 support in CIBA grant type. - #4166

Merged
thiva-k merged 1 commit into
thunder-id:mainfrom
ImalshaD:ciba-rfc8707-resource-indicators
Jul 20, 2026
Merged

Provide RFC 8707 support in CIBA grant type.#4166
thiva-k merged 1 commit into
thunder-id:mainfrom
ImalshaD:ciba-rfc8707-resource-indicators

Conversation

@ImalshaD

@ImalshaD ImalshaD commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Purpose

Add RFC 8707 Resource Indicator support to the OpenID Connect Client-Initiated Backchannel Authentication (CIBA) flow.

Previously, CIBA did not process or persist the resource parameter and issued access tokens with the OAuth client ID as the audience. This prevented CIBA requests from participating in Thunder’s single-resource-server audience model.

This change enables CIBA to:

  • Bind a backchannel authentication request to one resource server.
  • Use the configured default resource server for permission-bearing requests without an explicit resource.
  • Preserve client-ID audience behavior for OIDC-only requests without a resource.
  • Restrict permissions to those defined by the selected resource server.
  • Prevent token polling and refresh operations from widening the original resource binding.
  • Issue access tokens whose sole audience is the selected resource-server identifier.

Approach

The resource binding is selected at /oauth2/bc-authorize, before user authorization, because CIBA performs authorization before the client polls the token endpoint.

The implementation:

  1. Parses repeated RFC 8707 resource parameters at /oauth2/bc-authorize.
  2. Validates that resource values are absolute URIs without fragments.
  3. Enforces a single effective resource server and rejects multiple values, including duplicates, with invalid_target.
  4. Resolves:
    • The explicitly requested resource server when resource is supplied.
    • defaultResourceServer for permission-bearing requests without resource.
    • No resource binding for OIDC-only requests without resource.
  5. Downscopes requested permissions before initiating the authentication flow.
  6. Persists the canonical resource-server identifier in SQL and Redis.
  7. Allows token polling to omit resource or repeat the stored resource, while rejecting a different resource.
  8. Revalidates authorized permissions against the stored resource server before issuing the token.
  9. Issues resource-bound CIBA access tokens with exactly one resource-server audience.
  10. Retains the client ID as the access-token audience for unbound OIDC-only requests and as the ID-token audience.
  11. Preserves the original resource audience for refresh-token issuance.
  12. Updates the OAuth API contract, protocol documentation, and Wayfinder sample.
  13. Adds focused unit coverage for parsing, resolution, persistence, polling enforcement, token issuance, and refresh-token audience propagation.

The Wayfinder CIBA upgrade flow was manually verified end to end:
Upgrade request
→ CIBA initiation with resource
→ Email approval
→ Token polling
→ Resource-bound CIBA token
→ process_upgrade
→ Business-class booking confirmed

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided.
    • Ran Vale and fixed all errors and warnings
  • Tests provided.
    • Unit Tests
    • Integration Tests
  • Breaking changes.
    • Breaking changes section filled.
    • breaking change label added.

Security checks

Summary by CodeRabbit

  • New Features
    • Extended CIBA backchannel authentication (POST /oauth2/bc-authorize) to support optional resource binding, including polling-time matching and resource-restricted access token audiences/permissions.
    • CIBA now persists, validates, and carries resource indicators through token issuance (including refresh tokens).
  • Documentation
    • Updated CIBA and resource-indicators guides to describe resource binding at initiation and validation during polling.
  • Samples / Setup
    • Updated the Wayfinder sample with file-backed Direct Auth Secret instructions and changed run commands to npm run dev.
  • Tests
    • Added coverage for resource parsing, persistence, and grant/audience scope behavior.

Copilot AI review requested due to automatic review settings July 20, 2026 10:04
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1fc6fc18-565b-4c50-bf74-d9682586b89d

📥 Commits

Reviewing files that changed from the base of the PR and between 3895d6b and 154c889.

📒 Files selected for processing (25)
  • api/oauth2.yaml
  • backend/dbscripts/runtime-transient/postgres.sql
  • backend/dbscripts/runtime-transient/sqlite.sql
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/ciba/handler.go
  • backend/internal/oauth/oauth2/ciba/handler_test.go
  • backend/internal/oauth/oauth2/ciba/init.go
  • backend/internal/oauth/oauth2/ciba/model.go
  • backend/internal/oauth/oauth2/ciba/service.go
  • backend/internal/oauth/oauth2/ciba/service_test.go
  • backend/internal/oauth/oauth2/ciba/store.go
  • backend/internal/oauth/oauth2/ciba/store_constants.go
  • backend/internal/oauth/oauth2/ciba/store_redis_test.go
  • backend/internal/oauth/oauth2/ciba/store_test.go
  • backend/internal/oauth/oauth2/granthandlers/ciba.go
  • backend/internal/oauth/oauth2/granthandlers/ciba_test.go
  • backend/internal/oauth/oauth2/granthandlers/provider.go
  • backend/internal/oauth/oauth2/token/service_test.go
  • docs/content/guides/guides/protocols/oauth-oidc/backchannel-authentication.mdx
  • docs/content/guides/guides/protocols/oauth-oidc/resource-indicators.mdx
  • docs/content/guides/key-concepts/authorization.mdx
  • samples/apps/wayfinder-sample/README.md
  • samples/apps/wayfinder-sample/ai-agent/README.md
  • samples/apps/wayfinder-sample/ai-agent/agent.ts
  • samples/apps/wayfinder-sample/backend/README.md
🚧 Files skipped from review as they are similar to previous changes (19)
  • samples/apps/wayfinder-sample/ai-agent/README.md
  • backend/internal/oauth/oauth2/granthandlers/provider.go
  • docs/content/guides/key-concepts/authorization.mdx
  • samples/apps/wayfinder-sample/backend/README.md
  • backend/internal/oauth/oauth2/ciba/handler.go
  • backend/internal/oauth/oauth2/ciba/handler_test.go
  • docs/content/guides/guides/protocols/oauth-oidc/resource-indicators.mdx
  • backend/internal/oauth/oauth2/ciba/service.go
  • backend/dbscripts/runtime-transient/sqlite.sql
  • backend/internal/oauth/oauth2/ciba/store_constants.go
  • backend/internal/oauth/oauth2/token/service_test.go
  • samples/apps/wayfinder-sample/ai-agent/agent.ts
  • backend/internal/oauth/oauth2/ciba/store.go
  • backend/internal/oauth/oauth2/ciba/model.go
  • docs/content/guides/guides/protocols/oauth-oidc/backchannel-authentication.mdx
  • backend/internal/oauth/oauth2/ciba/store_test.go
  • backend/internal/oauth/oauth2/ciba/store_redis_test.go
  • backend/internal/oauth/oauth2/granthandlers/ciba_test.go
  • backend/internal/oauth/oauth2/granthandlers/ciba.go

📝 Walkthrough

Walkthrough

Changes

CIBA now supports RFC 8707 resource indicators from initiation through polling and token issuance. Resource bindings are resolved, persisted, validated, and used for token audiences and scopes. API schemas, database stores, tests, documentation, and the Wayfinder sample were updated.

CIBA Resource Binding

Layer / File(s) Summary
CIBA resource contract and initiation
api/oauth2.yaml, backend/internal/oauth/oauth2/ciba/model.go, backend/internal/oauth/oauth2/ciba/handler.go, docs/content/guides/guides/protocols/oauth-oidc/*, samples/apps/wayfinder-sample/ai-agent/agent.ts
The CIBA endpoint and models expose resource; request parsing preserves repeated values, and documentation and the sample describe initiation-time binding.
Resource resolution and request persistence
backend/internal/oauth/oauth2/ciba/{init.go,service.go,store.go,store_constants.go}, backend/dbscripts/runtime-transient/*, backend/internal/oauth/init.go
CIBA resolves explicit or default resource servers, downscopes permissions, and persists resolved resources through SQL and Redis-backed storage.
Polling validation and token issuance
backend/internal/oauth/oauth2/granthandlers/*, backend/internal/oauth/oauth2/token/service_test.go
Polling resources must match stored bindings, while issued tokens derive audiences and scopes from the bound resource and preserve audiences for refresh tokens.

Wayfinder Sample Setup

Layer / File(s) Summary
Sample setup instructions
samples/apps/wayfinder-sample/README.md, samples/apps/wayfinder-sample/ai-agent/README.md, samples/apps/wayfinder-sample/backend/README.md
Wayfinder instructions use a file-backed Direct Auth Secret and npm run dev for local agent startup.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CIBAClient
  participant CIBAHandler
  participant CIBAService
  participant ResourceService
  participant RequestStore
  participant TokenClient
  participant CIBAGrantHandler
  participant AccessTokenBuilder

  CIBAClient->>CIBAHandler: POST /oauth2/bc-authorize with resource
  CIBAHandler->>CIBAService: InitiateBackchannelAuth(Resources)
  CIBAService->>ResourceService: Resolve and downscope resource
  CIBAService->>RequestStore: Persist CIBA request
  TokenClient->>CIBAGrantHandler: Poll CIBA request
  CIBAGrantHandler->>ResourceService: Validate stored resource binding
  CIBAGrantHandler->>AccessTokenBuilder: Build resource-audience token
  AccessTokenBuilder-->>TokenClient: Return access token
Loading

Possibly related issues

  • thunder-id/thunderid 4163 — Directly covers the CIBA RFC 8707 resource-indicator implementation represented by this change.

Possibly related PRs

Suggested reviewers: thiva-k, thamindudilshan, rajithacharith, brionmario, darshanasbg

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: adding RFC 8707 support to the CIBA grant type.
Description check ✅ Passed The description covers Purpose, Approach, related issue, checklist, and security sections, matching the template well.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
api/oauth2.yaml

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


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

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

@ImalshaD ImalshaD changed the title Add RFC 8707 support in CIBA grant type. Provide RFC 8707 support in CIBA grant type. Jul 20, 2026

Copilot AI 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.

Pull request overview

This PR adds RFC 8707 Resource Indicator support to the OAuth2/OIDC CIBA (backchannel authentication) flow so CIBA requests can bind to a single resource server and receive resource-audience access tokens consistent with ThunderID’s single-resource-server audience model.

Changes:

  • Adds resource parsing/validation at /oauth2/bc-authorize, persists the effective resource binding, and enforces that token polling cannot widen/change the binding.
  • Issues CIBA access tokens with a single resource-server aud (or client_id for unbound OIDC-only requests) and re-downscopes permission scopes against the bound resource server at issuance time.
  • Updates API contract + protocol docs and refreshes the Wayfinder sample configuration, with focused unit coverage across handler/service/store/token issuance.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
samples/apps/wayfinder-sample/README.md Updates local setup instructions for the sample (direct-auth secret handling, dev commands).
samples/apps/wayfinder-sample/backend/README.md Aligns AuthZEN direct-auth secret documentation with file-backed secret usage.
samples/apps/wayfinder-sample/ai-agent/README.md Updates run instructions to match the agent’s dev script.
samples/apps/wayfinder-sample/ai-agent/agent.ts Adds resource to the sample’s CIBA initiation request to bind tokens to the MCP resource server.
docs/content/guides/key-concepts/authorization.mdx Updates guidance to reflect that all access tokens (including CIBA) target a single resource server when bound.
docs/content/guides/guides/protocols/oauth-oidc/resource-indicators.mdx Documents CIBA support and polling enforcement for resource indicators.
docs/content/guides/guides/protocols/oauth-oidc/backchannel-authentication.mdx Documents CIBA resource-binding behavior and links to Resource Indicators guide.
backend/internal/oauth/oauth2/token/service_test.go Adds unit coverage for propagating resource audience into refresh token issuance for CIBA.
backend/internal/oauth/oauth2/granthandlers/provider.go Injects resource service dependency into the CIBA grant handler.
backend/internal/oauth/oauth2/granthandlers/ciba.go Enforces polling resource consistency and issues resource-bound access tokens/scopes for CIBA.
backend/internal/oauth/oauth2/granthandlers/ciba_test.go Adds/updates tests for bound vs unbound behavior, polling enforcement, and scope downscoping.
backend/internal/oauth/oauth2/ciba/store.go Persists and retrieves the bound resource identifier(s) for CIBA auth requests in SQL-backed store.
backend/internal/oauth/oauth2/ciba/store_test.go Adds SQL-store tests for resource encoding/decoding and empty round-trips.
backend/internal/oauth/oauth2/ciba/store_redis_test.go Adds Redis-store test to ensure resources are preserved across Add/Get.
backend/internal/oauth/oauth2/ciba/store_constants.go Extends CIBA_AUTH_REQUEST SQL queries to include the RESOURCES column.
backend/internal/oauth/oauth2/ciba/service.go Resolves effective resource binding at initiation (explicit vs default), downscopes permissions, and stores the binding.
backend/internal/oauth/oauth2/ciba/service_test.go Adds unit tests for resource resolution (explicit/default/none), rejection cases, and storage behavior.
backend/internal/oauth/oauth2/ciba/model.go Adds Resources fields to CIBA request models for propagation/persistence.
backend/internal/oauth/oauth2/ciba/init.go Wires server-config service into CIBA service initialization.
backend/internal/oauth/oauth2/ciba/handler.go Parses repeated resource form parameters into the CIBA initiation request.
backend/internal/oauth/oauth2/ciba/handler_test.go Adds handler tests ensuring single and repeated resource parameters are parsed/preserved.
backend/internal/oauth/init.go Passes server-config service into CIBA initialization at the OAuth module level.
backend/dbscripts/runtime-transient/sqlite.sql Adds RESOURCES column to the runtime-transient SQLite schema for CIBA requests.
backend/dbscripts/runtime-transient/postgres.sql Adds RESOURCES column to the runtime-transient Postgres schema for CIBA requests.
api/oauth2.yaml Adds /oauth2/bc-authorize endpoint to the published OAuth API contract and documents RFC 8707 behavior for CIBA.

Comment thread docs/content/guides/guides/protocols/oauth-oidc/resource-indicators.mdx Outdated
Comment thread backend/internal/oauth/oauth2/ciba/store.go
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.62887% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/internal/oauth/oauth2/ciba/store.go 65.21% 4 Missing and 4 partials ⚠️
backend/internal/oauth/oauth2/ciba/service.go 89.47% 1 Missing and 1 partial ⚠️
...ackend/internal/oauth/oauth2/granthandlers/ciba.go 96.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@ImalshaD
ImalshaD force-pushed the ciba-rfc8707-resource-indicators branch from 2cee878 to 3895d6b Compare July 20, 2026 10:33

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/oauth2.yaml`:
- Around line 269-271: Update the TokenRequest schema to add
urn:openid:params:grant-type:ciba to grant_type.enum and add the required
auth_req_id string property with its CIBA-specific description. Preserve all
existing grant types and request fields.
- Around line 1145-1147: Update the requested_expiry schema property in the
relevant auth request definition from type string to type integer, preserving
its existing description and all other schema metadata.
- Around line 1109-1113: Update the BackchannelAuthRequest schema to include
client_id and client_secret in its properties, matching the corresponding
definitions and conventions used by TokenRequest so generated SDKs and API
documentation support form-based client authentication.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2053e99f-ae7d-4cc5-846b-aecf8ac91fa7

📥 Commits

Reviewing files that changed from the base of the PR and between 2cee878 and 3895d6b.

📒 Files selected for processing (25)
  • api/oauth2.yaml
  • backend/dbscripts/runtime-transient/postgres.sql
  • backend/dbscripts/runtime-transient/sqlite.sql
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/ciba/handler.go
  • backend/internal/oauth/oauth2/ciba/handler_test.go
  • backend/internal/oauth/oauth2/ciba/init.go
  • backend/internal/oauth/oauth2/ciba/model.go
  • backend/internal/oauth/oauth2/ciba/service.go
  • backend/internal/oauth/oauth2/ciba/service_test.go
  • backend/internal/oauth/oauth2/ciba/store.go
  • backend/internal/oauth/oauth2/ciba/store_constants.go
  • backend/internal/oauth/oauth2/ciba/store_redis_test.go
  • backend/internal/oauth/oauth2/ciba/store_test.go
  • backend/internal/oauth/oauth2/granthandlers/ciba.go
  • backend/internal/oauth/oauth2/granthandlers/ciba_test.go
  • backend/internal/oauth/oauth2/granthandlers/provider.go
  • backend/internal/oauth/oauth2/token/service_test.go
  • docs/content/guides/guides/protocols/oauth-oidc/backchannel-authentication.mdx
  • docs/content/guides/guides/protocols/oauth-oidc/resource-indicators.mdx
  • docs/content/guides/key-concepts/authorization.mdx
  • samples/apps/wayfinder-sample/README.md
  • samples/apps/wayfinder-sample/ai-agent/README.md
  • samples/apps/wayfinder-sample/ai-agent/agent.ts
  • samples/apps/wayfinder-sample/backend/README.md
🚧 Files skipped from review as they are similar to previous changes (23)
  • backend/dbscripts/runtime-transient/sqlite.sql
  • samples/apps/wayfinder-sample/ai-agent/README.md
  • backend/internal/oauth/oauth2/ciba/handler.go
  • backend/dbscripts/runtime-transient/postgres.sql
  • backend/internal/oauth/init.go
  • backend/internal/oauth/oauth2/granthandlers/provider.go
  • backend/internal/oauth/oauth2/ciba/model.go
  • docs/content/guides/guides/protocols/oauth-oidc/backchannel-authentication.mdx
  • samples/apps/wayfinder-sample/backend/README.md
  • backend/internal/oauth/oauth2/ciba/store_test.go
  • samples/apps/wayfinder-sample/ai-agent/agent.ts
  • backend/internal/oauth/oauth2/ciba/store_redis_test.go
  • backend/internal/oauth/oauth2/ciba/store_constants.go
  • backend/internal/oauth/oauth2/ciba/store.go
  • docs/content/guides/guides/protocols/oauth-oidc/resource-indicators.mdx
  • docs/content/guides/key-concepts/authorization.mdx
  • backend/internal/oauth/oauth2/ciba/init.go
  • backend/internal/oauth/oauth2/ciba/handler_test.go
  • samples/apps/wayfinder-sample/README.md
  • backend/internal/oauth/oauth2/ciba/service.go
  • backend/internal/oauth/oauth2/granthandlers/ciba_test.go
  • backend/internal/oauth/oauth2/granthandlers/ciba.go
  • backend/internal/oauth/oauth2/ciba/service_test.go

Comment thread api/oauth2.yaml
Comment thread api/oauth2.yaml
Comment thread api/oauth2.yaml
@ImalshaD
ImalshaD force-pushed the ciba-rfc8707-resource-indicators branch from 3895d6b to 154c889 Compare July 20, 2026 11:31
@thiva-k
thiva-k added this pull request to the merge queue Jul 20, 2026
Merged via the queue into thunder-id:main with commit 42deb79 Jul 20, 2026
25 of 26 checks passed
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.

3 participants