Skip to content

[POC] Implement OAuth2 Integration#161

Draft
ldjebran wants to merge 1 commit into
mainfrom
oauth2-integration
Draft

[POC] Implement OAuth2 Integration#161
ldjebran wants to merge 1 commit into
mainfrom
oauth2-integration

Conversation

@ldjebran

@ldjebran ldjebran commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Implement OAuth2 Integration

Enable opt-in OAuth2 authentication alongside the existing Bearer token
flow. When OAUTH2_CLIENT_ID and OAUTH2_CLIENT_SECRET are set, MCP
clients (Claude Code, Cursor, Gemini CLI) are automatically redirected
to the AAP authorization server's login page when no token is present.

Key features:

  • OAuth2 proxy between MCP clients and AAP auth server (OIDC discovery,
    PKCE, token exchange, revocation)
  • RFC 7591 local client registration returning pre-registered credentials
  • RFC 9728 path-specific protected resource metadata
  • Dual auth: JWT verification via JWKS with fallback to legacy /me/ validation
  • JWT audience validation (ansible-services) to prevent confused deputy attacks
  • Configurable redirect URI host allowlist (OAUTH2_ALLOWED_REDIRECT_HOSTS)
  • OIDC metadata origin validation and 10s discovery timeout
  • WWW-Authenticate headers on all 401 responses when OAuth2 is enabled
  • RFC 6750 error="invalid_token" for expired tokens to trigger refresh
  • Rate limiting on OAuth2 endpoints (60 req/min per IP)
  • Sanitized error logging to prevent log injection

New file: src/oauth2-provider.ts
Modified: src/index.ts, package.json
Documentation: docs/oauth2-integration.md

Issue: https://redhat.atlassian.net/browse/AAP-75808
Co-Authored-By: Claude Code noreply@anthropic.com

Note: this is a POC but very stable code and maybe considered as a basis for implementation.

for more details see document docs/oauth2-integration.md

Put it in draft as not intended to be merged for now

@ldjebran ldjebran added documentation Improvements or additions to documentation enhancement New feature or request labels Jun 3, 2026
@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 79.08% 711 / 899
🔵 Statements 78.75% 734 / 932
🟢 Functions 84.3% (🎯 70%) 145 / 172
🔴 Branches 68.75% (🎯 70%) 407 / 592
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/index.ts 81.4% 58.04% 89.36% 81.61% 39, 124-127, 200, 224, 233, 264-267, 302-305, 315, 358, 380, 388, 392, 406-407, 418, 430-433, 459-462, 485-499, 536, 571-601, 623-639, 679-689, 707-714, 719, 731-740, 792-793, 802-816, 843-845, 864, 924-927, 931-932
src/oauth2-provider.ts 34.48% 24.07% 47.05% 34.21% 25-31, 241-421
Generated in workflow #473 for commit 378e86a by the Vitest Coverage Report Action

Comment thread src/index.ts Fixed
Comment thread src/index.ts Fixed
Comment thread src/index.ts Fixed
@ldjebran ldjebran force-pushed the oauth2-integration branch from 0e8f6f3 to 0d3bc6c Compare June 3, 2026 16:40
Comment thread src/index.ts Fixed
@codecov-commenter

codecov-commenter commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 31.77083% with 131 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.50%. Comparing base (f25556e) to head (378e86a).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/oauth2-provider.ts 28.33% 79 Missing and 7 partials ⚠️
src/index.ts 37.50% 34 Missing and 11 partials ⚠️

Impacted file tree graph

@@             Coverage Diff             @@
##             main     #161       +/-   ##
===========================================
- Coverage   80.56%   70.50%   -10.07%     
===========================================
  Files           9       10        +1     
  Lines         772      956      +184     
  Branches      201      255       +54     
===========================================
+ Hits          622      674       +52     
- Misses         88      202      +114     
- Partials       62       80       +18     
Flag Coverage Δ
typescript 70.50% <31.77%> (-10.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/index.ts 67.42% <37.50%> (-8.80%) ⬇️
src/oauth2-provider.ts 28.33% <28.33%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ldjebran ldjebran force-pushed the oauth2-integration branch from 0d3bc6c to 0d35676 Compare June 3, 2026 16:51
Comment thread src/index.ts Fixed
Comment thread src/index.ts Fixed
@ldjebran ldjebran force-pushed the oauth2-integration branch 2 times, most recently from 6238a3e to 1757885 Compare June 3, 2026 17:21
Comment thread src/index.ts Dismissed
@ldjebran ldjebran force-pushed the oauth2-integration branch 10 times, most recently from 9267e1c to 665fb21 Compare June 10, 2026 10:17
@ldjebran ldjebran force-pushed the oauth2-integration branch from 665fb21 to 7e54367 Compare June 11, 2026 08:59
Comment thread src/index.ts Dismissed
@ldjebran ldjebran force-pushed the oauth2-integration branch 2 times, most recently from f9144df to 4ca1975 Compare June 16, 2026 08:44
Enable opt-in OAuth 2.1 authentication alongside the existing Bearer token
flow. When OAUTH2_CLIENT_ID is set, MCP clients (Claude Code, Cursor,
Gemini CLI) are automatically redirected to the AAP authorization
server's login page when no token is present.

Key features:
- OAuth2 proxy between MCP clients and AAP auth server (OIDC discovery,
  PKCE, token exchange, revocation)
- Public and confidential client support: OAUTH2_CLIENT_ID only = public
  client (PKCE only), + OAUTH2_CLIENT_SECRET = confidential client
  (PKCE + client_secret_post)
- RFC 7591 local client registration returning pre-registered credentials
- RFC 9728 path-specific protected resource metadata
- Dual auth: JWT verification via JWKS with selective fallback to legacy
  /me/ validation (claim/signature failures reject immediately, only
  structural failures fall back)
- JWT audience validation (ansible-services) to prevent confused deputy attacks
- Configurable redirect URI host allowlist (OAUTH2_ALLOWED_REDIRECT_HOSTS)
- OIDC metadata origin validation and 10s discovery timeout
- WWW-Authenticate headers on all 401 responses when OAuth2 is enabled
- RFC 6750 scope parameter in WWW-Authenticate (read/write based on ALLOW_WRITE_OPERATIONS)
- RFC 6750 error="invalid_token" for expired tokens to trigger refresh
- Configurable rate limiting on OAuth2 endpoints (OAUTH2_RATE_LIMIT,
  default 100 req/min per IP)
- X-Forwarded-For on OAuth2 proxy calls (/token, /revoke) via custom
  fetch and AsyncLocalStorage for audit traceability
- Sanitized error logging to prevent log injection
- Redirect URI rejection logging with allowed hosts for diagnostics

New file: src/oauth2-provider.ts
Modified: src/index.ts, package.json, package-lock.json
Documentation: docs/oauth2-integration.md

Issue: https://redhat.atlassian.net/browse/AAP-75808
Co-Authored-By: Claude Code <noreply@anthropic.com>
Signed-off-by: Djebran Lezzoum <ldjebran@gmail.com>
@ldjebran ldjebran force-pushed the oauth2-integration branch from 4ca1975 to 378e86a Compare June 16, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants