Skip to content

Fix CoinPay OAuth origin fallback#237

Merged
ralyodio merged 2 commits into
profullstack:masterfrom
meteop-x:codex/coinpay-oauth-origin-fallback
May 23, 2026
Merged

Fix CoinPay OAuth origin fallback#237
ralyodio merged 2 commits into
profullstack:masterfrom
meteop-x:codex/coinpay-oauth-origin-fallback

Conversation

@meteop-x
Copy link
Copy Markdown
Contributor

@meteop-x meteop-x commented May 23, 2026

Summary

  • Build CoinPay OAuth app URLs from NEXT_PUBLIC_APP_URL when configured, otherwise from the current request origin.
  • Strip trailing slashes from the configured app URL before composing callback/login links.
  • Add route coverage for the OAuth initiation redirect and callback error redirects.

Fixes #236.

uGig gig: https://ugig.net/gigs/abd6b2a0-e728-48cf-a46f-f99e419ed94e

Note: this replaces my closed duplicate PR #235; #235 overlapped with existing PR #128, so I closed it and moved to this non-overlapping bug/fix.

Validation

  • node_modules\.bin\vitest.cmd run src/app/api/auth/coinpay/route.test.ts src/app/api/callback/oauth/route.test.ts
  • node_modules\.bin\tsc.cmd --noEmit
  • node_modules\.bin\prettier.cmd --check src/app/api/auth/coinpay/route.ts src/app/api/auth/coinpay/route.test.ts src/app/api/callback/oauth/route.ts src/app/api/callback/oauth/route.test.ts
  • git diff --check -- src/app/api/auth/coinpay/route.ts src/app/api/auth/coinpay/route.test.ts src/app/api/callback/oauth/route.ts src/app/api/callback/oauth/route.test.ts

Note: corepack pnpm install --frozen-lockfile populated dependencies, but the repo postinstall script fails on this Windows shell because it invokes bare pnpm and Unix true; direct local binaries were used for validation after install.

@ralyodio ralyodio closed this May 23, 2026
@ralyodio ralyodio reopened this May 23, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR extracts a shared getAppUrl utility with a trustedOnly mode that prevents open-redirect attacks by rejecting untrusted request Host values, and uses VERCEL_URL as a server-controlled fallback for preview deployments. Both CoinPay OAuth routes are updated to use this helper, and new tests verify the trusted-origin and error-redirect behavior.

  • src/lib/app-url.ts: New trustedOnly option blocks non-local request origins when neither NEXT_PUBLIC_APP_URL nor VERCEL_URL is configured, falling back to a hardcoded https://ugig.net safe default. Also adds APP_URL as an undocumented secondary env-var check.
  • src/app/api/auth/coinpay/route.ts + src/app/api/callback/oauth/route.ts: Both now call getAppUrl(request, { trustedOnly: true }) instead of the old process.env.NEXT_PUBLIC_APP_URL || "http://localhost:8080" pattern.
  • Tests: New test files cover the OAuth initiation redirect and callback error-redirect paths with VERCEL_URL, trailing-slash normalization, and trusted-origin enforcement scenarios.

Confidence Score: 5/5

Safe to merge; the open-redirect vector from the previous review is correctly closed by the trustedOnly mode and VERCEL_URL fallback.

The core logic change — replacing the bare request.nextUrl.origin fallback with a mode that rejects non-local, non-env-configured origins — correctly addresses the open-redirect concern. The redirect_uri computed at initiation and at token exchange will be consistent across all documented environment configurations. The one notable undocumented addition (APP_URL) is unlikely to cause problems in practice but deserves attention before the pattern spreads to other callers.

src/lib/app-url.ts — the undocumented APP_URL env-var fallback and the absence of a test for that path.

Important Files Changed

Filename Overview
src/lib/app-url.ts Refactored to support a trustedOnly mode and VERCEL_URL fallback; silently adds APP_URL as an undocumented secondary env-var with no test coverage.
src/app/api/auth/coinpay/route.ts Clean swap to getAppUrl(request, { trustedOnly: true }); formatting-only restructuring otherwise.
src/app/api/callback/oauth/route.ts Same getAppUrl migration as the initiation route; remainder is whitespace/formatting cleanup with no logic changes.
src/lib/app-url.test.ts Adds trustedOnly mode tests and fixes teardown; APP_URL env var introduced in the implementation has no corresponding test.
src/app/api/auth/coinpay/route.test.ts New tests covering VERCEL_URL fallback, localhost fallback, and trailing-slash normalization for the initiation redirect.
src/app/api/callback/oauth/route.test.ts New tests covering error-redirect paths with VERCEL_URL, trusted-origin enforcement, and trailing-slash normalization.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["GET /api/auth/coinpay"] --> B["getAppUrl with trustedOnly"]
    B --> C{Configured env var?}
    C -- Yes --> D["Use configured URL"]
    C -- No --> E{VERCEL_URL present?}
    E -- Yes --> F["Use Vercel deployment URL"]
    E -- No --> G{Request from localhost?}
    G -- Yes --> H["Use request origin"]
    G -- No --> I["Use default ugig.net"]
    D & F & H & I --> J["Build redirectUri\nappUrl + /api/callback/oauth"]
    J --> K["Redirect to CoinPay OAuth\nStore state cookie"]
    K --> L["CoinPay redirects back"]
    L --> M["GET /api/callback/oauth"]
    M --> N["getAppUrl with trustedOnly\nsame resolution"]
    N --> O["Token exchange with\nmatching redirectUri"]
    O --> P{Success?}
    P -- No --> Q["Redirect to login with error"]
    P -- Yes --> R["Find or create user\nLink OAuth identity"]
    R --> S["Generate magic link\nRedirect to auth confirm"]
Loading

Reviews (4): Last reviewed commit: "Harden CoinPay OAuth app URL fallback" | Re-trigger Greptile

Comment thread src/app/api/auth/coinpay/route.ts Outdated
Comment thread src/app/api/callback/oauth/route.ts Outdated
Comment thread src/app/api/callback/oauth/route.test.ts
@ralyodio ralyodio closed this May 23, 2026
@ralyodio ralyodio reopened this May 23, 2026
@meteop-x
Copy link
Copy Markdown
Contributor Author

Addressed the Host-header redirect concern from the Greptile review in b5974d2.

What changed:

  • Added a shared getAppUrl() helper for CoinPay OAuth routes.
  • Prefer configured NEXT_PUBLIC_APP_URL / APP_URL, then trusted platform VERCEL_URL for preview deployments.
  • Only use the request origin for localhost development; otherwise fall back to https://ugig.net, so callback error redirects no longer point at an arbitrary request host when app URL config is absent.

Validation:

  • vitest run src/app/api/auth/coinpay/route.test.ts src/app/api/callback/oauth/route.test.ts
  • tsc --noEmit
  • prettier --check ...
  • git diff --check

@meteop-x meteop-x force-pushed the codex/coinpay-oauth-origin-fallback branch from b5974d2 to 919fb52 Compare May 23, 2026 12:19
@ralyodio ralyodio merged commit 07a2629 into profullstack:master May 23, 2026
4 checks passed
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.

bug: CoinPay OAuth falls back to localhost redirects

2 participants