Picture this: you’ve built a cool app called Blogs. Users can browse posts, filter them by tags like "travel" or "coding," and admins can write or edit posts. But what if someone pretends to be an admin and deletes everything? Or sneaks into a user’s private drafts? Authentication is the key—it’s like a bouncer at a club, checking IDs to let the right people in.
Authentication verifies "who’s who" in our app. It’s crucial for protecting data, controlling access, and making sure users trust us. Today, we’ll explore different ways to handle authentication in Blogs using Next.js and TypeScript. We’ll start with the basics, then dive into tokens, OAuth, and even SAML—stuff you’ll see in real apps. Plus, we’ll compare how secure each method is.
A common myth? "Passwords alone are enough." Nope—hackers love weak passwords. Another one: "Only admins need authentication." Wrong—every user needs it for a personalised experience. Let’s get started!
Let’s start with a classic approach: cookie-based authentication. In our Blogs app, when a user signs up, we store their email and a hashed password in a database like PostgreSQL. But the real magic happens with cookies—they’re how we keep users logged in without asking for their password every time.
Alice logs in to Blogs to check her drafts:
alice@example.com
and supersecret
.supersecret
with bcrypt, verifies it, generates a session ID (e.g., sess_12345
) and stores it in a database or any key-value storage to know which user belongs to this session.session=sess_12345
) and sent to her browser.session=sess_12345
) stored in the browser. Think of them as a backstage pass for Blogs.Cookie: session=sess_12345
). The server responds, and the dance continues.supersecret
plain—it’s hashed (e.g., $2b$10$...
) so leaks don’t expose it.Secure
, so they only travel over HTTPS, not plain HTTP, preventing eavesdropping.document.cookie
), blocking XSS (cross-site scripting) attacks.Strict
or Lax
, this limits cookies to our domain (Blogs), stopping CSRF (cross-site request forgery) where fake sites trick Alice into sending requests.Imagine Alice’s cookie gets stolen because we forgot HTTPS. A hacker could send requests as her—scary! But with HTTPS, HttpOnly, and SameSite, that cookie’s locked down. For Blogs, we’d set it up like this:
session=sess_12345; Secure; HttpOnly; SameSite=Strict
Now, let’s scale Blogs up. What if users want to log in from their phones, which do not support cookies? JSON Web Tokens (JWT) are a slick, token-based solution.
{ "userId": 1, "role": "user" }
), signs it, and sends it back.Authorization: Bearer <token>
).Alice filters Blogs posts by "coding." Her JWT proves she’s userId: 1
, so the server sends her the right posts.
Let’s dive into a powerful twist on token-based authentication: using session tokens and refresh tokens together. In our Blogs app, this approach helps us keep users like Alice logged in securely, even across devices, while minimizing risks if something goes wrong. Here’s how it works, why it’s safer, and where everything lives.
Imagine Alice wants to log into Blogs to write a post. Here’s what happens with session and refresh tokens:
This workflow is a big upgrade over a single, long-lived JWT. Here’s why:
Storage is key to keeping this secure. Here’s the breakdown:
Here’s how Blogs handles the token dance:
header.payload.signature
.What if Alice hates passwords? With OAuth, she can log into Blogs using her Google account.
Alice, an admin, logs in via Google. Her token proves she’s alice@gmail.com
, and Blogs gives her admin rights to edit posts.
next-auth
make this a breeze.Imagine Blogs is used by a company wanting single sign-on (SSO). SAML (Security Assertion Markup Language) steps in.
Alice, a company admin, logs in via SAML. The assertion says role: "admin"
, so she edits company posts.
Let’s break down how secure each method is for Blogs:
Key Insight: No method is "perfect." Security depends on how you use it—think HTTPS, strong hashing, and careful token management.
Here’s what we’ve learned about authentication in Blogs:
Best Practices: Hash passwords, use HTTPS, keep tokens short-lived, and match the method to your app’s needs. Pitfalls: Avoid plain-text passwords, unencrypted traffic, or skipping refresh token revocation.
Next time you log into an app—or build one—think about how it’s keeping you safe. You’ve got the tools to make Blogs secure and awesome!
Let's talk about different ways you can authenticate users of your application and deliver personalised experiences.
What is authentication?
Authentication is like a bouncer at a club—it checks who’s allowed into our Blogs app. It ensures Alice can see her drafts or edit posts as an admin, keeping imposters out!
Without it, hackers could trash Blogs posts or peek at private drafts. It builds trust—users feel safe, and we protect their stuff.
We’ll use Next.js App Router to add four authentication methods to Blogs: cookies, JWTs, OAuth, and SAML. You’ll see how they work and why they’re cool.
This is a basic login API for Blogs using App Router. Alice logs in, and we check her credentials—later, we’ll secure it!
This code implements a NextJS REST route that accepts a post request.
We grab Alice’s details from her login form provided as an object of POST request body
We check if Alice exists in the database
If Alice does not exists or her password does not match, we return an error message and status 401, representing unauthorised request.
If Alice is found, we return a positive message, which automatically return status 200.
In the previous slide, we showed how to authenticate a user in your application. But how can we maintain the authenticated session so that the user does not have to write a username and password with every request? We can use cookies! Cookies help maintain authenticated session by storing an identifier of the session. Let's break it down!
Alice logs into Blogs, and the server gives her a cookie, for example, containing the session ID or user ID—like a VIP wristband.
Her browser sends it back every time she browses.
We store the session ID in a Secure and HttpOnly cookie, so hackers can’t grab it. Simple and solid for Blogs! Next time, Alice clicks “My Drafts,” and her cookie proves it’s her—no re-login needed.
This is an example of cookie-based authentication endpoint.
This time, we will keep a record of all session IDs that the user has initiated.
Similarly to our previous example, if the user is not authenticated, we return an error message and an error code.
But, if the user authenticates, we generate a new session ID as some random string and store it in user's active session ID's.
We prepare the response with the return message.
Then, we add the session cookie to the response, providing this created session ID. Check how we set the secure and HTTP only properties.
Last, we return this response that will automatically set the client side cookie.
Let's take a look how we can use cookies to authenticate a session,
First, we read the sessionId from the cookie store
Then, we try to find a user who initiated a session with the provided sessionId. You need to generate session IDs that are complex enough so that users cannot guess them!
If the sessionId is not provided or user with that sessionId does not exists, we return an error.
Otherwise, we are in the authenticated zone, where we know which user is interacting with the route, returning only their drafts.
While cookies are the usual preference in the authentication of web applications, you may run into issues when securing mobile applications or heightened security applications that do not allow for the use of cookies. This is where JSON web tokens come into play.
With JWT we tend to use two different types of tokens. A session token is a short-lived token, often stored in a local storage that expires in a matter of minutes, and it is added to every authenticated request to confirm users identity.
The token is usually provided as an Authorisation header, bearing the token value. The lifetime of a session token is limited in case an attacker steals this token its use will be limited.
Refresh tokens are used to obtain new session tokens when old ones expire. They are stored more securely in either an http-only cookie or keychain.
Let's break down an example of how we can use JWT tokens to secure our application
We will use the popular jsonwebtoken package to handle the JWT tokens.
First, with JWT we need a strong secret that we will use to sign our application tokens. This time, we provided it directly in the code, but this is not secure as your secret would be stored in the repository. Please use environment variables instead.
We will also store the list of refresh tokens in the memory. Normally, you would store them in a persistent store, such as a database.
Similar to our previous examples, we find the user with the provided username and password and return an error if the user does not exist.
If the user exists, we create and sign a new session token with 15 minute validity
Also, we create and store the refresh token
Last, we prepare a response, where we return the value of the session token.
We also set the cookie with the refresh token value. Now, the response is ready to be delivered to the user with the session and refresh token ready to be used.
Let's take a look at how we can issue a new session token based on the old expired token.
First, we grab the refresh token from the cookie.
Then, we find the user that has this refresh token. This time, we assume that the session tokens are stored in a dictionary, mapped by refreshToken.
If the token or user does not exist we issue an error.
Next, we grab user info from the database ...
... and use it to issue a new session token with 15-minute validity.
... which we return back to the client,
Let's take a look at how we can use session tokens to authenticate requests.
First, we read the authorisation value from the request header.
If the authorisation header is missing, we issue an error.
If the token has been provided in the header, we verify it using the provided secret.
If the verification passed, we return the desired user posts.
If the verification failed, an error is thrown and we issue authentication error, mentioning the incorrect value.
The beauty of tokens is that you can use the same token to access multiple endpoints and services and use only one endpoint to re-issue new session tokens. This is the standard approach to securing API endpoints which we will cover in the near future.
The best approach is to leave authentication and password storage to others to minimise security risks to your application. A popular way of doing this is by using OAUTH and social logins with Github, Google, or others. In NextJS, we use the popular NextAuth package. Let's check it out!
We are going to implement a Google login provider. NextAuth contains over 50 providers, and we must choose the correct one. In our case, we choose Google.
Then ,we configure the provider with the arbitrary secrets, which you can obtain as per documentation in the NextAuth package
Then, we provide extra values to the token that will be issued to the users based on successful Google login.
Last, we can modify which information will be accessible in the session object. In our case, we add info about authorisation access of the current user based on their role.
Using NextAuth is very simple!
All we need to do is to call the getServerSession method, which returns the session object if user is logged in, or null if the session is anonymous.
Once we have the session object we can authenticate and authorise the request, returning only desired user's posts.
SAML is there for those who want to use single sign-on, similar to what Western Sydney University uses to log in to many of its applications.
SAML is aimed at large enterprises connecting many endpoints
The protocol issues XML with details of the user who logs into the system.
For simple apps, stay out of SAML as its implementation and administration is quite complicated.
We’ve seen cookies, JWTs, OAuth, and SAML in Blogs—now let’s compare them. Each has strengths and quirks, so you can pick the right one for your app!
Cookies are simple for Blogs—The user logs in, gets a cookie, and browses. Secure with HTTPS, but a stolen cookie’s trouble.
JWTs give users tokens—short ones keep hackers at bay, and refresh keeps her in. Great for their phone!
OAuth lets users use social logins—super secure and no password hassles. Perfect if Blogs want happy users.
SAML locks Blogs down for a company—Users log in once via Okta. Complex, but awesome for big teams.