NextAuth.js v4 and beyond
Balázs Orbán / 2021 December 04
12 min read
So NextAuth.js v4 is out! 🎉
NextAuth.js v3 and a half(?)
Since I've started maintaining the project, I've also introdced changes to v3, which I never really talked about. But since some of it were essential for v4, I'll mention them briefly as well.
TypeScript
One of the most adopted tool of a JavaScript developer is TypeScript. Not only providing hints about available APIs and inline documentation, TypeScript makes refactoring super easy for even newcomers to the project. When I became a co-maintainer, I knew and understood exactly zero of the source code. To help myself along the way, when I needed to write anything new, I always added JSDoc comments to myself, which you can think as a loose, compile-less version of TypeScript. With loose, I mean it gives a false sense of safety and confidence, but good enough so that you don't have to jump between files all the time.
As my understanding for the source code grew, and I had more and more of these JSDoc comments in place, I decided to involve the DefinitelyTyped maintainer, @lluia (Lluis), and ask him if he was interested in migrating the community types into the core. I could not only get an awesome person on my small "team", but we could deliver up-to-date types for the community, that would result in less issues and faster development. We then gradually migrated the types into the core, and now the @types/next-auth
is deprecated!
There might still be some small quirks, so if you find any, please let us know. But for the majority of users, the migration should have resulted in a lot less issues.
Adapters
You can use NextAuth.js to optionally save user data in your database of choice. To communicate with databases, NextAuth.js uses Adapters. When NextAuth.js v3 came out with a single adapter, it was using TypeORM under the hood. A fairly popular ORM at the time. The community soon saw the possibility, and wanted to expand beyond TypeORM. A Prisma adapter soon appeared in the source code, copying on the existing adapter.
This was awesome, because from now on, users could be able to write their own adapters, and just like with the OAuth providers, we could give full freedom to the user about their database. (One of the main goals for NextAuth.js is to give the user full control over their data.)
The issue with adapters at the time was that adding them as part of the core repository wasn't truly scaleable. Most adapters required an ORM, and bringing these into the core blew up the bundle size. So I decided that the best way for us to solve this was to create a separate repository for adapters, and distribute adapters as their own modules, letting the user import them only when needed. Enter @ndom91 (Nico). Another amazing person to our small team! I haven't worked with databases before, and I needed all the help to get started. I did not just want to migrate the existing adapters, but I wanted to make sure that the community can easily add new ones with confidence.
We have created a basic set of tests to conform to the NextAuth.js core. Soon enough, the community saw discovered the project and started opening pull requests for new adapters! As of writing, we have 11 adapters, and we are working on a few more. Open a PR if you are missing one!
NextAuth.js v4
Now that we are all caught up, let's finally see the goodies! What's exactly new in v4?
If you are coming from v3, we have created an upgrade guide for you.
Improved OAuth and OIDC support
NextAuth.js has already had a stellar list of built-in providers, but we wanted to make it even easier to add new ones! One of the tasks were to remove any provider-specific "glue" code from the core, and rely more heavily on the OAuth specification. openid-client
, jose
and its maintainer deserve a huge applause for this, because without @panva and his truly amazing projects, v4 probably wouldn't have been possible Filip delivers high quality libraries to the community. Thank you! 👏
Moving to openid-client
required a refactor, but in my opinion it will be a huge success. It is simpler than ever to add your own custom provider to NextAuth.js, if you cannot find it in the built-in providers yet.
Normalized APIs, focus on future extendability
Without going deeper into API changes, one of the main focus for v4 was to make it easier for future versions to implement new things, without breaking old behavior. Callback methods that previously used 5+ parameters are now using named parameters, so you can grab exactly what you need, leaving the rest of the params out, the adapters forward any data they are given so you don't need a whole custom adapter to save something that isn't the default, and so on. Check out the migration guide for a more comprehensive overview.
From v4 onward, I'm considering something like Next.js's experimental
flags. v4 has taken way too long to be released, and I want the adoption of new features to be much easier.
Testing of Providers
The ever growing list of built-in providers also meant we have a bigger surface to cover. A challenge with testing OAuth providers that many of them disallow bots to finish a login process (eg.: by randomly showing a CAPTCHA). I'm still thinking about how to test these providers, and please reach out if you have an idea. For now, we are going to be much more conscious about adding these new providers, making sure they follow the OAuth/OIDC specification as much as possible, and that they come with the same set of default features. (As long as the provider allows it)
Decoupled core from Next.js
The core functionality of next-auth
is now independent of Next.js API routes. This was the key to improve performance in certain situations.
getServerSession
The Next.js documentation explains that you should not use fetch calls to communicate with your own API routes, just import the logic directly. To keep the library simple, this rule has been broken by next-auth
, which sacrificed performance. It is better explained in this issue. In short, a new API is coming, that will improve the performance on serverless platforms like Vercel.
// import { getSession } from 'next-auth/react' // current way
import { getServerSession } from 'next-auth/next'
import { options } from "pages/api/auth/[...nextauth]"
...
export async function getServerSideProps(context) {
// const session = await getSession(context.req) // current way
const session = await getServerSession(context, options)
return {
props: {
session
}
}
}
This API is still undocumented and should be considered experimental.
Increased security
We are an authentication library. Most of our intended users come with limited resources when it comes to implementing authentication. We would like to help them as much as possible to think less about security, and focus more on building awesome apps. From now on, if you are using the strategy: "jwt
(default) option, we will also encrypt the session content (JWE). This only requires you to make sure that you provider a secret
at minimum in your production environment. Read more here.
Theming
To quickly get started, NextAuth.js implements some pages for you, like the login page for multiple providers. Until now, styling these pages have been limited, and users had to create custom pages for the most simple changes. Now, we have a theme system that will allow you to easily create your own pages, and use it in your project.
You will be able to add a brand logo, define a brand color in addition to configure your preferred color scheme (auto, light, dark).
Check out the theming section for more information.
Improved React integration
next-auth/client
has been moved to next-auth/react
. As we are exploring support for new frameworks, we want to make space for new libraries, like vue
or svelte
. We can even implement a Vanilla JS client, that doesn't depend on any framework.
Future plans
Refresh token rotation
Refresh token rotation implies the ability to update a user's access_token
without the user having to re-authenticate. Currently this has to be implemented by the user, but we are planning to make this easier for them. The details aren't clear yet, but if you have any suggestions or you would like to help out, please let us know! The goal is to have zero-config support for most of our built-in providers (at least for those that support refresh tokens).
Federated logout
Outsourcing authentication can benefit users in terms of security, but in some cases (like shared computers) it also means that whenever a user is finished with their work, they should be logged out everywhere on the computer. This is often referred to as federated logout. I've implemented this previously at work that also ships to production, but similarily to the refresh token rotation, we are planning to implement this in a way that requires the least configuration.
Token Provider
We already support OAuth, Credentials and Email as a provider, but we could open up for a whole new set of authentication if we generalized the Email provider. Check out this RFC for more information.
Subdomain support (SSO)
There are situations where you want the user to log-in on one site, and be logged in automatically on another. This is referred to as Single Sign-On (SSO). This is actually already supported by NextAuth.js, but the configuration for it is slightly hidden, so we would like to improve the experience.
Handle login cancellation
When a user is redirected to an OAuth provider's authorization page, they can decide to not follow through with the login for several reasons. In that case, they can be reidrected back to the application. We should provide a unified experience for this.
User management (link, unlink, delete, session update)
NextAuth.js comes with secure defaults for things like automatic account linking. But there are certain cases, where the user needs more control. With the NextAuth.js v4 adapters, we can provide a unified API for managing users. We can even create a profile page, where users can update their profile information, link/unlink delete accounts, or change/verify e-mail addresses. This will probably be customizable just like the current built-in pages.
We would also like to give a better experience when updating user information, without needing to relad the entire page.
Expanding to other frameworks
Decoupling the core from Next.js API routes also means that NextAuth.js can be dropped into any framework, with a few lines of code!
It's probably one of the changes that I am most excited about, because it will let us engage with new communities, and hopefully get some new maintainers on the project. The more the merrier 😊!
It will also make server-side sign-in and sign-out easier! To join the discussion, check out this issue. There are already people trying next-auth
out with Nuxt and SvelteKit!
Testing
We have much to do in this area. I would like us to give a similar set of tests what we have been doing for the Adapters in v4. If you would like to help out, please let us know!
Next.js Middleware
Middleware
Next.js 12 shipped Middleware. Many sites deliver mainly static content to their users by the need to authorize them first- Think of paywalls, or Role-Based Access Control (RBAC). Middleware is perfect for this usercase. You can intercept any request to a page, and authorize the user based on the request. Our import { getToken } from "next-auth/jwt
method has been refactored to work with Next.js Middleware, and we are exploring how to support more of our core features directly in the middleware.
React Server Components (RSC)
As of writing, this is a Server Components are still experimental, but we have plans supporting it when it is ready.
Some interesting numbers
- When I joined NextAuth.js, the library had ~10.000 downloads a week. We recently passed 100,000, which is a 10x increase in one year! 🤯
- Our small maintainer team now consists of 3 people, building on what @iaincollins (Iain Collins) has started
- Added 31 new OAuth providers providers (55 in total), also making it much easier to add new ones
- Added 9 new Adapters (11 in total)
- ~5000 new GitHub stars (3x growth)
- ~2000 new followers on Twitter (5x growth)
- 3 new financial contributors (see below)
These are some amazing results and I am so excited for our future!
Support
Despite delivering auth at scale for so many users, we are a small team, working on this project in our free-time! If you or your company benefit from our work, you could consier supporting us financially at our Open Collective page. Join amazing companies like Vercel, Prisma and Clerk. We are grateful for one-time contributions as well, and starring the repos or answering a fellow community member's question is also deeply appreciated. 💚