Next-auth: Remove error - NextAuth requires a 'database' or 'adapter' option to be specified.

Created on 4 Jun 2020  路  12Comments  路  Source: nextauthjs/next-auth

Error:
NextAuth requires a 'database' or 'adapter' option to be specified.
See documentation for details https://next-auth.js.org

Now that jwt is to be default

enhancement question

Most helpful comment

Is it possible to use multiple databases now? When using sessions some people for example want to save those to Redis or MongoDB and save the user data to Postgres.

And databases with social providers, I'm not sure about the no database thing. There are several packages that handle OAuth login but not the whole extra stuff this package provides so if someone wants that they can use one of these packages? I don't think we should drift away from the core too much especially if other packages already solve this problem.

Also maybe we can create separate packages for each login provider so these have to be installed separately as Passport does? Maybe this makes customization easier?

All 12 comments

So this is an interesting one!

I need to write this up somewhere, but I'll start here so I can crib from it later, and reference any follow up questions / answers.

JWT by default?

JWT is actually not the default right now, but can be used for sessions (with jwt: true) option.

However, JWT could be used without a database - and supporting that is absolutely the intention - but it depends on the use case as it won't be suitable for everyone (see below).

Note: For now it is possible to specify an in-memory SQLite DB and effectively is the same thing, but absolutely, it should be possible to just literally not specify a DB in future if JWT is enabled.

The obviously logical progression is then that it should just default to JWT if no database is specified so everything "just works" as long as you have at least one authentication provider.

The only snag there is I don't want the behaviour or options to be confusing to feel like there are gotchas, so am weighing up what is the most logical and consistent behaviour, and trying to factor in likely future options (e.g. functions that can get run before and/or after events) so that the API makes sense and is easy to understand for people new to NextAuth.js.

e.g. One option might be to ask people to set database: false explicitly, to draw attention to this and nudge people to read the documentation for it so they understand the implications, but if jwt: true is set to treat it as false and print a warning if it is left null / undefined. I'm not saying that's how it will or should work, just that that's my thought process on that.

Do we need a database?

We can avoid the error about having a database (and perhaps just make it a warning) if jwt is not specified and is fine for controlling access to services but that will not work for everyone.

One example is, if you want to persist things like a RefreshToken from services like Google, then you actually need to persist an account in a database as these are only granted on first sign in with Google (and some other providers).

You can actually change the sign in options for Google to force it to issue a new RefreshToken on every sign in, but then sign in flow gets more cumbersome every time, for everyone as it adds an extra confirmation prompt to the sign in flow from Google, and Google ends up silently revoking old RefreshTokens if you do this, which causes all sorts of issues for folks; basically this flow is intended for mobile app providers where they persist the data in the app, not for web browsers where the data is more transitory.

Not everyone (in fact, probably most use cases) actually need a RefreshToken for a user. It's only something you need if you are doing operations on behalf of a user via an API, but in most users cases just want to use authentication to authenticate people in a sign in flow.

_Note: To make things more confusing, it not true for all providers though, Twitter issues both an AccessToken and RefreshToken on every sign in._

However, in those cases typically you may also want to actually know who your users are.

If you are building an internal application, you don't need to and could just use an authentication provider that only lets you sign in from a specific domain / organisation account and that is fine, you don't need to track your users.

However, if you are building any kind of end user facing application - or using it for any kind of business with multiple end users - you will almost definitely want to have a user database so you know who your end users / customers are.

tl;dr You still need a database for some services / use cases - it depends what you are doing.

Product design decisions

Another consideration has been product design. This can be under appreciated in open source projects but thinking about the product experience is super important to making software easy to use and to understand, and with authentication there is of course a lot going on.

Currently NextAuth.js requires an email address to create an account. This a product decision as much as anything, it makes sure users have a way to sign in as long as they can access their email address (even if they close their account with Facebook, or whatever) and that there is a way to contact users if something goes wrong or there is an important announcement (e.g. security breach, a service changing or closing, etc).

Technically this constraint could be removed with additional work, and technically we could store multiple email addresses per user - a feature I'd like to support, but probably there are a bunch of other things to do first; and that's a such a big change it would probably be v3; though if we were crafty we might be able to do it as an backwards compatible update to v2.

There is a case that the software should be as flexible as possible for everyone, and I while I aim for that I don't entirely hold that view if it means the software becomes harder to use and understand for a wider audience that might otherwise find it useful.

I'm willing to accept enforcing some constraints if it leads to a better user experience that is as simple, less error prone and as secure if it could be. I think we if supported the widest possible array of options, it would lead to more security problems (even if it was entirely secure by default) and more errors in complex sign in flows and a more confusing API and that people would end up liking NextAuth.js less.

The only way I know to deal with conundrum is to communicate what the goals are, to listen to feedback and to communicate any decisions that are made - and to keep reviewing any decisions over time.

tl;dr I try to balance the needs of different people using NextAuth.js and the safety and user experience of end users as they are ultimately intertwined and I accept at times some people will be unhappy about some of the decisions and accept that as a lesser evil.

Tagging in @LoriKarikari @ndom91 @geraldnolan on this as it's quite a can of worms :-)

^ One specific action on this (which is currently being tracked in #98) is that all actionable error messages on the console should all point to a specific documentation page. Tagging that issue in as a reminder.

(Make sense to clean up the console / error logging behaviour first though, so it's all handled by one or two functions.)

Is it possible to use multiple databases now? When using sessions some people for example want to save those to Redis or MongoDB and save the user data to Postgres.

And databases with social providers, I'm not sure about the no database thing. There are several packages that handle OAuth login but not the whole extra stuff this package provides so if someone wants that they can use one of these packages? I don't think we should drift away from the core too much especially if other packages already solve this problem.

Also maybe we can create separate packages for each login provider so these have to be installed separately as Passport does? Maybe this makes customization easier?

We should split this up into concrete tasks we can split up among people. I've heard you say in a few places you wanted to give the JWT / no database requirement another think before coming to a conclusion, right? Once you have that nailed down theoretically, maybe you could come back here and let us know exactly how we can help. i.e. code changes, docs, etc.

Regarding the oauth providers in separate docs. I agree having separate pages for each is probably a good idea, that way you can elaborate more on each and get into details for the ones that require it (apple, for example).

Putting the oauth providers into separate packages though may be a bit overkill imo. What would be shipped in each package? i.e. what would the differences be? Mainly just the config object, right? I think that would be a ton of work, managing all those packages, just to save people the work of copying and pasting the configs out of the docs. Sure it may be a bittt more user friendly. But at what cost, you know?

Right now it might be overkill but when you have a large number of providers with their own quirks it might be nice to split them up? There are so many other protocols that we don't support yet. It's better than adding a bunch of if-else and workarounds to make them all work and the code gets messy. But this might be a concern for later as we aren't really at that point yet. It's a bit out of the scope now.

Anyway @iaincollins, I will see what you come up with and will gladly help. In the meantime I'll continue adding providers and start writing docs for each one of them.

These are good questions! Will try to address questions / comments from both of you here as they do related a lot to JWT and database support.

PS: I agree needs some work on planning and tickets :-)

Is it possible to use multiple databases now? When using sessions some people for example want to save those to Redis or MongoDB and save the user data to Postgres.

No, only one at a time. I agree this is a not uncommon use case, and v1 did support it for that reason, but it was complicated to wrangle as a result and I would rather not even think about doing that again and just provide an easy turn key solution where you have three simple options:

  1. Pick a single database for everything
  2. User and Account database, with JWT for sessions
  3. No database, with JWT for sessions

To support option 3 would still have a custom sign in function so you can still control who can sign in (e.g. verified or whitelisted accounts from a specific provider only, or via email only, etc).

We could also provide further functions for sign in and for sessions - to let people handle this entirely themselves, but I'm not inclined to get fancy with this as you are right it gets really complicated for everyone otherwise.

And databases with social providers, I'm not sure about the no database thing. There are several packages that handle OAuth login but not the whole extra stuff this package provides so if someone wants that they can use one of these packages? I don't think we should drift away from the core too much especially if other packages already solve this problem.

I get where you are coming from and absolutely agree about not drifting too far from the core proposition; that's actually one reason I am reluctant to encourage people to use username / passwords with the service; I want it to be simple and secure (and it's an often requested feature, but one that can be problematic).

The no database scenario is one I personally need on a few sites, where I just want to restrict sign in to an "allow list" of specific accounts, or to everyone at a specific domain on Google (with a verified account) and I want to make that really easy to setup - and I think a lot of folks have that use case when building tools tools.

Mostly I use it for things things like company dashboards or sites with a simple CMS where only certain users can sign in and make changes to content or to admin users.

Also maybe we can create separate packages for each login provider so these have to be installed separately as Passport does? Maybe this makes customization easier?

I thought about that but it's quite an admin overhead to manage that, and PassportJS providers need a lot of config and it's not even that simple to use - the passport modules don't even have compatible signatures, so were a bit of a nightmare to support in v1.

There are some other modern tools that also just bundle a load of OAuth providers as simple configs are so light and I'd rather keep it that way - but it has been designed so they are just passed as object so folks should be able to create their own provider libraries if they want to.

I appreciate there are going to be weird exceptions (e.g. for Apple) but am prepared to make a small number of those for really common providers and to refactor the OAuth code as required over time.

I think maintaining an API that lets you plugin any other provider is actually a lot more code and (based on experience with PassportJS) it doesn't really live up to the goal of them being that interoperable anyway (sadly, because the OAuth spec is so loose).

RE: Database support / Splitting the package

I think I want to keep the package roughly as it is with regard to what is included; to make life easier for both people who are using it and for people working on it.

I think having the client, server, common database layer and common provider support included results in a reasonably small bundle size (if still bigger than I would like) and the result is it's fairly easy to use.

The only exception I think I might make to that is making the database support require loading a third party module if we start seeing support for other databases, like FaunaDB and Prisma. I don't plan to change how the default provider for version 2.0, but I would consider in future publishing different modules for different databases and requiring folks to pass them as an option.

e.g. The default SQL provider might be one model, the MongoDB version might be another.

Splitting them means be more development overhead, which is why I don't want to do it now, but is more scalable and would keep the bundle size smaller.

I feel like for now though, using TypeORM for MySQL, MariaDB, Postgres and MongoDB (the latter having required a little hackery) is really good bang-per-buck. The structure is (by design) very simple ANSI SQL compatible too, so it should really work with any SQL database.

It was actually a somewhat hard decision to accept the limitation as it's not infinitely flexible and it is a larger core dependancy than I like, but it is fairly small and gives people a lot of options and has allowed development to be really fast.

Good points @iaincollins. I can follow your toughts. About the email and password login, I'm still not sure if we should exclude that. It is the "classic" way of logging in and most websites have it. A lot of people don't want to log in with social accounts so it's nice if you could offer that option too. Passwordless is nice but I can imagine not everyone wants to use that as a replacement as it isn't as widely adopted.

Sorry if this has hijacked the thread a little but I know @jamespfarrell cares about this too, so seems a good place to discuss it :-)

About the email and password login, I'm still not sure if we should exclude that. It is the "classic" way of logging in and most websites have it. A lot of people don't want to log in with social accounts so it's nice if you could offer that option too. Passwordless is nice but I can imagine not everyone wants to use that as a replacement as it isn't as widely adopted.

I should clarify as I'm so negative about it, yeah I agree with we should support it in some form, even though I'm reluctant to go all out with it.

I am not sure what that middle ground looks like yet and looking forward to writing up some thoughts. Would also happy be interested in reading a list of features / functionality / description of the flow people have in mind if they are looking for something specific.

Resolved in #223

Sorry I got distracted for a couple weeks by other projects, I came back here to convince you of how important it is to be able to implement without the requirement of having a database... So cool you have done this already, I run `npm update next-auth' and I'm off to the races!

Thanks @iaincollins et al

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benoror picture benoror  路  3Comments

iaincollins picture iaincollins  路  3Comments

bscaspar picture bscaspar  路  3Comments

readywater picture readywater  路  3Comments

MelMacaluso picture MelMacaluso  路  3Comments