Skip to content

feat(backend): derive JWT issuer and OAuth redirect_uri from request host#1498

Merged
BilalG1 merged 3 commits into
devfrom
feat/host-aware-api-url
May 28, 2026
Merged

feat(backend): derive JWT issuer and OAuth redirect_uri from request host#1498
BilalG1 merged 3 commits into
devfrom
feat/host-aware-api-url

Conversation

@BilalG1
Copy link
Copy Markdown
Collaborator

@BilalG1 BilalG1 commented May 27, 2026

Summary

When the backend serves both api.stack-auth.com and api.hexclave.com from the same deployment, signed JWT iss claims and OAuth redirect_uri values need to match the host the customer's SDK actually talks to — otherwise customers with hardcoded issuer checks or registered OAuth callback URLs break when their SDK upgrades. This PR makes both follow the request host.

Closes the "Interpretation B" plan from our earlier discussion.

Changes

Backend — request-host-derived iss and redirect_uri

  • New helper apps/backend/src/lib/request-api-url.ts exports getApiUrlForRequest(req) and getApiUrlForHost(host). A consolidated CLOUD_HOST_PAIRS constant is the single source of truth for the stack-auth ↔ hexclave host pairs (prod, dev, staging). Both the allowlist here and the validator alias map in tokens.tsx derive from it, so they can never drift again.
  • JWT issuer per request (apps/backend/src/lib/tokens.tsx) — getIssuer now takes apiUrl. generateAccessTokenFromRefreshTokenIfValid and createAuthTokens accept an apiUrl parameter that flows into the iss claim. getAllowedIssuers stays env-driven with the bidirectional alias map, so tokens cross-validate across hosts.
  • OAuth redirect_uri per request — all 12 providers + MockProvider now take apiUrl and use it to build redirect_uri = apiUrl + "/api/v1/auth/oauth/callback/<provider>". getProvider() accepts an { apiUrl } option and forwards it.
  • OAuth2Server factory — the module-level oauthServer singleton became a per-request createOAuthServer({ apiUrl }) factory so OAuthModel.generateAccessToken mints tokens with the right iss. Used in the callback route, the token route, and the cross-domain-authorize helper.
  • Token-minting call sites updated — all 10 createAuthTokens invocations (password sign-up/sign-in, sessions create, sessions/current/refresh, anonymous sign-up, apple-native callback, MFA/OTP/passkey sign-in, OAuth model token exchange), plus the CLI-complete generateAccessTokenFromRefreshTokenIfValid direct call, now pass getApiUrlForRequest(fullReq).
  • createVerificationCodeHandler refactored to pass apiUrl as a 6th positional arg to the user's handler, so MFA/OTP/passkey sign-in flows get the same per-request iss as the rest. The other 8 callers (password-reset, contact-channels-verify, etc.) don't need changes — they accept fewer args and TS function-arity compatibility makes that fine.

SDK — freeze @stackframe/* defaults at stack-auth.com

  • packages/template/src/lib/stack-app/apps/implementations/common.ts reverts defaultBaseUrl and defaultAnalyticsBaseUrl to https://api.stack-auth.com / https://r.stack-auth.com. A customer who upgrades their @stackframe/* package to the latest version without explicitly migrating to @hexclave/* keeps hitting api.stack-auth.com and never sees their JWT iss or OAuth redirect_uri change.
  • The @hexclave/* mirror packages are unaffected because they were published from source when defaultBaseUrl = "https://api.hexclave.com"; v1.0.0 already targets the hexclave host on npm. Extending scripts/rewrite-packages-to-hexclave.ts to substitute these literals during future republishes is a separate follow-up.

Docs — migration guide rewrite

  • docs-mintlify/migration.mdx rewritten concisely. Spells out the two host-visible changes that require pre-deploy action when migrating to @hexclave/*: updating manual JWT verifier code (with the array-of-issuers pattern) and updating OAuth callback URLs at each provider (with the GitHub-OAuth-Apps single-URL caveat explicitly called out).

What was deliberately left out

  • Rewriter pipeline extension for @hexclave/* republishes — separate follow-up.
  • Cross-SDK defaults (Swift, stack-cli, init-stack still default to api.hexclave.com) — out of scope per discussion.
  • Dashboard launch-checklist host-awareness — out of scope per discussion (callback URLs stay hexclave-branded in the dashboard UI).

Verification

  • pnpm typecheck — 29/29 packages pass.
  • pnpm lint — 29/29 packages pass.
  • Five parallel review agents (JWT, OAuth, helper, migration guide, SDK defaults) + an external review of the commit caught four real issues — all resolved in the same commit before push:
    • Missing api.staging.* entries in issuerHostAliases (would have broken cross-host token validation on staging).
    • Stale comment in apps/backend/src/stack.tsx.
    • Misleading "backward-compat" comment in getHardcodedFallbackUrls.
    • MFA/OTP/passkey using env-var fallback for iss instead of the request host.

Summary by cubic

Makes JWT issuers and OAuth redirect_uri values follow the incoming request’s host so tokens and redirects always match api.stack-auth.com or api.hexclave.com. Also freezes @stackframe/* SDK defaults to Stack Auth and tightens the migration guide to focus on OAuth callbacks.

  • New Features

    • Added request-api-url helper with an allowlist of cloud hosts; unknown hosts fall back to the deployment’s API URL.
    • JWT iss now uses the per-request API URL; validation accepts both brands via aliases derived from one CLOUD_HOST_PAIRS source.
    • All OAuth providers build redirect_uri from the request host; getProvider() now takes { apiUrl }.
    • Replaced the OAuth2Server singleton with per-request createOAuthServer({ apiUrl }) so token exchange mints with the right issuer.
    • Updated token-minting and OAuth routes to pass the API URL; verification-code flows receive it; connected-accounts refresh paths safely pin the deployment default.
    • SDK: @stackframe/* defaults point to https://api.stack-auth.com; @hexclave/* mirrors remain hexclave-branded.
    • Shared: updated fallback API host lists to include both stack-auth and hexclave hosts.
  • Migration

    • Update each provider’s OAuth callback URL to https://api.hexclave.com/api/v1/auth/oauth/callback/<provider> when migrating to @hexclave/*.
    • If you verify JWTs manually, update the expected issuer to the hexclave host (including anonymous/restricted variants).

Written for commit e42dfaf. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Per-request API host awareness so tokens and OAuth flows reflect the incoming request’s canonical API URL.
  • Updates

    • OAuth providers and servers now derive callback/redirect URLs from request context rather than a static URL.
    • Token issuance/validation now embeds and accepts host-specific issuer URLs and paired host aliases for rebrand compatibility.
  • Documentation

    • Migration guide updated for branding, JWT issuer expectations, and OAuth callback guidance.

Review Change Stack

…host

When the backend serves both api.stack-auth.com and api.hexclave.com from the
same deployment, signed tokens and OAuth redirect URIs need to match the host
the customer's SDK actually talks to — otherwise customers with hardcoded
issuer checks or registered OAuth callback URLs break when the SDK upgrades.

This change:

- Adds apps/backend/src/lib/request-api-url.ts with getApiUrlForRequest()
  that maps known cloud hosts (stack-auth.com, hexclave.com, plus dev/staging
  variants) to their own URLs; unknown hosts (localhost, previews, self-host)
  fall back to NEXT_PUBLIC_STACK_API_URL.
- Threads apiUrl through getIssuer + signJWT in tokens.tsx so the iss claim
  follows the request host. getAllowedIssuers stays env-driven with the
  existing alias map, so tokens cross-validate between the two hosts.
- Refactors all 12 OAuth providers + Mock to take apiUrl, used to build the
  redirect_uri sent to Google/GitHub/etc. getProvider() forwards the value
  from the route handler.
- Converts the OAuth2Server singleton to a per-request createOAuthServer()
  factory so OAuthModel.generateAccessToken signs with the right issuer.
- Wires getApiUrlForRequest() into all token-minting and provider-instantiating
  route handlers (10 createAuthTokens sites, the authorize/callback/token/
  cross-domain-authorize routes, connected-accounts crud).

For the SDK side:

- Reverts packages/template defaultBaseUrl / defaultAnalyticsBaseUrl back to
  stack-auth.com so the next @stackframe/* publish keeps existing customers
  pointed at the legacy host. The @hexclave/* mirror publishing pipeline
  (rewrite-packages-to-hexclave.ts) is unchanged here; flipping it to
  substitute these literals during republish lands in a follow-up.

For the docs side:

- Rewrites docs-mintlify/migration.mdx to clearly call out the two host-
  visible changes (JWT iss claim and OAuth callback URLs) that require
  pre-deploy action when migrating to @hexclave/*, with the GitHub-OAuth-App
  single-URL caveat spelled out.

Verification: pnpm typecheck and pnpm lint pass clean across all 29 packages.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-auth-internal-tool Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-auth-mcp Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-auth-skills Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-backend Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-dashboard Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-demo Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-docs Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-preview-backend Ready Ready Preview, Comment May 27, 2026 8:48pm
stack-preview-dashboard Ready Ready Preview, Comment May 27, 2026 8:48pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

📝 Walkthrough

Walkthrough

This PR threads request-derived API URLs (apiUrl) through token creation and OAuth initialization. It adds a request-api-url helper with host-pair allowlisting, updates token issuer construction/validation to accept apiUrl, replaces the oauthServer singleton with a per-request factory, and changes all OAuth providers to build redirect URIs from apiUrl.

Changes

Request-aware API URL and token issuer rebrand

Layer / File(s) Summary
Request API URL infrastructure and host pair mapping
apps/backend/src/lib/request-api-url.ts
Introduces CLOUD_HOST_PAIRS and functions to normalize hostnames and derive canonical apiUrl from request headers with env fallback.
Token issuer and validation for paired hosts
apps/backend/src/lib/tokens.tsx
Threads apiUrl through access-token generation and signing, changes issuer construction to accept apiUrl, and accepts alias issuers derived from CLOUD_HOST_PAIRS. Adds GenerateAccessTokenOptions and CreateAuthTokensOptions.
OAuth module per-request factory and provider parameterization
apps/backend/src/oauth/index.tsx, apps/backend/src/oauth/model.tsx
Replaces module-level oauthServer with createOAuthServer({ apiUrl }), updates getProvider to accept apiUrl options, and stores apiUrl in OAuthModel for per-request token generation.
OAuth provider implementations updated for apiUrl
apps/backend/src/oauth/providers/*.tsx
All provider .create(...) factories now accept apiUrl and compute redirectUri from it instead of reading NEXT_PUBLIC_STACK_API_URL.
Verification code handler factory threading
apps/backend/src/route-handlers/verification-code-handler.tsx
Derives apiUrl from the incoming request and passes it to handler callbacks so verification-based flows can forward apiUrl into token generation.
Auth routes: password, anonymous, MFA, OTP, passkey token generation
apps/backend/src/app/api/latest/auth/*
Sign-up/sign-in and verification handlers import getApiUrlForRequest, accept fullReq where required, and pass apiUrl into createAuthTokens / access-token generation.
Auth routes: session creation and access token refresh
apps/backend/src/app/api/latest/auth/sessions/*
Session creation and refresh endpoints derive apiUrl from request and pass it to createAuthTokens and generateAccessTokenFromRefreshTokenIfValid.
Auth routes: OAuth authorize and cross-domain authorize
apps/backend/src/app/api/latest/auth/oauth/*
OAuth authorize, callback, token, and cross-domain flows derive apiUrl from request and pass it to getProvider and createOAuthServer, removing reliance on module-level oauthServer.
Auth routes: OAuth apple native callback, CLI complete, token endpoint
apps/backend/src/app/api/latest/auth/oauth/callback/apple/native/route.tsx, apps/backend/src/app/api/latest/auth/cli/complete/route.tsx, apps/backend/src/app/api/latest/auth/oauth/token/route.tsx
Apple native callback and CLI complete now pass request-derived apiUrl into token generation; token endpoint constructs a per-request OAuth server via createOAuthServer({ apiUrl }).
Connected accounts access token CRUD handlers
apps/backend/src/app/api/latest/connected-accounts/*/access-token/crud.tsx
getProvider is called with a pinned apiUrl (from NEXT_PUBLIC_STACK_API_URL) for refresh/validity checks to avoid alternate-branded-host pitfalls.
SDK defaults and migration documentation updates
packages/template/src/lib/stack-app/apps/implementations/common.ts, packages/stack-shared/src/utils/urls.tsx, docs-mintlify/migration.mdx, apps/backend/src/stack.tsx
Updates SDK default API/analytics host literals, reorders fallback logic, and revises migration docs to explain JWT issuer and OAuth redirect_uri hostname changes and install steps.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • N2D4
  • nams1570

"I hopped through headers, tails in the breeze,
I matched host pairs with elegant ease.
Tokens wear the right issuer crown,
Redirects follow apiUrl all around town.
A rabbit's cheer for the rebrand release!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the main change: deriving JWT issuer and OAuth redirect_uri from the request host, which directly addresses the core objective.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive and well-structured. It clearly explains the motivation (serving both api.stack-auth.com and api.hexclave.com from one deployment), details all backend and SDK changes, documents the migration guide rewrite, explicitly states scope boundaries, and includes verification steps. The description follows the spirit of the repository's guidelines by providing context and rationale.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/host-aware-api-url

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 27, 2026

Greptile Summary

This PR makes the JWT iss claim and OAuth redirect_uri follow the incoming request's host (either api.stack-auth.com or api.hexclave.com) rather than always using NEXT_PUBLIC_STACK_API_URL. A new CLOUD_HOST_PAIRS constant is the single source of truth that drives both the allowlist in getApiUrlForRequest and the bidirectional issuerHostAliases validator map, preventing drift between signing and validation.

  • Backend: getApiUrlForHost/getApiUrlForRequest helpers added; all 10+ token-minting call sites, all 13 OAuth providers, and the OAuthModel/OAuthServer factory updated to accept and forward a per-request apiUrl.
  • SDK defaults: @stackframe/* defaultBaseUrl reverted to api.stack-auth.com so customers on the legacy package keep a stable iss and OAuth callback URL until they explicitly migrate.
  • Docs: Migration guide rewritten to front-load the two pre-migration requirements (JWT verifier update and OAuth callback URL re-registration).

Confidence Score: 4/5

The core mechanism is implemented consistently across all call sites; the two findings are a documentation gap and a comment clarification with no runtime impact.

The logic changes are comprehensive and internally consistent: CLOUD_HOST_PAIRS drives both the signing allowlist and the validation alias map, preventing the drift bug called out in the PR description. All 10+ token-minting call sites pass apiUrl, and getAllowedIssuers correctly expands to both hosts for every supported cloud-host pair including staging. The two findings are a documentation gap in the migration guide and a comment clarification — neither affects runtime correctness.

The migration guide (docs-mintlify/migration.mdx) dropped the @stackframe/emails row from the package table. apps/backend/src/lib/request-api-url.ts has a trust-model comment that should be clarified for non-Vercel deployers.

Important Files Changed

Filename Overview
apps/backend/src/lib/request-api-url.ts New file — exports CLOUD_HOST_PAIRS (single source of truth for paired hosts), CLOUD_API_HOSTS allowlist, getApiUrlForHost (with port-stripping via split(":")), and getApiUrlForRequest. Logic is straightforward; fallback to NEXT_PUBLIC_STACK_API_URL for non-cloud hosts is safe.
apps/backend/src/lib/tokens.tsx getIssuer now accepts apiUrl param; CLOUD_HOST_PAIRS drives issuerHostAliases bidirectionally (all 6 cloud hosts covered including staging). getAllowedIssuers stays env-var–based and returns both the primary and its alias, ensuring tokens minted under either host validate correctly.
apps/backend/src/oauth/index.tsx Module-level oauthServer singleton replaced with createOAuthServer({ apiUrl }) factory. getProvider updated to accept options.apiUrl and thread it into all 13 provider constructors. Pattern is consistent across all call sites.
apps/backend/src/oauth/model.tsx OAuthModel gains a constructor argument apiUrl, stored as readonly field and passed to generateAccessTokenFromRefreshTokenIfValid. Since the server is built per-request, each token exchange uses the request's host for the iss claim.
apps/backend/src/route-handlers/verification-code-handler.tsx Handler callback type gains 6th apiUrl param; fullReq is now threaded through so MFA/OTP/passkey sign-in handlers receive the per-request host. TypeScript arity compatibility keeps the 8 non-token-minting callers unchanged.
docs-mintlify/migration.mdx Migration guide rewritten to front-load pre-migration requirements (JWT verifier update, OAuth callback URL re-registration). The @stackframe/emails → @hexclave/emails row was dropped from the package mapping table.
packages/template/src/lib/stack-app/apps/implementations/common.ts defaultBaseUrl reverted to api.stack-auth.com; analyticsBaseUrlsByApiBaseUrl updated so both stack-auth and hexclave URLs resolve to the correct analytics host. The hexclave entry is now forward compat for @hexclave/* mirror packages.
packages/stack-shared/src/utils/urls.tsx Cosmetic reordering of getHardcodedFallbackUrls branches — stack-auth entries now precede hexclave entries. No functional change.

Sequence Diagram

sequenceDiagram
    participant SDK as SDK (api.stack-auth.com)
    participant BE as Backend
    participant Helper as getApiUrlForRequest
    participant Tokens as tokens.tsx / getIssuer
    participant Provider as OAuthProvider
    participant ExtOAuth as External OAuth Provider

    Note over SDK,BE: Password/anonymous/session sign-in flows
    SDK->>BE: POST /auth/password/sign-in (Host: api.stack-auth.com)
    BE->>Helper: getApiUrlForRequest(fullReq)
    Helper-->>BE: https://api.stack-auth.com
    BE->>Tokens: "createAuthTokens({ apiUrl })"
    Tokens-->>SDK: "JWT with iss=https://api.stack-auth.com/api/v1/projects/..."

    Note over SDK,ExtOAuth: OAuth flow
    SDK->>BE: GET /auth/oauth/authorize/github (Host: api.stack-auth.com)
    BE->>Helper: getApiUrlForRequest(fullReq)
    Helper-->>BE: https://api.stack-auth.com
    BE->>Provider: "getProvider(cfg, { apiUrl })"
    Provider-->>BE: "redirectUri = https://api.stack-auth.com/.../callback/github"
    BE-->>SDK: Redirect to GitHub with redirect_uri
    ExtOAuth->>BE: GET /auth/oauth/callback/github (Host: api.stack-auth.com)
    BE->>Helper: getApiUrlForRequest(callbackReq)
    Helper-->>BE: https://api.stack-auth.com
    BE->>Provider: "getProvider(cfg, { apiUrl }) — redirectUri matches authorize step"
    BE->>Tokens: "createAuthTokens({ apiUrl })"
    Tokens-->>SDK: "JWT with iss=https://api.stack-auth.com/..."
Loading
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
docs-mintlify/migration.mdx:37-39
The `@stackframe/emails``@hexclave/emails` row was present in the previous version of this table but has been dropped in the rewrite. Customers who use Hexclave's stored email templates import from `@stackframe/emails` (a virtual module injected at build time), so without this row they have no documentation guidance to update that import path and would have a silent breakage after migration.

```suggestion
| `@stackframe/stack-sc` | `@hexclave/sc` |
| `@stackframe/stack-cli` | `@hexclave/cli` |
| `@stackframe/dashboard-ui-components` | `@hexclave/dashboard-ui-components` |
| `@stackframe/emails` *(virtual module in stored email templates)* | `@hexclave/emails` |
```

### Issue 2 of 2
apps/backend/src/lib/request-api-url.ts:39-45
The comment states that `x-forwarded-host` "cannot be spoofed by a client" on Vercel. This is true for Vercel edge-terminated deployments, but the code is also used in self-hosted scenarios without an edge proxy. In those deployments a client-controlled `x-forwarded-host: api.stack-auth.com` would cause a token to be minted with an `iss` from the cloud allowlist rather than the deployment's `NEXT_PUBLIC_STACK_API_URL`. The minted token would then fail validation on that same server (since `getAllowedIssuers` is env-var–based), so the practical blast radius is zero — but the comment's "cannot be spoofed" claim could mislead future readers who add new trust checks here.

```suggestion
 * Trust model: on Vercel, `x-forwarded-host` is set by the edge from the
 * customer-facing hostname and cannot be spoofed by a client. In self-hosted
 * deployments without an edge proxy a client *can* set this header, but the
 * blast radius is bounded: a spoofed cloud host (e.g. api.stack-auth.com)
 * causes a token to be minted under that iss, which then fails validation on
 * the self-hosted backend because getAllowedIssuers uses the deployment's
 * NEXT_PUBLIC_STACK_API_URL (a different hostname) — the token is unusable.
 * A spoofed host that isn't in the allowlist falls back to the env-var default.
 * The helper does NOT gate on a trusted-proxy signal; it assumes the
 * deployment's proxy chain sets `x-forwarded-host` from a trusted source.
```

Reviews (1): Last reviewed commit: "feat(backend): derive JWT issuer and OAu..." | Re-trigger Greptile

Comment thread docs-mintlify/migration.mdx Outdated
Comment thread apps/backend/src/lib/request-api-url.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (13)
apps/backend/src/oauth/providers/bitbucket.tsx (1)

11-12: ⚡ Quick win

Use the standard URL helper for redirectUri.

Switch this callback URL construction from string concatenation to urlString\`` (or the project-standard URL utility).

As per coding guidelines: "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency".

Also applies to: 18-18, 20-20

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/bitbucket.tsx` around lines 11 - 12, The
redirectUri construction in the static async create method (function create)
currently builds the callback URL via string interpolation; replace that string
concatenation with the project-standard URL helper (use the urlString`...`
template or the project's URL utility) when forming redirectUri so parameters
are correctly encoded and consistent; update all occurrences in create where
redirectUri or callback URLs are built (including the instances noted around
lines 18 and 20) to use urlString`...` instead of normal template strings or
concatenation.
apps/backend/src/oauth/providers/gitlab.tsx (1)

11-12: ⚡ Quick win

Use the standard URL helper for redirectUri.

For consistency with repository conventions, build this callback URL using urlString\`` (or the shared URL utility), not direct string concatenation.

As per coding guidelines: "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency".

Also applies to: 19-19, 21-21

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/gitlab.tsx` around lines 11 - 12, In the
static async create method of the GitLab provider (create in
apps/backend/src/oauth/providers/gitlab.tsx) replace direct string interpolation
when building redirectUri and any other callback URLs with the repository's URL
helper (use urlString`...` or the shared URL utility) instead of normal
concatenation; locate where redirectUri is constructed (and related usages
around the same block) and refactor to use urlString template literals so the
callback URL is encoded/constructed consistently with project conventions.
apps/backend/src/oauth/providers/facebook.tsx (1)

16-16: ⚡ Quick win

Use the standard URL helper for redirectUri.

This should use urlString\`(or equivalent shared URL builder) instead of concatenatingapiUrl` with a string path.

As per coding guidelines: "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency".

Also applies to: 18-18, 23-23, 30-30

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/facebook.tsx` at line 16, The code is
building redirect and endpoint URLs by concatenating apiUrl with path strings;
replace those concatenations to use the shared URL builder (urlString``) so URLs
are constructed consistently and safely. Locate where the apiUrl parameter is
combined (the redirectUri and other endpoint strings referenced in this file,
e.g., where redirectUri is set and where API endpoints are formed) and change
them to use urlString template calls (and wrap query values with
encodeURIComponent if present) instead of normal string interpolation; keep the
same path segments and query keys but construct them via urlString`` for all
occurrences noted (including the lines flagged at 16, 18, 23, 30) so the file
uses the standard URL helper consistently.
apps/backend/src/oauth/providers/apple.tsx (1)

13-14: ⚡ Quick win

Use the standard URL helper for redirectUri.

Please avoid apiUrl + "/..." here and construct the callback URL with urlString\`` (or the project-standard URL utility) for consistency.

As per coding guidelines: "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency".

Also applies to: 20-20, 26-26

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/apple.tsx` around lines 13 - 14, The
redirectUri is being built via string concatenation inside the static async
create method; replace any occurrences of concatenating apiUrl + "/..." (in the
create method and the other two spots where redirect/callback URLs are
assembled) with the project-standard URL helper (e.g., use urlString`...` or the
shared URL utility) to construct the callback URL safely and consistently,
updating the redirectUri construction in the static async create function and
the two other concatenation sites to use that helper.
apps/backend/src/oauth/providers/github.tsx (1)

16-16: ⚡ Quick win

Use the standard URL helper for redirectUri.

Please construct this URL with urlString\`(or the project URL helper) instead ofapiUrl + "/..."`.

As per coding guidelines: "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency".

Also applies to: 18-18, 25-25, 38-38

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/github.tsx` at line 16, Replace all string
concatenations that build redirectUri using apiUrl + "/..." with the project's
URL helper or the urlString`` template tag: locate the redirectUri constructions
(references to apiUrl and redirectUri in this file, e.g., where apiUrl + "/..."
is used around the GitHub OAuth provider code) and change them to
urlString`{apiUrl}/path` (or the canonical project URL helper) so the URLs are
constructed via the helper/template instead of plain concatenation; update every
occurrence mentioned (uses at the redirectUri assignments and related places
around apiUrl at the top of the GitHub provider file).
apps/backend/src/oauth/providers/discord.tsx (1)

14-14: ⚡ Quick win

Use the standard URL helper for redirectUri.

Please replace apiUrl + "/..." with urlString\`` (or the shared URL helper used in this codebase) for callback URL construction.

As per coding guidelines: "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency".

Also applies to: 16-16, 21-21, 23-23

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/discord.tsx` at line 14, The code is
concatenating callback URLs using apiUrl + "/..." — update all places where
redirectUri (and any callback URL construction) is built from apiUrl (including
occurrences around the current declarations) to use the standardized URL helper
template (e.g., urlString`...`) or the shared URL helper used in this codebase
instead of string concatenation; locate the redirectUri construction(s) that
reference the apiUrl parameter (and the functions/methods that consume it) and
replace patterns like apiUrl + "/path" with urlString`{apiUrl}/path` (or the
equivalent project helper) for each occurrence noted (lines ~14, ~16, ~21, ~23).
apps/backend/src/oauth/providers/x.tsx (1)

12-21: ⚡ Quick win

Use structured URL construction for X callback URI.

Please avoid direct string concatenation for the redirect URI.

♻️ Proposed change
-        redirectUri: apiUrl + "/api/v1/auth/oauth/callback/x",
+        redirectUri: new URL("/api/v1/auth/oauth/callback/x", apiUrl).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/x.tsx` around lines 12 - 21, The redirectUri
in XProvider.create is being built via string concatenation; update the
construction in the call to OAuthBaseProvider.createConstructorArgs so the
callback URL is built using a proper URL API (e.g., new URL or a urlString
helper) or by encoding path segments with encodeURIComponent instead of apiUrl +
"/api/v1/auth/oauth/callback/x"; modify the redirectUri value to derive the full
callback URL by resolving the path against the apiUrl (preserving any trailing
slash handling) so XProvider.create and OAuthBaseProvider.createConstructorArgs
get a well-formed, encoded URL.
apps/backend/src/oauth/providers/mock.tsx (1)

12-16: ⚡ Quick win

Encode providerId when building redirectUri.

providerId is a dynamic path segment and should be URL-encoded before inclusion.

♻️ Proposed change
-      redirectUri: `${options.apiUrl}/api/v1/auth/oauth/callback/${providerId}`,
+      redirectUri: new URL(
+        `/api/v1/auth/oauth/callback/${encodeURIComponent(providerId)}`,
+        options.apiUrl
+      ).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/mock.tsx` around lines 12 - 16, The
redirectUri is built with an unconstrained providerId; update
MockProvider.create to URL-encode providerId before interpolation (when calling
OAuthBaseProvider.createConstructorArgs) — e.g., compute an encodedId using
encodeURIComponent(providerId) or a url-building helper and use that encodedId
in the redirectUri template string (`redirectUri:
\`${options.apiUrl}/api/v1/auth/oauth/callback/${encodedId}\``) so dynamic path
segments are safely encoded; change the reference in the create method of
MockProvider and ensure any helper (urlString) is used consistently if
available.
apps/backend/src/oauth/providers/linkedin.tsx (1)

13-27: ⚡ Quick win

Construct redirectUri with a URL builder, not string concat.

This keeps redirect URI generation consistent and avoids subtle path/base formatting issues.

♻️ Proposed change
-        redirectUri: apiUrl + "/api/v1/auth/oauth/callback/linkedin",
+        redirectUri: new URL("/api/v1/auth/oauth/callback/linkedin", apiUrl).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/linkedin.tsx` around lines 13 - 27, The
redirectUri is built via string concatenation in LinkedInProvider.create; update
it to use a URL builder helper (e.g., urlString or new URL) so paths and slashes
are handled consistently: construct the base URL from apiUrl and append the path
"/api/v1/auth/oauth/callback/linkedin" using the chosen URL helper, then pass
that built string into OAuthBaseProvider.createConstructorArgs (referencing
LinkedInProvider.create and OAuthBaseProvider.createConstructorArgs) instead of
apiUrl + "/api/v1/auth/oauth/callback/linkedin".
apps/backend/src/oauth/providers/google.tsx (1)

11-23: ⚡ Quick win

Use structured URL construction for redirectUri.

redirectUri is currently built via string concatenation. Please switch to structured URL construction to keep URL handling consistent and robust.

♻️ Proposed change
-      redirectUri: apiUrl + "/api/v1/auth/oauth/callback/google",
+      redirectUri: new URL("/api/v1/auth/oauth/callback/google", apiUrl).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/google.tsx` around lines 11 - 23, The
redirectUri is currently built via string concatenation inside
GoogleProvider.create when calling OAuthBaseProvider.createConstructorArgs;
change it to a structured URL build (e.g., use the project's urlString helper or
the URL constructor) to join apiUrl and the path
"/api/v1/auth/oauth/callback/google" and ensure proper encoding (use
encodeURIComponent for any dynamic segments if needed). Update the redirectUri
argument passed to OAuthBaseProvider.createConstructorArgs accordingly so it
reliably handles trailing slashes and encodings.
apps/backend/src/oauth/providers/spotify.tsx (1)

11-24: ⚡ Quick win

Avoid concatenated redirect URI strings.

Use structured URL construction for consistency and safer base/path handling.

♻️ Proposed change
-      redirectUri: apiUrl + "/api/v1/auth/oauth/callback/spotify",
+      redirectUri: new URL("/api/v1/auth/oauth/callback/spotify", apiUrl).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/spotify.tsx` around lines 11 - 24, The
redirectUri is being built by simple string concatenation in
SpotifyProvider.create when calling OAuthBaseProvider.createConstructorArgs;
replace the concatenation with structured URL construction (e.g., use the URL
constructor or your project's urlString helper) to safely join apiUrl and the
path and ensure proper encoding—update the redirectUri argument passed to
OAuthBaseProvider.createConstructorArgs and keep other fields unchanged.
apps/backend/src/oauth/providers/microsoft.tsx (1)

11-30: ⚡ Quick win

Use consistent URL construction for Microsoft callback URI.

Please avoid concatenating URL strings directly here.

♻️ Proposed change
-      redirectUri: apiUrl + "/api/v1/auth/oauth/callback/microsoft",
+      redirectUri: new URL("/api/v1/auth/oauth/callback/microsoft", apiUrl).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/microsoft.tsx` around lines 11 - 30, The
redirectUri is built via string concatenation (redirectUri: apiUrl +
"/api/v1/auth/oauth/callback/microsoft") inside MicrosoftProvider.create;
replace this with a proper URL construction using the project's URL helper
(e.g., urlString) or the URL constructor to join apiUrl and the callback path so
the callback URI is encoded/normalized correctly before passing into
OAuthBaseProvider.createConstructorArgs and the MicrosoftProvider.
apps/backend/src/oauth/providers/twitch.tsx (1)

11-25: ⚡ Quick win

Build Twitch callback URI via URL API.

This avoids manual string joining and keeps URI generation consistent.

♻️ Proposed change
-      redirectUri: apiUrl + "/api/v1/auth/oauth/callback/twitch",
+      redirectUri: new URL("/api/v1/auth/oauth/callback/twitch", apiUrl).toString(),

As per coding guidelines, "Use urlString`` or encodeURIComponent()` for URL construction instead of normal string interpolation, for consistency."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/src/oauth/providers/twitch.tsx` around lines 11 - 25, The
redirectUri is built via string concatenation inside TwitchProvider.create when
calling OAuthBaseProvider.createConstructorArgs; replace that manual join with
the URL API by constructing the callback path against the provided apiUrl (e.g.,
new URL('/api/v1/auth/oauth/callback/twitch', apiUrl).toString()) and supply
that result as the redirectUri to ensure correct encoding and consistent URI
formation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/backend/src/route-handlers/verification-code-handler.tsx`:
- Line 219: The post-handler is bypassing type-safety by passing requestBody as
any to options.handler (and similar casts in options.validate and
options.details); instead ensure requestBody is typed/validated as RequestBody
before the handoff—either refine the inferred type when parsing the incoming
body or run/return a transformation that yields RequestBody and pass that
validated/typed value (no any) into options.validate, options.handler and
options.details (references: requestBody, options.validate, options.handler,
options.details, validatedMethod, validatedData, auth.tenancy, auth.user,
getApiUrlForRequest, fullReq); update the parse/validate code so requestBody is
of type RequestBody or map it to that type prior to the calls.

---

Nitpick comments:
In `@apps/backend/src/oauth/providers/apple.tsx`:
- Around line 13-14: The redirectUri is being built via string concatenation
inside the static async create method; replace any occurrences of concatenating
apiUrl + "/..." (in the create method and the other two spots where
redirect/callback URLs are assembled) with the project-standard URL helper
(e.g., use urlString`...` or the shared URL utility) to construct the callback
URL safely and consistently, updating the redirectUri construction in the static
async create function and the two other concatenation sites to use that helper.

In `@apps/backend/src/oauth/providers/bitbucket.tsx`:
- Around line 11-12: The redirectUri construction in the static async create
method (function create) currently builds the callback URL via string
interpolation; replace that string concatenation with the project-standard URL
helper (use the urlString`...` template or the project's URL utility) when
forming redirectUri so parameters are correctly encoded and consistent; update
all occurrences in create where redirectUri or callback URLs are built
(including the instances noted around lines 18 and 20) to use urlString`...`
instead of normal template strings or concatenation.

In `@apps/backend/src/oauth/providers/discord.tsx`:
- Line 14: The code is concatenating callback URLs using apiUrl + "/..." —
update all places where redirectUri (and any callback URL construction) is built
from apiUrl (including occurrences around the current declarations) to use the
standardized URL helper template (e.g., urlString`...`) or the shared URL helper
used in this codebase instead of string concatenation; locate the redirectUri
construction(s) that reference the apiUrl parameter (and the functions/methods
that consume it) and replace patterns like apiUrl + "/path" with
urlString`{apiUrl}/path` (or the equivalent project helper) for each occurrence
noted (lines ~14, ~16, ~21, ~23).

In `@apps/backend/src/oauth/providers/facebook.tsx`:
- Line 16: The code is building redirect and endpoint URLs by concatenating
apiUrl with path strings; replace those concatenations to use the shared URL
builder (urlString``) so URLs are constructed consistently and safely. Locate
where the apiUrl parameter is combined (the redirectUri and other endpoint
strings referenced in this file, e.g., where redirectUri is set and where API
endpoints are formed) and change them to use urlString template calls (and wrap
query values with encodeURIComponent if present) instead of normal string
interpolation; keep the same path segments and query keys but construct them via
urlString`` for all occurrences noted (including the lines flagged at 16, 18,
23, 30) so the file uses the standard URL helper consistently.

In `@apps/backend/src/oauth/providers/github.tsx`:
- Line 16: Replace all string concatenations that build redirectUri using apiUrl
+ "/..." with the project's URL helper or the urlString`` template tag: locate
the redirectUri constructions (references to apiUrl and redirectUri in this
file, e.g., where apiUrl + "/..." is used around the GitHub OAuth provider code)
and change them to urlString`{apiUrl}/path` (or the canonical project URL
helper) so the URLs are constructed via the helper/template instead of plain
concatenation; update every occurrence mentioned (uses at the redirectUri
assignments and related places around apiUrl at the top of the GitHub provider
file).

In `@apps/backend/src/oauth/providers/gitlab.tsx`:
- Around line 11-12: In the static async create method of the GitLab provider
(create in apps/backend/src/oauth/providers/gitlab.tsx) replace direct string
interpolation when building redirectUri and any other callback URLs with the
repository's URL helper (use urlString`...` or the shared URL utility) instead
of normal concatenation; locate where redirectUri is constructed (and related
usages around the same block) and refactor to use urlString template literals so
the callback URL is encoded/constructed consistently with project conventions.

In `@apps/backend/src/oauth/providers/google.tsx`:
- Around line 11-23: The redirectUri is currently built via string concatenation
inside GoogleProvider.create when calling
OAuthBaseProvider.createConstructorArgs; change it to a structured URL build
(e.g., use the project's urlString helper or the URL constructor) to join apiUrl
and the path "/api/v1/auth/oauth/callback/google" and ensure proper encoding
(use encodeURIComponent for any dynamic segments if needed). Update the
redirectUri argument passed to OAuthBaseProvider.createConstructorArgs
accordingly so it reliably handles trailing slashes and encodings.

In `@apps/backend/src/oauth/providers/linkedin.tsx`:
- Around line 13-27: The redirectUri is built via string concatenation in
LinkedInProvider.create; update it to use a URL builder helper (e.g., urlString
or new URL) so paths and slashes are handled consistently: construct the base
URL from apiUrl and append the path "/api/v1/auth/oauth/callback/linkedin" using
the chosen URL helper, then pass that built string into
OAuthBaseProvider.createConstructorArgs (referencing LinkedInProvider.create and
OAuthBaseProvider.createConstructorArgs) instead of apiUrl +
"/api/v1/auth/oauth/callback/linkedin".

In `@apps/backend/src/oauth/providers/microsoft.tsx`:
- Around line 11-30: The redirectUri is built via string concatenation
(redirectUri: apiUrl + "/api/v1/auth/oauth/callback/microsoft") inside
MicrosoftProvider.create; replace this with a proper URL construction using the
project's URL helper (e.g., urlString) or the URL constructor to join apiUrl and
the callback path so the callback URI is encoded/normalized correctly before
passing into OAuthBaseProvider.createConstructorArgs and the MicrosoftProvider.

In `@apps/backend/src/oauth/providers/mock.tsx`:
- Around line 12-16: The redirectUri is built with an unconstrained providerId;
update MockProvider.create to URL-encode providerId before interpolation (when
calling OAuthBaseProvider.createConstructorArgs) — e.g., compute an encodedId
using encodeURIComponent(providerId) or a url-building helper and use that
encodedId in the redirectUri template string (`redirectUri:
\`${options.apiUrl}/api/v1/auth/oauth/callback/${encodedId}\``) so dynamic path
segments are safely encoded; change the reference in the create method of
MockProvider and ensure any helper (urlString) is used consistently if
available.

In `@apps/backend/src/oauth/providers/spotify.tsx`:
- Around line 11-24: The redirectUri is being built by simple string
concatenation in SpotifyProvider.create when calling
OAuthBaseProvider.createConstructorArgs; replace the concatenation with
structured URL construction (e.g., use the URL constructor or your project's
urlString helper) to safely join apiUrl and the path and ensure proper
encoding—update the redirectUri argument passed to
OAuthBaseProvider.createConstructorArgs and keep other fields unchanged.

In `@apps/backend/src/oauth/providers/twitch.tsx`:
- Around line 11-25: The redirectUri is built via string concatenation inside
TwitchProvider.create when calling OAuthBaseProvider.createConstructorArgs;
replace that manual join with the URL API by constructing the callback path
against the provided apiUrl (e.g., new URL('/api/v1/auth/oauth/callback/twitch',
apiUrl).toString()) and supply that result as the redirectUri to ensure correct
encoding and consistent URI formation.

In `@apps/backend/src/oauth/providers/x.tsx`:
- Around line 12-21: The redirectUri in XProvider.create is being built via
string concatenation; update the construction in the call to
OAuthBaseProvider.createConstructorArgs so the callback URL is built using a
proper URL API (e.g., new URL or a urlString helper) or by encoding path
segments with encodeURIComponent instead of apiUrl +
"/api/v1/auth/oauth/callback/x"; modify the redirectUri value to derive the full
callback URL by resolving the path against the apiUrl (preserving any trailing
slash handling) so XProvider.create and OAuthBaseProvider.createConstructorArgs
get a well-formed, encoded URL.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3bc95fa7-d2c0-4a1a-8066-0dd37626cf44

📥 Commits

Reviewing files that changed from the base of the PR and between c753ab2 and 61c1a0e.

📒 Files selected for processing (38)
  • apps/backend/src/app/api/latest/auth/anonymous/sign-up/route.ts
  • apps/backend/src/app/api/latest/auth/cli/complete/route.tsx
  • apps/backend/src/app/api/latest/auth/mfa/sign-in/verification-code-handler.tsx
  • apps/backend/src/app/api/latest/auth/oauth/authorize/[provider_id]/route.tsx
  • apps/backend/src/app/api/latest/auth/oauth/callback/[provider_id]/route.tsx
  • apps/backend/src/app/api/latest/auth/oauth/callback/apple/native/route.tsx
  • apps/backend/src/app/api/latest/auth/oauth/cross-domain/authorize/route.tsx
  • apps/backend/src/app/api/latest/auth/oauth/token/route.tsx
  • apps/backend/src/app/api/latest/auth/otp/sign-in/verification-code-handler.tsx
  • apps/backend/src/app/api/latest/auth/passkey/sign-in/verification-code-handler.tsx
  • apps/backend/src/app/api/latest/auth/password/sign-in/route.tsx
  • apps/backend/src/app/api/latest/auth/password/sign-up/route.tsx
  • apps/backend/src/app/api/latest/auth/sessions/current/refresh/route.tsx
  • apps/backend/src/app/api/latest/auth/sessions/route.tsx
  • apps/backend/src/app/api/latest/connected-accounts/[user_id]/[provider_id]/[provider_account_id]/access-token/crud.tsx
  • apps/backend/src/app/api/latest/connected-accounts/[user_id]/[provider_id]/access-token/crud.tsx
  • apps/backend/src/lib/request-api-url.ts
  • apps/backend/src/lib/tokens.tsx
  • apps/backend/src/oauth/index.tsx
  • apps/backend/src/oauth/model.tsx
  • apps/backend/src/oauth/providers/apple.tsx
  • apps/backend/src/oauth/providers/bitbucket.tsx
  • apps/backend/src/oauth/providers/discord.tsx
  • apps/backend/src/oauth/providers/facebook.tsx
  • apps/backend/src/oauth/providers/github.tsx
  • apps/backend/src/oauth/providers/gitlab.tsx
  • apps/backend/src/oauth/providers/google.tsx
  • apps/backend/src/oauth/providers/linkedin.tsx
  • apps/backend/src/oauth/providers/microsoft.tsx
  • apps/backend/src/oauth/providers/mock.tsx
  • apps/backend/src/oauth/providers/spotify.tsx
  • apps/backend/src/oauth/providers/twitch.tsx
  • apps/backend/src/oauth/providers/x.tsx
  • apps/backend/src/route-handlers/verification-code-handler.tsx
  • apps/backend/src/stack.tsx
  • docs-mintlify/migration.mdx
  • packages/stack-shared/src/utils/urls.tsx
  • packages/template/src/lib/stack-app/apps/implementations/common.ts

Comment thread apps/backend/src/route-handlers/verification-code-handler.tsx
- Remove the prominent top-of-page warning; the same information now
  lives in the relevant sections, where it applies to the smaller subset
  of customers doing manual JWT verification or running custom OAuth apps.
- Section 2 (manual JWT verification): show only the new
  api.hexclave.com issuer in the After example. Customers migrating to
  @hexclave/* are explicitly opting into the new host, so there's no
  reason to teach the array-of-issuers compat pattern.
- Section 3 (OAuth callback URLs): same simplification — instruct
  customers to set the new api.hexclave.com URL and stop there. Drop
  the byte-by-byte explanation and the GitHub-OAuth-Apps single-URL
  warning. Add a brief Note that most providers allow registering both
  the old and new URLs temporarily to avoid signup downtime during the
  SDK swap.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 38 files

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

Fix all with cubic | Re-trigger cubic

Comment thread docs-mintlify/migration.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs-mintlify/migration.mdx (1)

46-60: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Consider guidance for gradual migration with mixed SDK versions.

The backend's getAllowedIssuers uses an alias map to accept both api.stack-auth.com and api.hexclave.com issuers (per PR summary), but the migration doc instructs users to update manual JWT verification to only check the new hexclave issuer. During a gradual rollout where some clients use @stackframe/* (issuing tokens with stack-auth.com issuer) and others use @hexclave/* (issuing tokens with hexclave.com issuer), manual verification that only checks the hexclave issuer will reject tokens from old SDK clients.

The commit message indicates the array-of-issuers compatibility example was intentionally removed to simplify the doc. However, for users with multi-client deployments (web + mobile, multiple services, etc.) performing gradual rollouts, the simplified guidance may cause production authentication failures.

🔄 Suggested addition for transition period

Add a note after line 60:

<Note>
  During a gradual migration where some clients still use `@stackframe/*`, your manual JWT verification should accept **both** issuers:
  
  ```ts
  const { payload } = await jose.jwtVerify(token, jwks, {
    issuer: [
      'https://api.stack-auth.com/api/v1/projects/YOUR_PROJECT_ID',
      'https://api.hexclave.com/api/v1/projects/YOUR_PROJECT_ID',
    ],
    audience: 'YOUR_PROJECT_ID',
  });

Once all clients are migrated, you can remove the stack-auth.com issuer.

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs-mintlify/migration.mdx around lines 46 - 60, Add guidance for gradual
migration to the migration.mdx around the jose.jwtVerify example: explain that
during rollouts you should accept both issuers (referencing the backend helper
getAllowedIssuers and the jose.jwtVerify call) by showing that issuer can be an
array containing both 'https://api.stack-auth.com/.../projects/YOUR_PROJECT_ID'
and 'https://api.hexclave.com/.../projects/YOUR_PROJECT_ID', and note to remove
the old stack-auth.com issuer once all clients use @hexclave/*; keep the
existing single-issuer example but add this transitional note immediately after
it.


</details>

</blockquote></details>

</blockquote></details>
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-mintlify/migration.mdx`:
- Line 62: Add concrete example issuer strings for the anonymous and restricted
issuer variants in the migration docs: insert two example lines showing the
exact issuer values to use when verifying JWTs, e.g. "issuer:
'https://api.hexclave.com/api/v1/projects-anonymous-users/YOUR_PROJECT_ID'" for
anonymous and "issuer:
'https://api.hexclave.com/api/v1/projects-restricted-users/YOUR_PROJECT_ID'" for
restricted so readers can copy the exact formats.

---

Outside diff comments:
In `@docs-mintlify/migration.mdx`:
- Around line 46-60: Add guidance for gradual migration to the migration.mdx
around the jose.jwtVerify example: explain that during rollouts you should
accept both issuers (referencing the backend helper getAllowedIssuers and the
jose.jwtVerify call) by showing that issuer can be an array containing both
'https://api.stack-auth.com/.../projects/YOUR_PROJECT_ID' and
'https://api.hexclave.com/.../projects/YOUR_PROJECT_ID', and note to remove the
old stack-auth.com issuer once all clients use `@hexclave/`*; keep the existing
single-issuer example but add this transitional note immediately after it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 670baccb-8027-49fe-ab35-54add96fab7f

📥 Commits

Reviewing files that changed from the base of the PR and between 61c1a0e and bbe1486.

📒 Files selected for processing (1)
  • docs-mintlify/migration.mdx

Comment thread docs-mintlify/migration.mdx
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

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

Fix all with cubic | Re-trigger cubic

Comment thread docs-mintlify/migration.mdx Outdated
@BilalG1 BilalG1 requested a review from N2D4 May 27, 2026 20:14
@BilalG1 BilalG1 assigned N2D4 and unassigned BilalG1 May 27, 2026
@github-actions github-actions Bot assigned BilalG1 and unassigned N2D4 May 28, 2026
@BilalG1 BilalG1 merged commit 6b07c43 into dev May 28, 2026
35 of 38 checks passed
@BilalG1 BilalG1 deleted the feat/host-aware-api-url branch May 28, 2026 00:06
BilalG1 added a commit that referenced this pull request May 28, 2026
Resolves conflicts from #1498 (request-host-derived JWT iss / OAuth
redirect_uri) by taking dev's structural changes wholesale, then
rewriting @stackframe/stack-shared -> @hexclave/shared on the merged-in
files to match this branch's PR-3 rename convention. tokens.tsx adopts
dev's CLOUD_HOST_PAIRS-derived issuerHostAliases (adds the staging host
pair the hand-rolled map was missing).

pnpm typecheck: 28/28 pass
pnpm lint: 28/28 pass
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.

2 participants