Skip to content

feat: oauth authentication#320

Open
gabrielmfern wants to merge 38 commits into
mainfrom
feat/oauth
Open

feat: oauth authentication#320
gabrielmfern wants to merge 38 commits into
mainfrom
feat/oauth

Conversation

@gabrielmfern

@gabrielmfern gabrielmfern commented Jun 5, 2026

Copy link
Copy Markdown
Member

this will only work with the staging api for now, but that's fine. the cleint id is hard coded, and, for consistency, I think we should ensure this exact client id also used in the production oauth client for the CLI

I've verified this does indeed work with the non-sending apis


Summary by cubic

Adds OAuth authentication to the CLI with a browser-based PKCE flow, secure secret storage, and unified credential handling (API keys or OAuth) across commands. Updates login, whoami, doctor, and client auth to support tokens, scopes, and better UX without breaking existing API keys.

  • New Features

    • resend login: adds “Login with Resend” (opens browser), uses a local loopback callback with state checks, ignores non-callback requests, renders a styled success/failure page, times out after 5 minutes, exchanges the code, closes the local server, and saves the grant per profile. Reports where credentials are stored and, on Linux, hints how to enable secure storage. API key flows remain (open API-keys page or manual entry).
    • OAuth grants: secrets go to secure storage (keychain blob) when available; only metadata stays in credentials.json. Plaintext fallback if no secure storage. Overwriting replaces old secrets, we roll back the keychain secret if the metadata write fails, and storage is set to secure_storage or file.
    • Token handling: access expiry is read from a validated JWT exp; /oauth/token responses are schema‑validated; token requests time out after 30s; refresh happens on demand with a 60s leeway before expiry; transient network/timeout errors are labeled and treated as warnings in doctor. Uses RESEND_BASE_URL and OAUTH_CLIENT_ID.
    • Unified auth: resolveAuthentication returns an API key or an OAuth grant; createClient/requireClient use the right token; maps OAuth scopes (full_access, emails:send) to CLI permissions and blocks unknown scopes with a clear error; errors refer to “credentials,” not just keys.
    • CLI UX: whoami is local‑only (no refresh), labels OAuth as “Token,” masks values, and reports the correct source (flag, env, config, or secure_storage); doctor is local‑only for presence and validates the credential against the API, shows OAuth details, treats transient refresh failures as warnings, and fails validation only when the server rejects the credential.
  • Migration

    • No action needed; existing API keys continue to work.
    • credentials.json now stores a type per profile and supports OAuth grants; with secure storage, only grant metadata is in the file.
    • Secure‑storage secrets are replaced automatically if you switch credential types for a profile.
    • To use OAuth, run resend login and choose “Login with Resend.”

Written for commit 1613285. Summary will update on new commits.

Review in cubic

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

0 issues found across 6 files (changes from recent commits).

Requires human review: This PR introduces a new OAuth authentication flow with PKCE, token refresh, and credential migration across multiple commands and core libraries, which is a high-risk change to critical authentication logic that requires human review for security, correctness, and integration with existing API key

Re-trigger cubic

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

7 issues found

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread src/lib/oauth.ts
Comment thread src/lib/config.ts Outdated
Comment thread src/lib/client.ts Outdated
Comment thread src/lib/oauth.ts Outdated
Comment thread src/commands/whoami.ts
Comment thread src/commands/auth/login.ts Outdated
Comment thread src/commands/auth/login.ts Outdated

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Auto-approval blocked by 6 unresolved issues from previous reviews.

Re-trigger cubic

Comment thread src/lib/oauth.ts Outdated
Comment thread src/lib/config.ts Outdated
Comment thread src/commands/whoami.ts
Comment thread src/lib/config.ts Outdated
Comment thread src/lib/config.ts Outdated
Comment thread src/lib/oauth.ts Outdated
Comment thread src/lib/oauth.ts Outdated

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

2 issues found across 5 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread src/lib/oauth.ts Outdated
Comment thread src/lib/config.ts Outdated
Comment thread src/lib/oauth.ts Outdated
gabrielmfern and others added 12 commits June 25, 2026 15:55
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Signed-off-by: Gabriel Miranda <gabrielmfern@outlook.com>
Felipe review (#1): getJwtExp cast the decoded payload without guards, so a
malformed access token would throw a cryptic error or store NaN/undefined as
the expiry, leaving the credential in an inconsistent state. Validate segment
count, JSON payload, and numeric exp, throwing a clear re-login message.
Felipe review (#6): both refreshOAuthGrant and exchangeAuthorizationCode cast
the JSON body with `as` after only checking response.ok. A 200 with an
unexpected body (proxy error page, partial payload) would be persisted as a
grant. Add parseTokenResponse() to validate the required fields and reuse it in
both token calls.
Felipe review (#8): the refresh and exchange fetches had no timeout, so a hung
connection would make the CLI wait forever. Route both through a shared
fetchOAuthToken helper that aborts after 30s (AbortSignal.timeout) and maps
TimeoutError / network failures to clear, actionable messages.
Felipe review (#7): the loopback callback always rendered "Authentication
complete", even when the provider returned ?error= or omitted code/state. Render
a distinct "Authentication failed" page in those cases so the user isn't told
success while the terminal reports failure. Promise resolve/reject logic is
unchanged.
Comment thread src/lib/oauth.ts Outdated
Comment thread src/commands/whoami.ts Outdated
Comment thread src/commands/doctor.ts Outdated
Comment thread src/commands/doctor.ts Outdated
Comment thread src/lib/client.ts Outdated

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

0 issues found across 3 files (changes from recent commits).

Requires human review: Implements OAuth authentication with PKCE flow, token refresh, and secure credential storage across the CLI. This is a major architectural change affecting auth, credential management, and API client construction.

Re-trigger cubic

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

0 issues found across 2 files (changes from recent commits).

Requires human review: Adds OAuth authentication, a major new feature affecting core login, credential storage, and multiple commands. High risk; requires human review.

Re-trigger cubic

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

2 issues found across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread tests/lib/oauth.test.ts
Comment thread tests/lib/oauth.test.ts

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

0 issues found across 5 files (changes from recent commits).

Requires human review: Auto-approval blocked by 2 unresolved issues from previous reviews.

Re-trigger cubic

@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 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread src/commands/doctor.ts

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

0 issues found across 2 files (changes from recent commits).

Requires human review: Auto-approval blocked by 3 unresolved issues from previous reviews.

Re-trigger cubic

@dielduarte dielduarte requested a review from felipefreitag June 26, 2026 14:26

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

0 issues found across 1 file (changes from recent commits).

Requires human review: This is a major feature adding OAuth authentication (PKCE, token refresh, credential store) affecting core CLI auth, login, doctor, whoami, and client creation. High risk of breakage in authentication, credential management, and backward compatibility.

Re-trigger cubic

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

0 issues found across 1 file (changes from recent commits).

Requires human review: Major new feature (OAuth authentication) with 1990 lines changed across core config, client, and auth logic. High risk and impact.

Re-trigger cubic

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

0 issues found across 1 file (changes from recent commits).

Re-trigger cubic

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.

3 participants