Skip to content

fix(oauth): apply manual-token + requiresClientSecret + app-not-found checks uniformly (#30251 follow-up)#30255

Merged
noanflaherty merged 1 commit into
mainfrom
credence/oauth-connect-followup-fixes
May 11, 2026
Merged

fix(oauth): apply manual-token + requiresClientSecret + app-not-found checks uniformly (#30251 follow-up)#30255
noanflaherty merged 1 commit into
mainfrom
credence/oauth-connect-followup-fixes

Conversation

@credence-the-bot
Copy link
Copy Markdown
Contributor

@credence-the-bot credence-the-bot Bot commented May 11, 2026

Summary

Follow-up to #30251 addressing unaddressed Codex/Devin review feedback. Three concrete fixes:

1. connect.ts reads wrong field name — manual-token guard was dead code (🔴 Devin, 🟡 Codex P2)

The IPC route serializer emits the provider's authorize URL as authUrl (camelCase), but the CLI was reading auth_url (snake_case). authorizeUrl was always undefined, so the manual-token check at line 303 (if (authorizeUrl === "urn:manual-token")) was unreachable. For BYO-mode manual-token providers like slack_channel and telegram, the CLI silently fell through to the daemon instead of returning the intended actionable error.

One-character fix: auth_urlauthUrl.

2. Daemon route bypassed manual-token + app-not-found + requiresClientSecret checks when clientId was explicitly supplied (🟡 Codex P2, 🟡 Devin)

handleOAuthConnectStart had three validations that only ran inside if (!clientId):

  • Provider not found → NotFoundError.
  • authorizeUrl === "urn:manual-token"BadRequestError.
  • requiresClientSecret && missing secret → BadRequestError.

Callers passing --client-id skipped all three. For manual-token providers this let the OAuth browser flow start when it could never succeed; for providers requiring a secret it produced a cryptic downstream error instead of an actionable one; for unregistered client IDs the call silently continued instead of failing fast.

Refactor: hoist the three checks above the branch split so they apply uniformly to both !clientId and explicit-clientId callers. Also added the missing app-not-found NotFoundError to the explicit-clientId branch.

3. Dead PlatformConnectionEntry type in shared.ts (🚩 Devin)

The interface was exported from shared.ts but had zero importers anywhere in the repo — oauth-commands-routes.ts keeps its own local copy. Removed the dead export.

Test coverage

7 new tests in oauth-connect-routes.test.ts covering every validation path the refactor touches:

  • Unknown provider → NotFoundError.
  • Manual-token provider rejected even when clientId is explicitly supplied (the bug).
  • Manual-token provider rejected when no clientId is supplied.
  • Explicit clientId with no registered app → NotFoundError (the bug).
  • No clientId and no registered app → BadRequestError.
  • Missing client_secret when requiresClientSecret is true → BadRequestError.
  • Explicit clientId + stored secret in keyring succeeds without caller-supplied secret.

Existing tests now mock oauth-store to avoid relying on the unseeded DB returning null. The removed "missing clientId throws BadRequestError" test was redundant — it was implicitly testing "no app registered" by way of an unseeded DB, which the new explicit "no clientId and no registered app" test covers properly.

19/19 tests pass in oauth-connect-routes.test.ts.

Findings explicitly NOT addressed

  • Devin 🚩 "Daemon-side readBodyData can read from daemon's stdin or filesystem" (oauth-commands-routes.ts:606-619). Devin's own analysis notes the practical risk is low (daemon stdin is /dev/null, route requires policy enforcement), and the CLI never exercises the data field (only parsed_data). Worth a separate scoping conversation rather than a defensive patch here.

Bot tags

@codex review
@devin review


Open in Devin Review

… validations to apply uniformly

Three follow-up fixes from review of #30251:

- CLI: provider serializer emits `authUrl` (camelCase) but `connect.ts` was
  reading `auth_url`, making the manual-token guard dead code for BYO-mode
  providers like slack_channel and telegram.

- Daemon: `handleOAuthConnectStart` previously ran the manual-token check,
  app-not-found error, and `requiresClientSecret` check only inside
  `if (!clientId)`. Callers passing `--client-id` bypassed all three.
  Hoisted them above the branch split so they apply uniformly, and added the
  missing app-not-found `NotFoundError` to the explicit-clientId branch.

- Cleanup: removed dead `PlatformConnectionEntry` export from
  `cli/commands/oauth/shared.ts` (zero importers in the repo).

Adds 7 new tests in `oauth-connect-routes.test.ts` covering every
validation path the refactor touches. Existing tests now mock
`oauth-store` so they no longer depend on an unseeded DB returning null.
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@noanflaherty noanflaherty merged commit 3bdf0ed into main May 11, 2026
11 of 13 checks passed
@noanflaherty noanflaherty deleted the credence/oauth-connect-followup-fixes branch May 11, 2026 03:57
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