I’m writing a toy example for basic cookie/magic link authentication.
The flow goes something like this:
- If the the auth token cookie is missing from the request when sending requests to a protected path, then inside the
getServerSideProps
for those paths, it redirects them tohttps://myapp.com/auth/login
, where they can request a magic link - Click on the magic link
https://myapp.com/auth/login?token=AUTH_TOKEN_VALUE
- Inside
getServerSideProps
for the login page, I extractAUTH_TOKEN_VALUE
from query params and send it to an API server to check if it is valid - If it is, then set it as an HttpOnly cookie in the response and redirect to the home page
https://myapp.com/
, a protected path
The section of code which deals with setting the cookie and redirecting looks like this:
export const getServerSideProps: GetServerSideProps = async (context) => {
// code extracting AUTH_TOKEN_VALUE and sending it to backend API
context.res.writeHead(307, {
"Set-Cookie": // the HTTP only cookie containing AUTH_TOKEN_VALUE,
Location: "https://myapp.com/"
}).end()
return { props: {} };
}
Ideally, this would result in the NextJS app sending the browser an empty response that only contains those two headers. The browser would receive and save the auth cookie, and then redirect to https://myapp.com/
. The redirected request will now have the auth cookie and succeed in going to https://myapp.com/
.
Strangely, however, when I test it, the page I end up on is https://myapp/auth/login
. The first thing I did is check if the redirect happened at all (by console logging in the getServerSideProps
of the appropriate pages), and sure enough, it did. It first hit the /auth/login?token=AUTH_TOKEN_VALUE
endpoint, then the /
endpoint, then the /auth/login
endpoint.
The next thing I did was check if the cookie was set, and sure enough, it was (I checked in the Application tab of DevTools). In fact, if I subsequently, MANUALLY navigated to https://myapp.com/
, it did not redirect me back to /auth/login
since I had the authentication cookie.
I also tested if browser-side redirecting can even be done in such a manner, and sure enough, it can.
When running the following code inside getServerSideProps
:
export const getServerSideProps: GetServerSideProps = async (context) => {
// other code
context.res.writeHead(307, {
Location: "https://example.com/?test=true"
});
return { props: {} };
}
It in fact DID redirect me, browser-side, to https://example.com/?test=true
. This suggests to me that NextJS checks if it CAN perform an internal redirect (by checking the hostname of the Location
header probably) and if it can, it does.
Is there a way to disable this behaviour and let the browser do the redirecting? Because for my application, I NEED the browser to be doing the redirecting, or else there won’t be the authentication cookie that I need in the redirected request.