Skip to content

refactor(auth): migrate custom OAuth app login to the device flow - #3449

Open
setchy wants to merge 2 commits into
mainfrom
refactor/migrate-oauth-app-login-to-device-flow
Open

setchy wants to merge 2 commits into
mainfrom
refactor/migrate-oauth-app-login-to-device-flow

Conversation

@setchy

@setchy setchy commented Oct 17, 2026

Copy link
Copy Markdown
Member

Summary

Replaces the client-secret OAuth web flow for user-supplied ("custom") OAuth apps with the OAuth device flow, which authorizes using only a public client ID — no secret, and no gitify:// custom-protocol redirect.

A desktop app is an OAuth public client and cannot keep a client secret confidential, and the gitify:// custom-scheme callback can be registered by any local app. The device flow removes both. Gitify's built-in GitHub sign-in already used the device flow, so this makes it the single OAuth mechanism for both sign-in paths.

What changed

  • New: a "Custom OAuth App" sign-in collecting a hostname + client ID (no secret), reusing the shared device-flow authorization and public/recommended scope UI.
  • Retired: the /login/github/oauth-app web-flow route, the authorization-code + secret exchange, the oauthWebApp adapter bundle, and the gitify:// custom-protocol callback (Electron main open-url/handleProtocolURL, preload onAuthCallback, and the AUTH_CALLBACK IPC event).
  • Renamed: auth-method labels GitHub App → Gitify OAuth App and OAuth App → Custom OAuth App; the custom app's client ID is persisted so its developer-settings link targets the user's own app.
  • Migration: persisted accounts are relabelled on load; tokens keep working and no re-login is forced.
  • Errors: device_flow_disabled and unrecognized client IDs surface actionable guidance (enable device flow in the app's settings / the client ID is invalid for the host).

Compatibility

Existing custom-app and built-in accounts keep working without re-authentication. On a host where Gitify's app is disallowed (e.g. enterprise OAuth-app restrictions), the user registers their own OAuth app, enables its device flow, and signs in with that client ID.

BREAKING: the gitify:// custom-protocol callback is removed.

Testing

  • pnpm check (lint + format + types): clean
  • pnpm test: 1911 passing
  • pnpm test:visual: 60 passing — baselines updated (new login-github-custom-oauth-app route, retired login-github-oauth-app removed)

Note: src/main/ciDependencyCompatibility.test.ts fails locally due to a stale node_modules/playwright (1.63.0) versus the workflow pin (1.64.0); unrelated to this change.

Replace the client-secret OAuth web flow for user-supplied ("custom") OAuth
apps with the OAuth device flow, which authorizes using only a public client ID.

- Add a custom OAuth app sign-in that collects a hostname and client ID and
  reuses the shared device-flow authorization and scope UI; no client secret.
- Retire the web flow end to end: the /login/github/oauth-app route, the
  authorization-code + secret exchange, the oauthWebApp adapter bundle, and the
  gitify:// custom-protocol callback across the Electron main process, preload,
  and the shared IPC event.
- Rename auth-method labels: GitHub App -> Gitify OAuth App, OAuth App ->
  Custom OAuth App; persist the custom app's client ID for its settings link.
- Migrate persisted accounts on load without forcing re-login.
- Surface actionable guidance for device_flow_disabled and unknown client IDs.
Follow-up naming pass on the device-flow migration:

- Rename describeDeviceFlowError -> describeDeviceFlowStartError; it only
  covers start-time failures (device_flow_disabled / unknown client ID), not
  poll errors.
- Group the custom OAuth app helpers (authMethod, validateClientId,
  getNewOAuthAppUrl) into a customOAuthApp adapter bundle, so validateClientId
  and getNewOAuthAppUrl live together instead of split across the top-level
  adapter and the deviceFlow bundle.
- Have useLogins derive the recorded auth method from the adapter's
  customOAuthApp bundle rather than hardcoding 'Custom OAuth App'.
- Extract GitHubDeviceFlowAuthorize as the shared authorization UI and keep
  GitHubLoginWithDeviceFlowRoute as the thin built-in route element, so the
  custom route composes a mechanism-named component rather than a login route.
- Rename effectiveHostname -> resolvedHostname and migrateAuthMethod ->
  migrateLegacyAuthMethod.
@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Refactoring of existing feature

Development

Successfully merging this pull request may close these issues.

1 participant