Skip to content

Commit

Permalink
[fix] Fix apple callbacks not redirecting for expo logins
Browse files Browse the repository at this point in the history
  • Loading branch information
garshythoel committed Nov 28, 2024
1 parent ceb7e3c commit 4d103ee
Showing 1 changed file with 39 additions and 21 deletions.
60 changes: 39 additions & 21 deletions apps/nextjs/src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,46 @@ function rewriteRequestUrlInDevelopment(req: NextRequest) {
return new NextRequest(newURL, req);
}

export const POST = async (_req: NextRequest) => {
async function handleExpoSigninCallback(req: NextRequest, redirectURL: string) {
cookies().delete(EXPO_COOKIE_NAME);

// Run original handler, then extract the session token from the response
// Send it back via a query param in the Expo deep link. The Expo app
// will then get that and set it in the session storage.
const authResponse = await handlers.POST(req);
const setCookie = authResponse.headers
.getSetCookie()
.find((cookie) => AUTH_COOKIE_PATTERN.test(cookie));
const match = setCookie?.match(AUTH_COOKIE_PATTERN)?.[1];

if (!match)
throw new Error(
"Unable to find session cookie: " +
JSON.stringify(authResponse.headers.getSetCookie()),
);

const url = new URL(redirectURL);
url.searchParams.set("session_token", match);

return NextResponse.redirect(url);
}

export const POST = async (
_req: NextRequest,
props: { params: { nextauth: string[] } },
) => {
// First step must be to correct the request URL.
const req = rewriteRequestUrlInDevelopment(_req);

const nextauthAction = props.params.nextauth[0];
const isExpoCallback = cookies().get(EXPO_COOKIE_NAME);

// callback handler required separately in the POST handler
// since Apple sends a POST request instead of a GET
if (nextauthAction === "callback" && !!isExpoCallback) {
return handleExpoSigninCallback(req, isExpoCallback.value);
}

return handlers.POST(req);
};

Expand All @@ -54,26 +91,7 @@ export const GET = async (
}

if (nextauthAction === "callback" && !!isExpoCallback) {
cookies().delete(EXPO_COOKIE_NAME);

// Run original handler, then extract the session token from the response
// Send it back via a query param in the Expo deep link. The Expo app
// will then get that and set it in the session storage.
const authResponse = await handlers.GET(req);
const setCookie = authResponse.headers
.getSetCookie()
.find((cookie) => AUTH_COOKIE_PATTERN.test(cookie));
const match = setCookie?.match(AUTH_COOKIE_PATTERN)?.[1];

if (!match)
throw new Error(
"Unable to find session cookie: " +
JSON.stringify(authResponse.headers.getSetCookie()),
);

const url = new URL(isExpoCallback.value);
url.searchParams.set("session_token", match);
return NextResponse.redirect(url);
return handleExpoSigninCallback(req, isExpoCallback.value);
}

// Every other request just calls the default handler
Expand Down

0 comments on commit 4d103ee

Please sign in to comment.