Skip to content

refactor(oauth-config): use shared authorization attempts - #14158

Open
wenxi-onyx wants to merge 1 commit into
whuang/external-app-oauth-attemptsfrom
whuang/action-oauth-attempts
Open

refactor(oauth-config): use shared authorization attempts#14158
wenxi-onyx wants to merge 1 commit into
whuang/external-app-oauth-attemptsfrom
whuang/action-oauth-attempts

Conversation

@wenxi-onyx

@wenxi-onyx wenxi-onyx commented Aug 22, 2026

Copy link
Copy Markdown
Member

Description

OAuth-protected actions previously reused the federated-connector state format. That coupling did not provide the same owner-bound, atomic callback lifecycle used by the other OAuth connection flows and left PKCE and pending-configuration validation outside the action flow.

This change migrates OAuth actions to the shared authorization-attempt store. The feature declares its namespace and payload type once and reuses the base implementation for tenant-aware cache resolution, TTL, fingerprint validation, PKCE-verifier constraints, protected authorization parameters, and safe return paths. Initiation creates an owner-bound attempt with a server-side verifier and configuration fingerprint; the callback atomically claims it, rejects changed configuration, exchanges the code with PKCE, and persists the token through the existing OAuthConfig path.

OAuthConfig lookup, permissions, fingerprint inputs, token persistence, and action behavior remain feature-owned, so this completes the lifecycle migration without introducing a universal provider abstraction.

How Has This Been Tested?

Additional Options

  • [Optional] Please cherry-pick this PR to the latest release version.
  • [Optional] Override Linear Check

@wenxi-onyx
wenxi-onyx requested a review from a team as a code owner August 22, 2026 00:04
@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR moves OAuth-config authorization state into the shared one-time authorization-attempt store and adds owner binding, PKCE, configuration fingerprinting, and safe return-path validation.

  • Stores overlapping authorization attempts independently with a ten-minute lifetime.
  • Rejects changed OAuth configurations and conflicting authorization parameters.
  • Extends shared token helpers to accept optional PKCE inputs.
  • Adds unit coverage for ownership, one-time consumption, PKCE, configuration changes, and return paths.

Confidence Score: 4/5

The PR should not merge until OAuth configurations for providers without PKCE support remain usable.

The generic OAuth-config path now sends PKCE parameters to every provider, while related flows require an explicit provider capability before doing so.

Files Needing Attention: backend/onyx/server/features/oauth_config/api.py

Important Files Changed

Filename Overview
backend/onyx/auth/oauth_token_manager.py Adds optional PKCE inputs to shared authorization and token-exchange helpers and exposes OAuth flow parameters.
backend/onyx/server/features/oauth_config/api.py Replaces legacy state handling with owner-bound shared attempts, but unconditionally enables PKCE for arbitrary providers.
backend/onyx/server/features/oauth_config/models.py Restricts OAuth completion redirects to validated internal return paths.
backend/tests/unit/onyx/server/features/oauth_config/test_oauth_flow.py Covers the new attempt lifecycle and validation, but only tests a provider that accepts PKCE.

Sequence Diagram

sequenceDiagram
  participant U as User
  participant API as OAuth Config API
  participant Cache as Authorization Attempt Store
  participant P as OAuth Provider
  participant DB as Database
  U->>API: POST /oauth-config/initiate
  API->>Cache: Store owner, config fingerprint, return path, verifier
  API-->>U: Authorization URL with state and PKCE challenge
  U->>P: Authorize
  P-->>U: Callback with code and state
  U->>API: POST /oauth-config/callback
  API->>Cache: Consume owner-bound attempt
  API->>API: Verify configuration fingerprint
  API->>P: Exchange code and PKCE verifier
  P-->>API: Access token
  API->>DB: Store user OAuth token
  API-->>U: Return safe redirect path
Loading
Prompt To Fix All With AI
### Issue 1
backend/onyx/server/features/oauth_config/api.py:275-282
**Unconditional PKCE breaks provider compatibility**

If an existing OAuth configuration uses a provider that does not support PKCE or rejects unknown protocol parameters, this path always sends a `code_challenge` and later a `code_verifier`, causing authorization or token exchange to fail without storing a token. The other provider-agnostic OAuth flows gate PKCE behind an explicit capability flag.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "refactor(oauth-config): use shared autho..." | Re-trigger Greptile

Comment on lines +275 to +282
code_verifier, code_challenge = generate_pkce_pair()
state = generate_authorization_state()

# Build authorization URL
redirect_uri = f"{WEB_DOMAIN}/oauth-config/callback"
authorization_url = OAuthTokenManager.build_authorization_url(
oauth_config, redirect_uri, state
oauth_config,
_oauth_callback_url(),
state,
code_challenge=code_challenge,

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.

P1 Unconditional PKCE breaks provider compatibility

If an existing OAuth configuration uses a provider that does not support PKCE or rejects unknown protocol parameters, this path always sends a code_challenge and later a code_verifier, causing authorization or token exchange to fail without storing a token. The other provider-agnostic OAuth flows gate PKCE behind an explicit capability flag.

Knowledge Base Used: Restore the previous OAuth login flow

Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/onyx/server/features/oauth_config/api.py
Line: 275-282

Comment:
**Unconditional PKCE breaks provider compatibility**

If an existing OAuth configuration uses a provider that does not support PKCE or rejects unknown protocol parameters, this path always sends a `code_challenge` and later a `code_verifier`, causing authorization or token exchange to fail without storing a token. The other provider-agnostic OAuth flows gate PKCE behind an explicit capability flag.

**Knowledge Base Used:** [Restore the previous OAuth login flow](https://app.greptile.com/onyx/-/custom-context/knowledge-base/onyx-dot-app/onyx/-/reverts/revert_7593-20260120-fastapi-users-oauth-csrf-010bc36.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@github-actions

github-actions Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Full-stack Preview (frontend + backend)

Status Preview Commit Updated
https://2d8f3d4-onyx.preview.onyxcorp.dev/ 2d8f3d4 2026-08-22 00:25:22 UTC

Sign in with GitHub as an onyx-dot-app member to view it.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8115ace314

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

redirect_uri=request.return_path,
additional_data={"oauth_config_id": request.oauth_config_id},
)
_validate_additional_authorization_params(oauth_config)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve configured OAuth resource parameters

When an OAuth config supplies the RFC 8707 resource value through additional_params, this validation now rejects initiation. conflicting_authorization_params() reserves resource, but this flow never supplies a replacement to build_authorization_url(). Such configs worked before this change and now have no supported way to send the required resource value.

Useful? React with 👍 / 👎.

additional_data={"oauth_config_id": request.oauth_config_id},
)
_validate_additional_authorization_params(oauth_config)
code_verifier, code_challenge = generate_pkce_pair()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make PKCE optional for providers that do not support it

When a configured provider does not support PKCE, this unconditional generation makes every OAuth-config flow send an S256 challenge and verifier. Other repository OAuth flows check a supports_pkce capability because some providers reject these fields. OAuthConfig has no equivalent setting, so previously working non-PKCE integrations can no longer complete authorization.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 4 files

Confidence score: 3/5

  • backend/onyx/server/features/oauth_config/api.py sends PKCE parameters to every configured OAuth provider, which can cause providers that reject or lack PKCE support to fail during authorization or token exchange; gate generation and exchange on an explicit provider capability.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/onyx/server/features/oauth_config/api.py">

<violation number="1" location="backend/onyx/server/features/oauth_config/api.py:275">
P1: Gate PKCE generation and exchange on an explicit provider capability. This currently sends `code_challenge` to every configured provider and later sends `code_verifier`, so providers that reject or do not support PKCE cannot complete OAuth.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

additional_data={"oauth_config_id": request.oauth_config_id},
)
_validate_additional_authorization_params(oauth_config)
code_verifier, code_challenge = generate_pkce_pair()

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.

P1: Gate PKCE generation and exchange on an explicit provider capability. This currently sends code_challenge to every configured provider and later sends code_verifier, so providers that reject or do not support PKCE cannot complete OAuth.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/onyx/server/features/oauth_config/api.py, line 275:

<comment>Gate PKCE generation and exchange on an explicit provider capability. This currently sends `code_challenge` to every configured provider and later sends `code_verifier`, so providers that reject or do not support PKCE cannot complete OAuth.</comment>

<file context>
@@ -215,18 +271,25 @@ def initiate_oauth_flow(
-        additional_data={"oauth_config_id": request.oauth_config_id},
-    )
+    _validate_additional_authorization_params(oauth_config)
+    code_verifier, code_challenge = generate_pkce_pair()
+    state = generate_authorization_state()
 
</file context>

@github-actions

Copy link
Copy Markdown
Contributor

🖼️ Visual Regression Report

Project Changed Added Removed Unchanged Report
admin 0 187 0 0 View Report
exclusive 0 10 0 0 View Report

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.

1 participant