Next.js — JWT auth example app

Example of an Next.js app using SSR (Server Side Rendering) to protected pages under login and talking with and Express.js API server via JWT authentication.

Photo by David Papillon on Unsplash

0. Project Structure

There will be two folders. One is server and the other is app. The server one will contain an Express app, while the other will contain the Nextjs app. Both will run on their own ports. App/Client on 3000, and Express/Api on 3001.

1. Server side

Lets first build the server side. Start first with a standard Express.js app. Create it in the server folder.

Now because our client is also written in JavaScript, we must handle CORS. You can use a fancy library or you can add the logic yourself. Just add this lines of code.

Now we add JWT support. I’m using the jsonwebtoken library.

Do note, to keep yout secrets secure in a .env file and never push them to git. This is just an example.

I define a custom middleware code that will check the header Authorization if a value is present, validate it and then decide wether to continue with the request or block it and return 401 Not Authorized back. The api route for login does not need to be verified as that route will not have the header set.

Finally let’s add some routes that the client can call.

The login route will create a fixed JWT token, expiration set to 1min.

The token ping route, we need this one for the Next.js SSR. Next.js code while doing SSR it has to verify the token somehow otherwise it will render the “secret” page (non-auth users can’t access), show it to the user, and then again render another page on the client side (e.g. login) once it figures out that the user should not see the secret one. So while doing the token verification on the SSR of Nextjs live cycle, the app can render the correct page to the user from the start. Speaking of Next.js…

2. Client side

Create a Nextjs app like you would normally in the appfolder. Now make apages folder and add the following two:

The index page has a button. When you click on it, it will call the api/login endpoint, which returns a token. The token is then stored in a cookie. I also store it in state, just to display it on the page, for demo purposes.

Index also contains a link to a Secret page. Looks like this:

This secret page can only be viewed/accessed by if a valid token is present.
We can check this in the functiongetInitialProps.

handleAuthSSR does all the checking. Based on the context it determines wether we are server-side or client-side, then gets the token value. Remember, while we are server-side we don’t have access to cookies or localStorage and other browser related stuff, only the request and what was send with it.

Based on the response from api/token/ping, we either do nothing, or we redirect back to login in case of an error. Now, based on if we are server-side or client-side we must redirect the correct way.

And that’s it, fell free to clone the repo and run the example yourself if that helps you better understand.

Whole code can be found at: https://github.com/zprima/jwt-cors-app

developer