Penn
Posted on April 27, 2023
NextJS doens’t provided internal authencation support such as private root, redirection for unauthenticated request.
This article introduce a approuch to use Nginx to help fill the gaps.
Steps
Add an API to authenticate incoming request
/next-app/pages/api/auth.tsx
import { NextApiRequest, NextApiResponse } from 'next'
import isValid from 'token/isValid'
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const token = req.cookies['access_token']
// isValid is an function that check if the token is valid or not
if (await isValid(token)) {
res.status(200).json({ message: 'Hello from Next App!' })
} else {
res.status(401).json({ message: 'unauthorized' })
}
}
PS: Please use the real isValid function for your project. 🙂
Protect private routes, redirect to signin page if unauthencated
Let’s say the Next App is serving on port 3030
. Nginx listens incoming request on 3000
and make redirection per configuration.
nginx.conf
server {
listen 3000;
listen [::]:3000;
server_name localhost;
large_client_header_buffers 4 12k;
gzip on;
gzip_types application/javascript application/json text/css;
# Place this before the next one in order to take the high porior.
location ~* ^/_next/data {
auth_request /auth;
auth_request_set $auth_status $upstream_status;
error_page 401 =401 /401;
proxy_pass http://localhost:3030;
}
location ~* \.(gif|jpg|jpeg|svg|png|ico|woff|woff2|js|css|json|yaml)$ {
expires 1y;
add_header Cache-Control "public";
proxy_pass http://localhost:3030;
}
location /_next/static {
expires 1y;
add_header Cache-Control "public";
proxy_pass http://localhost:3030;
}
# public routes
location ~* ^/(sign_in|other-public-routes)/?$ {
proxy_pass http://localhost:3030;
}
location / {
auth_request /auth;
auth_request_set $auth_status $upstream_status;
error_page 401 =3=2 $schema$host/sign_in?redirect=$request_uri;
proxy_pass http://localhost:3030;
}
location = /auth {
internal;
proxy_pass http://localhost:3030/api/auth;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
}
Note: Make sure the location ~* ^/_next/data
take a high prior by placing it before the static asset location location ~* \.(gif|jpg|jpeg|svg|png|ico|woff|woff2|js|css|json|yaml)$
.
The incoming request will be redirected to /auth
(actually /api/auth
on Next App). When the response code is 401, a [302](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/302)
redirection to /signin will be returned to the client. Then the user has to finish the signin
process before actually visiting the protected pages/apis.
The sequence diagram would be:
Tips: use the online test to verify matched location with request uri.
Alternative when $schema
or $host
is transformed
Sometimes the $schema (either HTTPS or HTTP) or $host (e.g. www.notion.com) is not the same with the one that the user types in the address bar in the browser since the request was proxies by another gateway so the original host was replaced. In this case, using server-side redirect could resolve the problem.
nginx.conf
location / {
auth_request /auth;
auth_request_set $auth_status $upstream_status;
error_page 401 /signin?redirect=$request_uri;
proxy_pass http://localhost:3030;
}
Since it’s server-side redirection, the redirect param has to be handled on the server side as well.
Data Fetching: getServerSideProps | Next.js
Summary
- Add authencation API in NextJS app.
- Perform redirection with Nginx
Nginx plays the key role in the sample. And you may get it that the authencation API could be replaced by any third part API. And the flexibility is provided by Nginx.
Posted on April 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.