Skip to content

feat: loginview should honor nextauth callbackurl from the query string (middleware-friendly) (#955)#959

Merged
NoopDog merged 2 commits into
mainfrom
fran/955-loginview-callbackurl-query-string
Jun 10, 2026
Merged

feat: loginview should honor nextauth callbackurl from the query string (middleware-friendly) (#955)#959
NoopDog merged 2 commits into
mainfrom
fran/955-loginview-callbackurl-query-string

Conversation

@frano-m

@frano-m frano-m commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds getQueryCallbackUrl helper that extracts a same-origin path from router.query.callbackUrl, rejecting absolute URLs, protocol-relative (//evil.com/x), and non-/-prefixed values.
  • useNextAuthService.onLogin and useSessionActive's post-settle Router.push now prefer the query callbackUrl over the existing route-history fallback, with the same-origin guard in place. Aligns the library with the standard NextAuth + middleware contract.
  • useSessionActive's effect intentionally captures queryCallbackUrl once at first settle (excluded from deps with an explanatory comment) so a later URL change doesn't re-trigger a redirect.

Closes #955

Back-compat

  • Consumers without middleware (no ?callbackUrl=) see identical behavior to before — the query is empty so the route-history fallback runs.
  • Empty/array/unsafe values fall back to route history instead of being honored.
  • Existing inactivity-timeout flow (driven by ?inactivityTimeout=true) is unaffected.

Security note

The new helper deliberately blocks absolute and protocol-relative URLs so that Router.push (which does NOT enforce same-origin) cannot be used as an open redirector via a crafted /login?callbackUrl=https://evil.example link. NextAuth's signIn has its own same-origin guard, but consumers that override the redirect callback would lose it — this helper protects both call sites.

Test plan

  • tests/getQueryCallbackUrl.test.ts — 10 cases (string, string[], undefined, empty, absolute URL, protocol-relative, javascript:, query/fragment preservation).
  • tests/useNextAuthService.test.ts — new file covering the sign-in path's query-preference + open-redirect rejection.
  • tests/useSessionActive.test.ts — extended with the query-preference branch + open-redirect rejection.
  • npm run lint clean.
  • npm run check-format clean.
  • npx tsc clean.
  • npm test — 469/469 pass.
  • Verified end-to-end in hca-atlas-tracker via tarball install: middleware-driven sign-in now lands the user directly on the originally-requested page (no extra hop through /).

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 10, 2026 07:31
…ng (middleware-friendly) (#955)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@frano-m frano-m force-pushed the fran/955-loginview-callbackurl-query-string branch from 525eca5 to fc089d8 Compare June 10, 2026 07:32
@frano-m frano-m marked this pull request as ready for review June 10, 2026 07:32

Copilot AI 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.

Pull request overview

Updates the authentication redirect flow to honor NextAuth middleware’s ?callbackUrl= query parameter (with same-origin guarding) so users return directly to the originally requested route after login/session settle.

Changes:

  • Added getQueryCallbackUrl helper to safely extract a same-origin callback path from router.query.callbackUrl.
  • Updated useNextAuthService and useSessionActive to prefer the query callbackUrl over route-history fallback.
  • Added/expanded Jest coverage for helper behavior and both redirect call sites (including open-redirect rejection cases).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/hooks/authentication/session/useSessionActive.ts Prefer query callbackUrl for post-settle redirect; adds guarded getQueryCallbackUrl helper.
src/nextauth/hooks/useNextAuthService.ts Prefer guarded query callbackUrl when calling service.login.
tests/getQueryCallbackUrl.test.ts Adds unit tests for getQueryCallbackUrl across safe/unsafe inputs.
tests/useNextAuthService.test.ts Adds hook tests to verify query preference and open-redirect guard for login.
tests/useSessionActive.test.ts Extends redirect tests to cover query preference and guard behavior.

Comment thread tests/useSessionActive.test.ts
Comment thread tests/useNextAuthService.test.ts
)

Addresses copilot review feedback on PR #959: Router.push and other
module-level jest.fn() mocks weren't being cleared between tests, which
made assertions order-dependent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 10, 2026 07:42

Copilot AI 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.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@NoopDog NoopDog merged commit 197edd8 into main Jun 10, 2026
3 checks passed
@frano-m frano-m deleted the fran/955-loginview-callbackurl-query-string branch June 10, 2026 09:05
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.

feat: LoginView should honor NextAuth callbackUrl from the query string (middleware-friendly)

3 participants