fix(auth): improve auth error handling and fix Link CORS issue#120
Merged
fix(auth): improve auth error handling and fix Link CORS issue#120
Conversation
Why: The auth module had three issues: 1. <Link> to auth API routes caused unnecessary RSC fetch + CORS errors 2. getSession() coupled auth and DB access, making error types indistinguishable 3. authActionClient used a separate auth path (getCurrentUser) from getSession() What: - Split getSession() into getAuthSession(), tryGetAuthSession(), getSessionWithUser() - Add React cache() for per-request memoization - Replace <Link> with <a> for auth routes that redirect to Cognito - Unify authActionClient to use getAuthSession() - Convert Header.tsx from Client to Server Component
Contributor
Author
Local VerificationVerified on
|
badmintoncryer
suggested changes
Mar 20, 2026
Contributor
There was a problem hiding this comment.
作成ありがとうございます!!
<a>と<Link>の違いは大変勉強になりました。似たケースではaws-amplifyのAuth.federatedSignIn()関数などに頼っており、こちらも内部的には<a>の挙動となっているようでした。
コメントに加えて、1点確認です。
既存実装を見ると、webapp/src/app/api/cognito-token/route.tsでもtryGeetAuthSession()が活用できそうです!
現状
const session = await runWithAmplifyServerContext({
nextServerContext: { cookies },
operation: (contextSpec) => fetchAuthSession(contextSpec),
});
if (session.tokens?.accessToken == null) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}提案
const session = await tryGetAuthSession();
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}こちらも合わせて修正してよいと思いました。もちろん別 PR でも OK です。
tmokmss
approved these changes
Mar 21, 2026
…h helpers Replace direct runWithAmplifyServerContext/fetchAuthSession calls in cognito-token route with tryGetAuthSession(), and replace manual getAuthSession + prisma.user.findUnique in authActionClient with getSessionWithUser(). This eliminates duplicate auth code paths that were missed in the initial refactor, ensuring all authentication flows go through the centralized auth.ts helpers. The change also benefits from cache() memoization in getSessionWithUser() to avoid redundant DB lookups within the same request.
583aab3 to
62dc1c0
Compare
konokenj
pushed a commit
that referenced
this pull request
Mar 22, 2026
🤖 I have created a release *beep* *boop* --- ## [2.1.0](v2.0.0...v2.1.0) (2026-03-22) ### Features * add /update-snapshot comment trigger to update_snapshot workflow ([764a4fa](764a4fa)) * add CloudWatch LogGroup with retention policy to Lambda functions ([#117](#117)) ([53877bb](53877bb)), closes [#103](#103) * **database:** enable Data API and connection logging ([#123](#123)) ([e32dc7a](e32dc7a)) * increase webapp Lambda memory from 512MB to 1024MB ([#116](#116)) ([03c5a00](03c5a00)), closes [#101](#101) ### Bug Fixes * add lambda:InvokeFunction permission for CloudFront OAC ([#83](#83)) ([3cc66bf](3cc66bf)) * **auth:** improve auth error handling and fix Link CORS issue ([#120](#120)) ([84be605](84be605)) * disable Cognito self sign-up by default ([#115](#115)) ([9396e6f](9396e6f)), closes [#106](#106) * prevent CloudFront cache poisoning for Next.js RSC responses ([#119](#119)) ([70cddda](70cddda)) * **prisma:** add retry for Aurora Serverless v2 connection errors ([#121](#121)) ([7c05dfb](7c05dfb)) * support Amazon Linux 2023 for NAT instance ([#81](#81)) ([0c41aa8](0c41aa8)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
close #107
Problem
The authentication module had three issues:
CORS errors from
<Link>on auth routes:Header.tsxandsign-in/page.tsxused<Link prefetch={false}>for auth API routes (/api/auth/sign-out,/api/auth/sign-in). Even withprefetch={false}, clicking triggers a client-side RSC fetch. Since auth routes return a 302 redirect to the Cognito domain, the fetch follows the redirect cross-origin, causing a CORS error. Next.js falls back to MPA navigation via the catch block (source), so the navigation still works, but an unnecessary fetch + console error occurs on every click.getSession()coupled auth and DB access: Authentication (AmplifyfetchAuthSession) and database access (Prismauser.findUnique) were in a single function. When tokens expired, the thrown error was indistinguishable from a DB error, making it impossible to return 401 vs 500 in API routes. Additionally,cache()was not used, so multiple calls within the same request would hit Cognito + DB each time.Duplicate auth paths in
authActionClient:safe-action.tsusedgetCurrentUser()from Amplify whileauth.tsusedfetchAuthSession(), creating two separate authentication code paths.Solution
Replace
<Link>with<a>for auth routes: Auth API routes that redirect to Cognito should use plain<a>tags for full-page navigation, avoiding the RSC fetch entirely. This also allowedHeader.tsxto become a Server Component by removing"use client"anduseRouter.Split
getSession()into three functions withcache():getAuthSession(): Auth only, no DB access. Memoized with Reactcache().tryGetAuthSession(): Returnsnullon failure instead of throwing. For API routes that need to distinguish 401 from 500.getSessionWithUser(): Auth + DB user lookup. Memoized with Reactcache().Unify
authActionClientto usegetAuthSession(): ReplacedgetCurrentUser()withgetAuthSession()to consolidate the auth path.Changes
webapp/src/lib/auth.ts: SplitgetSession()intogetAuthSession(),tryGetAuthSession(),getSessionWithUser()withcache()webapp/src/lib/safe-action.ts: ReplacegetCurrentUser()withgetAuthSession()webapp/src/components/Header.tsx:<Link>→<a>for sign-out, remove"use client"/useRouterwebapp/src/app/sign-in/page.tsx:<Link>→<a>for sign-in, removeLinkimportwebapp/src/app/(root)/page.tsx:getSession()→getAuthSession()webapp/src/app/auth-callback/page.tsx: Simplify user creation flow withgetAuthSession()+ direct Prisma callVerification
tsc --noEmit: passeseslint: passes (with intentionalno-html-link-for-pagesdisable for auth routes)prettier --check: passes/api/auth/*) use<a>tags, preventing RSC fetch and CORS errorsauth-callbackcorrectly creates users on first logincache()prevents duplicate Cognito/DB calls within a single request