refactor(auth): switch to class-based social login and v4 route handler
Migrate from function-based social login helpers (`facebookLogin`, `googleLogin`) to class-based services (`new FacebookLogin().signIn()`, `new GoogleLogin().signIn()`), updating call sites in `AuthFacebookPanel` and `SplashButton` with try/catch error handling. The NextAuth route handler is also refactored to the v4 pattern, importing pre-built `GET` / `POST` exports from `@/lib/auth/nextauth` instead of constructing the handler inline with `NextAuth(authOptions)`.
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
id: adapters
|
||||||
|
title: Adapters
|
||||||
|
---
|
||||||
|
|
||||||
|
Visit the [authjs.dev](https://authjs.dev/getting-started/database) page for the up-to-date documentation.
|
||||||
|
|
||||||
|
- [Dgraph](https://authjs.dev/getting-started/adapters/dgraph)
|
||||||
|
- [Drizzle](https://authjs.dev/getting-started/adapters/drizzle)
|
||||||
|
- [DynamoDB](https://authjs.dev/getting-started/adapters/dynamodb)
|
||||||
|
- [Fauna](https://authjs.dev/getting-started/adapters/fauna)
|
||||||
|
- [Firebase](https://authjs.dev/getting-started/adapters/firebase)
|
||||||
|
- [kysely](https://authjs.dev/getting-started/adapters/kysely)
|
||||||
|
- [MikroORM](https://authjs.dev/getting-started/adapters/mikro-orm)
|
||||||
|
- [MongoDB](https://authjs.dev/getting-started/adapters/mongodb)
|
||||||
|
- [neo4j](https://authjs.dev/getting-started/adapters/neo4j)
|
||||||
|
- [Prisma](https://authjs.dev/getting-started/adapters/prisma)
|
||||||
|
- [PouchDB](https://authjs.dev/getting-started/adapters/pouchdb)
|
||||||
|
- [Sequelize](https://authjs.dev/getting-started/adapters/sequelize)
|
||||||
|
- [Supabase](https://authjs.dev/getting-started/adapters/supabase)
|
||||||
|
- [TypeORM](https://authjs.dev/getting-started/adapters/typeorm)
|
||||||
|
- [Upstash Redis](https://authjs.dev/getting-started/adapters/upstash-redis)
|
||||||
|
- [Xata](https://authjs.dev/getting-started/adapters/xata)
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
---
|
||||||
|
id: callbacks
|
||||||
|
title: Callbacks
|
||||||
|
---
|
||||||
|
|
||||||
|
Callbacks are **asynchronous** functions you can use to control what happens when an action is performed.
|
||||||
|
|
||||||
|
Callbacks are extremely powerful, especially in scenarios involving JSON Web Tokens as they allow you to implement access controls without a database and to integrate with external databases or APIs.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If you want to pass data such as an Access Token or User ID to the browser when using JSON Web Tokens, you can persist the data in the token when the `jwt` callback is called, then pass the data through to the browser in the `session` callback.
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can specify a handler for any of the callbacks below.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async signIn({ user, account, profile, email, credentials }) {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
async redirect({ url, baseUrl }) {
|
||||||
|
return baseUrl
|
||||||
|
},
|
||||||
|
async session({ session, user, token }) {
|
||||||
|
return session
|
||||||
|
},
|
||||||
|
async jwt({ token, user, account, profile, isNewUser }) {
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The documentation below shows how to implement each callback, their default behaviour and an example of what the response for each callback should be. Note that configuration options and authentication providers you are using can impact the values passed to the callbacks.
|
||||||
|
|
||||||
|
## Sign in callback
|
||||||
|
|
||||||
|
Use the `signIn()` callback to control if a user is allowed to sign in.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async signIn({ user, account, profile, email, credentials }) {
|
||||||
|
const isAllowedToSignIn = true
|
||||||
|
if (isAllowedToSignIn) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
// Return false to display a default error message
|
||||||
|
return false
|
||||||
|
// Or you can return a URL to redirect to:
|
||||||
|
// return '/unauthorized'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
- When using the **Email Provider** the `signIn()` callback is triggered both when the user makes a **Verification Request** (before they are sent an email with a link that will allow them to sign in) and again _after_ they activate the link in the sign-in email.
|
||||||
|
|
||||||
|
Email accounts do not have profiles in the same way OAuth accounts do. On the first call during email sign in the `email` object will include a property `verificationRequest: true` to indicate it is being triggered in the verification request flow. When the callback is invoked _after_ a user has clicked on a sign-in link, this property will not be present.
|
||||||
|
|
||||||
|
You can check for the `verificationRequest` property to avoid sending emails to addresses or domains on a blocklist (or to only explicitly generate them for email address in an allow list).
|
||||||
|
|
||||||
|
* When using the **Credentials Provider** the `user` object is the response returned from the `authorize` callback and the `profile` object is the raw body of the `HTTP POST` submission.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
When using NextAuth.js with a database, the User object will be either a user object from the database (including the User ID) if the user has signed in before or a simpler prototype user object (i.e. name, email, image) for users who have not signed in before.
|
||||||
|
|
||||||
|
When using NextAuth.js without a database, the user object will always be a prototype user object, with information extracted from the profile.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Redirects returned by this callback cancel the authentication flow. Only redirect to error pages that, for example, tell the user why they're not allowed to sign in.
|
||||||
|
|
||||||
|
To redirect to a page after a successful sign in, please use [the `callbackUrl` option](/getting-started/client#specifying-a-callbackurl) or [the redirect callback](/configuration/callbacks#redirect-callback).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Redirect callback
|
||||||
|
|
||||||
|
The redirect callback is called anytime the user is redirected to a callback URL (e.g. on signin or signout).
|
||||||
|
|
||||||
|
By default only URLs on the same URL as the site are allowed, you can use the redirect callback to customise that behaviour.
|
||||||
|
|
||||||
|
The default redirect callback looks like this:
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async redirect({ url, baseUrl }) {
|
||||||
|
// Allows relative callback URLs
|
||||||
|
if (url.startsWith("/")) return `${baseUrl}${url}`
|
||||||
|
// Allows callback URLs on the same origin
|
||||||
|
else if (new URL(url).origin === baseUrl) return url
|
||||||
|
return baseUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The redirect callback may be invoked more than once in the same flow.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## JWT callback
|
||||||
|
|
||||||
|
This callback is called whenever a JSON Web Token is created (i.e. at sign
|
||||||
|
in) or updated (i.e whenever a session is accessed in the client). The returned value will be [encrypted](/configuration/options#jwt), and it is stored in a cookie.
|
||||||
|
|
||||||
|
Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`, `getServerSession()`, `useSession()` will invoke this function, but only if you are using a [JWT session](/configuration/options#session). This method is not invoked when you persist sessions in a database.
|
||||||
|
|
||||||
|
- As with database persisted session expiry times, token expiry time is extended whenever a session is active.
|
||||||
|
- The arguments _user_, _account_, _profile_ and _isNewUser_ are only passed the first time this callback is called on a new session, after the user signs in. In subsequent calls, only `token` will be available.
|
||||||
|
|
||||||
|
The contents _user_, _account_, _profile_ and _isNewUser_ will vary depending on the provider and if you are using a database. You can persist data such as User ID, OAuth Access Token in this token, see the example below for `access_token` and `user.id`. To expose it on the client side, check out the [`session()` callback](#session-callback) as well.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async jwt({ token, account, profile }) {
|
||||||
|
// Persist the OAuth access_token and or the user id to the token right after signin
|
||||||
|
if (account) {
|
||||||
|
token.accessToken = account.access_token
|
||||||
|
token.id = profile.id
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Use an if branch to check for the existence of parameters (apart from `token`). If they exist, this means that the callback is being invoked for the first time (i.e. the user is being signed in). This is a good place to persist additional data like an `access_token` in the JWT. Subsequent invocations will only contain the `token` parameter.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Session callback
|
||||||
|
|
||||||
|
The session callback is called whenever a session is checked. By default, **only a subset of the token is returned for increased security**. If you want to make something available you added to the token (like `access_token` and `user.id` from above) via the `jwt()` callback, you have to explicitly forward it here to make it available to the client.
|
||||||
|
|
||||||
|
e.g. `getSession()`, `useSession()`, `/api/auth/session`
|
||||||
|
|
||||||
|
- When using database sessions, the User (`user`) object is passed as an argument.
|
||||||
|
- When using JSON Web Tokens for sessions, the JWT payload (`token`) is provided instead.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async session({ session, token, user }) {
|
||||||
|
// Send properties to the client, like an access_token and user id from a provider.
|
||||||
|
session.accessToken = token.accessToken
|
||||||
|
session.user.id = token.id
|
||||||
|
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
When using JSON Web Tokens the `jwt()` callback is invoked before the `session()` callback, so anything you add to the
|
||||||
|
JSON Web Token will be immediately available in the session callback, like for example an `access_token` or `id` from a provider.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
The session object is not persisted server side, even when using database sessions - only data such as the session token, the user, and the expiry time is stored in the session table.
|
||||||
|
|
||||||
|
If you need to persist session data server side, you can use the `accessToken` returned for the session as a key - and connect to the database in the `session()` callback to access it. Session `accessToken` values do not rotate and are valid as long as the session is valid.
|
||||||
|
|
||||||
|
If using JSON Web Tokens instead of database sessions, you should use the User ID or a unique key stored in the token (you will need to generate a key for this yourself on sign in, as access tokens for sessions are not generated when using JSON Web Tokens).
|
||||||
|
:::
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
id: databases
|
||||||
|
title: Databases
|
||||||
|
---
|
||||||
|
|
||||||
|
NextAuth.js offers multiple database adapters. Check out [the overview](https://authjs.dev/getting-started/database).
|
||||||
|
|
||||||
|
> As of **v4** NextAuth.js no longer ships with an adapter included by default. If you would like to persist any information, you need to install one of the many available adapters yourself. See the individual adapter documentation pages for more details.
|
||||||
|
|
||||||
|
To learn more about databases in NextAuth.js and how they are used, check out [databases in the FAQ](/faq#databases).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to use a database
|
||||||
|
|
||||||
|
See the [documentation for adapters](https://authjs.dev/getting-started/database) for more information on advanced configuration, including how to use NextAuth.js with other databases using a [custom adapter](https://authjs.dev/guides/creating-a-database-adapter).
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
id: events
|
||||||
|
title: Events
|
||||||
|
---
|
||||||
|
|
||||||
|
Events are asynchronous functions that do not return a response, they are useful for audit logs / reporting or handling any other side-effects.
|
||||||
|
|
||||||
|
You can specify a handler for any of these events below, for debugging or for an audit log.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The execution of your authentication API will be blocked by an `await` on your event handler. If your event handler starts any burdensome work it should not block its own promise on that work.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
### signIn
|
||||||
|
|
||||||
|
Sent on a successful sign in.
|
||||||
|
|
||||||
|
The message will be an object and contain:
|
||||||
|
|
||||||
|
- `user` (from your adapter or from the provider if a `credentials` type provider)
|
||||||
|
- `account` (from your adapter or the provider)
|
||||||
|
- `profile` (from the provider, is `undefined` on `credentials` provider, use `user` instead)
|
||||||
|
- `isNewUser` (whether your adapter had a user for this account already)
|
||||||
|
|
||||||
|
### signOut
|
||||||
|
|
||||||
|
Sent when the user signs out.
|
||||||
|
|
||||||
|
The message object will contain one of these depending on if you use JWT or database persisted sessions:
|
||||||
|
|
||||||
|
- `token`: The JWT token for this session.
|
||||||
|
- `session`: The session object from your adapter that is being ended
|
||||||
|
|
||||||
|
### createUser
|
||||||
|
|
||||||
|
Sent when the adapter is told to create a new user.
|
||||||
|
|
||||||
|
The message object will contain the user.
|
||||||
|
|
||||||
|
### updateUser
|
||||||
|
|
||||||
|
Sent when the adapter is told to update an existing user. Currently, this is only sent when the user verifies their email address.
|
||||||
|
|
||||||
|
The message object will contain the user.
|
||||||
|
|
||||||
|
### linkAccount
|
||||||
|
|
||||||
|
Sent when an account in a given provider is linked to a user in our user database. For example, when a user signs up with Twitter or when an existing user links their Google account.
|
||||||
|
|
||||||
|
The message object will contain:
|
||||||
|
|
||||||
|
- `user`: The user object from your adapter.
|
||||||
|
- `account`: The object returned from the provider.
|
||||||
|
- `profile`: The object returned from the `profile` callback of the OAuth provider.
|
||||||
|
|
||||||
|
### session
|
||||||
|
|
||||||
|
Sent at the end of a request for the current session.
|
||||||
|
|
||||||
|
The message object will contain one of these depending on if you use JWT or database persisted sessions:
|
||||||
|
|
||||||
|
- `token`: The JWT token for this session.
|
||||||
|
- `session`: The session object from your adapter.
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
---
|
||||||
|
id: initialization
|
||||||
|
title: Initialization
|
||||||
|
---
|
||||||
|
|
||||||
|
The main entry point of NextAuth.js is the `NextAuth` method that you import from `next-auth`. It handles different types of requests, as defined in the [REST API](/getting-started/rest-api.md) section.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
NextAuth.js cannot use the run [Edge Runtime](https://nextjs.org/docs/api-reference/edge-runtime) for initialization. The upcoming [`@auth/nextjs` library](https://authjs.dev/reference/next-auth) (which will replace `next-auth`) on the other hand will be fully compatible.
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can initialize NextAuth.js in a few different ways.
|
||||||
|
|
||||||
|
## Simple initialization
|
||||||
|
|
||||||
|
### API Routes (`pages`)
|
||||||
|
|
||||||
|
In Next.js, you can define an API route that will catch all requests that begin with a certain path. Conveniently, this is called [Catch all API routes](https://nextjs.org/docs/api-routes/dynamic-api-routes#catch-all-api-routes).
|
||||||
|
|
||||||
|
When you define a `/pages/api/auth/[...nextauth]` JS/TS file, you instruct NextAuth.js that every API request beginning with `/api/auth/*` should be handled by the code written in the `[...nextauth]` file.
|
||||||
|
|
||||||
|
```ts title="/pages/api/auth/[...nextauth].ts"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
export default NextAuth({
|
||||||
|
...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, you only need to pass your [options](/configuration/options) to `NextAuth`, and `NextAuth` does the rest.
|
||||||
|
|
||||||
|
This is the preferred initialization in tutorials/other parts of the documentation, as it simplifies the code and reduces potential errors in the authentication flow.
|
||||||
|
|
||||||
|
### Route Handlers (`app/`)
|
||||||
|
|
||||||
|
[Next.js 13.2](https://nextjs.org/blog/next-13-2#custom-route-handlers) introduced [Route Handlers](https://beta.nextjs.org/docs/routing/route-handlers), the preferred way to handle REST-like requests in App Router (`app/`).
|
||||||
|
|
||||||
|
You can initialize NextAuth.js with a Route Handler too, very similar to API Routes.
|
||||||
|
|
||||||
|
```ts title="/app/api/auth/[...nextauth]/route.ts"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
const handler = NextAuth({
|
||||||
|
...
|
||||||
|
})
|
||||||
|
|
||||||
|
export { handler as GET, handler as POST }
|
||||||
|
```
|
||||||
|
|
||||||
|
Internally, NextAuth.js detects that it is being initialized in a Route Handler (by understanding that it is passed a Web [`Request` instance](https://developer.mozilla.org/en-US/docs/Web/API/Request)), and will return a handler that returns a [`Response` instance](https://developer.mozilla.org/en-US/docs/Web/API/Response). A Route Handler file expects you to export some named handler functions that handle a request and return a response. NextAuth.js needs the `GET` and `POST` handlers to function properly, so we export those two.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
Technically, in a Route Handler, the `api/` prefix is not necessary, but we decided to keep it required for an easier migration.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Advanced initialization
|
||||||
|
|
||||||
|
:::info
|
||||||
|
The following describes the advanced initialization with API Routes, but everything will apply similarily when using [Route Handlers](https://beta.nextjs.org/docs/routing/route-handlers) too.
|
||||||
|
Instead, `NextAuth` will receive the first two arguments of a Route Handler, and the third argument will be the [auth options](/configuration/options)
|
||||||
|
:::
|
||||||
|
|
||||||
|
If you have a specific use case and need to make NextAuth.js do something slightly different than what it is designed for, keep in mind, the `[...nextauth].ts` config file is just **a regular [API Route](https://nextjs.org/docs/api-routes/introduction)**.
|
||||||
|
|
||||||
|
That said, you can initialize NextAuth.js like this:
|
||||||
|
|
||||||
|
```ts title="/pages/api/auth/[...nextauth].ts"
|
||||||
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
// Do whatever you want here, before the request is passed down to `NextAuth`
|
||||||
|
return await NextAuth(req, res, {
|
||||||
|
...
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `...` section will still be your [options](/configuration/options), but you now have the possibility to execute/modify certain things on the request.
|
||||||
|
|
||||||
|
You could for example log the request, add headers, read `query` or `body` parameters, whatever you would do in an API route.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Since this is a catch-all route, remember to check what kind of NextAuth.js "action" is running. Compare the REST API with the `req.query.nextauth` parameter.
|
||||||
|
|
||||||
|
For example to execute something on the "callback" action when the request is a POST method, you can check for `req.query.nextauth.includes("callback") && req.method === "POST"`
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
`NextAuth` will implicitly close the response (by calling `res.end`, `res.send` or similar), so you should not run code **after** `NextAuth` in the function body. Using `return NextAuth` makes sure you don't forget that.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Any variable you create this way will be available in the `NextAuth` options as well, since they are in the same scope.
|
||||||
|
|
||||||
|
```ts title="/pages/api/auth/[...nextauth].ts"
|
||||||
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
|
||||||
|
if(req.query.nextauth.includes("callback") && req.method === "POST") {
|
||||||
|
console.log(
|
||||||
|
"Handling callback request from my Identity Provider",
|
||||||
|
req.body
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a custom cookie value from the request
|
||||||
|
const someCookie = req.cookies["some-custom-cookie"]
|
||||||
|
|
||||||
|
return await NextAuth(req, res, {
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
session({ session, token }) {
|
||||||
|
// Return a cookie value as part of the session
|
||||||
|
// This is read when `req.query.nextauth.includes("session") && req.method === "GET"`
|
||||||
|
session.someCookie = someCookie
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A practical example could be to not show a certain provider on the default sign-in page, but still be able to sign in with it. (The idea is taken from [this discussion](https://github.com/nextauthjs/next-auth/discussions/3133)):
|
||||||
|
|
||||||
|
```js title="/pages/api/auth/[...nextauth].ts"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
import CredentialsProvider from "next-auth/providers/credentials"
|
||||||
|
import GoogleProvider from "next-auth/providers/google"
|
||||||
|
|
||||||
|
export default async function auth(req, res) {
|
||||||
|
const providers = [
|
||||||
|
CredentialsProvider(...),
|
||||||
|
GoogleProvider(...),
|
||||||
|
]
|
||||||
|
|
||||||
|
const isDefaultSigninPage = req.method === "GET" && req.query.nextauth.includes("signin")
|
||||||
|
|
||||||
|
// Will hide the `GoogleProvider` when you visit `/api/auth/signin`
|
||||||
|
if (isDefaultSigninPage) providers.pop()
|
||||||
|
|
||||||
|
return await NextAuth(req, res, {
|
||||||
|
providers,
|
||||||
|
...
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details on all available actions and which methods are supported, please check out the [REST API documentation](/getting-started/rest-api) or the appropriate area in [the source code](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/index.ts)
|
||||||
|
|
||||||
|
This way of initializing `NextAuth` is very powerful, but should be used sparingly.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Changing parts of the request that is essential to `NextAuth` to do its job - like messing with the [default cookies](/configuration/options#cookies) - can have unforeseen consequences, and have the potential to introduce security holes if done incorrectly. Only change those if you understand consequences.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
# Next.js
|
||||||
|
|
||||||
|
## `getServerSession`
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
You can create a helper function so you don't need to pass `authOptions` around:
|
||||||
|
|
||||||
|
```ts title=auth.ts
|
||||||
|
import type {
|
||||||
|
GetServerSidePropsContext,
|
||||||
|
NextApiRequest,
|
||||||
|
NextApiResponse,
|
||||||
|
} from "next"
|
||||||
|
import type { NextAuthOptions } from "next-auth"
|
||||||
|
import { getServerSession } from "next-auth"
|
||||||
|
|
||||||
|
// You'll need to import and pass this
|
||||||
|
// to `NextAuth` in `app/api/auth/[...nextauth]/route.ts`
|
||||||
|
export const config = {
|
||||||
|
providers: [], // rest of your config
|
||||||
|
} satisfies NextAuthOptions
|
||||||
|
|
||||||
|
// Use it in server contexts
|
||||||
|
export function auth(
|
||||||
|
...args:
|
||||||
|
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]]
|
||||||
|
| [NextApiRequest, NextApiResponse]
|
||||||
|
| []
|
||||||
|
) {
|
||||||
|
return getServerSession(...args, config)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
When calling from the server-side i.e. in Route Handlers, React Server Components, API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` on server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
|
||||||
|
|
||||||
|
`getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way:
|
||||||
|
|
||||||
|
In `[...nextauth].ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
import type { NextAuthOptions } from "next-auth"
|
||||||
|
|
||||||
|
export const authOptions: NextAuthOptions = {
|
||||||
|
// your configs
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NextAuth(authOptions)
|
||||||
|
```
|
||||||
|
|
||||||
|
### In `getServerSideProps`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { authOptions } from "pages/api/auth/[...nextauth]"
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
const session = await getServerSession(context.req, context.res, authOptions)
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: "/",
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
session,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### In API Routes:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { authOptions } from "pages/api/auth/[...nextauth]"
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
const session = await getServerSession(req, res, authOptions)
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
res.status(401).json({ message: "You must be logged in." })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
message: "Success",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### In App Router:
|
||||||
|
|
||||||
|
You can also use `getServerSession` in Next.js' server components:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
import { authOptions } from "pages/api/auth/[...nextauth]"
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
const session = await getServerSession(authOptions)
|
||||||
|
return <pre>{JSON.stringify(session, null, 2)}</pre>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::info
|
||||||
|
In contrast to `useSession`, which will return a `session` object whether or not a user has logged in (whether or not cookies are present), `getServerSession` only returns a `session` object when a user has logged in (only when authenticated cookies are present), otherwise, it returns `null`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Currently, the underlying Next.js `cookies()` method [only provides read access](https://beta.nextjs.org/docs/api-reference/cookies) to the request cookies. This means that the `expires` value is stripped away from `session` in Server Components. Furthermore, there is a hard expiry on sessions, after which the user will be required to sign in again. (The default expiry is 30 days).
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Caching
|
||||||
|
|
||||||
|
Note that using this function implies personalized data and that you should not store pages or APIs using this in a [public cache](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control). For example a host like [Vercel](https://vercel.com/docs/concepts/functions/serverless-functions/edge-caching) will implicitly prevent you from caching publicly due to the `set-cookie` header set by this function.
|
||||||
|
|
||||||
|
## `unstable_getServerSession`
|
||||||
|
|
||||||
|
This method was renamed to `getServerSession`. See the documentation above.
|
||||||
|
|
||||||
|
## Middleware
|
||||||
|
|
||||||
|
You can use a Next.js Middleware with NextAuth.js to protect your site.
|
||||||
|
|
||||||
|
Next.js 12 has introduced [Middleware](https://nextjs.org/docs/middleware). It is a way to run logic before accessing any page, even when they are static. On platforms like Vercel, Middleware is run at the [Edge](https://nextjs.org/docs/api-reference/edge-runtime).
|
||||||
|
|
||||||
|
If the following options look familiar, this is because they are a subset of [these options](/configuration/options#options). You can extract these to a common configuration object to reuse them. In the future, we would like to be able to run everything in Middleware. (See [Caveats](#caveats)).
|
||||||
|
|
||||||
|
You can get the `withAuth` middleware function from `next-auth/middleware` either as a default or a named import:
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
You must set the same secret in the middleware that you use in NextAuth. The easiest way is to set the [`NEXTAUTH_SECRET`](/configuration/options#nextauth_secret) environment variable. It will be picked up by both the [NextAuth config](/configuration/options#options), as well as the middleware config.
|
||||||
|
|
||||||
|
Alternatively, you can provide the secret using the [`secret`](#secret) option in the middleware config.
|
||||||
|
|
||||||
|
**We strongly recommend** replacing the `secret` value completely with this `NEXTAUTH_SECRET` environment variable.
|
||||||
|
|
||||||
|
### Basic usage
|
||||||
|
|
||||||
|
The most simple usage is when you want to require authentication for your entire site. You can add a `middleware.js` file with the following:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export { default } from "next-auth/middleware"
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! Your application is now secured. 🎉
|
||||||
|
|
||||||
|
If you only want to secure certain pages, export a `config` object with a `matcher`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export { default } from "next-auth/middleware"
|
||||||
|
|
||||||
|
export const config = { matcher: ["/dashboard"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you will still be able to visit every page, but only `/dashboard` will require authentication.
|
||||||
|
|
||||||
|
If a user is not logged in, the default behavior is to redirect them to the sign-in page.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `callbacks`
|
||||||
|
|
||||||
|
- **Required:** No
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Callbacks are asynchronous functions you can use to control what happens when an action is performed.
|
||||||
|
|
||||||
|
#### Example (default value)
|
||||||
|
|
||||||
|
```js
|
||||||
|
callbacks: {
|
||||||
|
authorized({ req , token }) {
|
||||||
|
if(token) return true // If there is a token, the user is authenticated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `pages`
|
||||||
|
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Specify URLs to be used if you want to create custom sign-in and error pages. The pages specified will override the corresponding built-in page.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
The `pages` configuration should match the same configuration in `[...nextauth].ts`. This is so that the `next-auth` Middleware is aware of your custom pages, so it won't end up redirecting to itself when an unauthenticated condition is met.
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Example (default value)
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { withAuth } from "next-auth/middleware"
|
||||||
|
|
||||||
|
export default withAuth({
|
||||||
|
// Matches the pages config in `[...nextauth]`
|
||||||
|
pages: {
|
||||||
|
signIn: "/login",
|
||||||
|
error: "/error",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information, see the documentation for the [pages option](/configuration/pages).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `secret`
|
||||||
|
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
The same `secret` is used in the [NextAuth.js config](/configuration/options#options).
|
||||||
|
|
||||||
|
#### Example (default value)
|
||||||
|
|
||||||
|
```js
|
||||||
|
secret: process.env.NEXTAUTH_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Advanced usage
|
||||||
|
|
||||||
|
NextAuth.js Middleware is very flexible, there are multiple ways to use it.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you do not define the options, NextAuth.js will use the default values for the omitted options.
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### wrap middleware
|
||||||
|
|
||||||
|
```ts title="middleware.ts"
|
||||||
|
import { withAuth } from "next-auth/middleware"
|
||||||
|
|
||||||
|
export default withAuth(
|
||||||
|
// `withAuth` augments your `Request` with the user's token.
|
||||||
|
function middleware(req) {
|
||||||
|
console.log(req.nextauth.token)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
callbacks: {
|
||||||
|
authorized: ({ token }) => token?.role === "admin",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
export const config = { matcher: ["/admin"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
The `middleware` function will only be invoked if the `authorized` callback returns `true`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Custom JWT decode method
|
||||||
|
|
||||||
|
If you have a custom jwt decode method set in `[...nextauth].ts`, you must also pass the same `decode` method to `withAuth` in order to read the custom-signed JWT correctly. You may want to extract the encode/decode logic to a separate function for consistency.
|
||||||
|
|
||||||
|
```ts title="/api/auth/[...nextauth].ts"
|
||||||
|
import type { NextAuthOptions } from "next-auth"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
import jwt from "jsonwebtoken"
|
||||||
|
|
||||||
|
export const authOptions: NextAuthOptions = {
|
||||||
|
providers: [...],
|
||||||
|
jwt: {
|
||||||
|
async encode({ secret, token }) {
|
||||||
|
return jwt.sign(token, secret)
|
||||||
|
},
|
||||||
|
async decode({ secret, token }) {
|
||||||
|
return jwt.verify(token, secret)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NextAuth(authOptions)
|
||||||
|
```
|
||||||
|
|
||||||
|
And:
|
||||||
|
|
||||||
|
```ts title="middleware.ts"
|
||||||
|
import withAuth from "next-auth/middleware"
|
||||||
|
import { authOptions } from "pages/api/auth/[...nextauth]"
|
||||||
|
|
||||||
|
export default withAuth({
|
||||||
|
jwt: { decode: authOptions.jwt?.decode },
|
||||||
|
callbacks: {
|
||||||
|
authorized: ({ token }) => !!token,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Caveats
|
||||||
|
|
||||||
|
- Currently only supports session verification, as parts of the sign-in code need to run in a Node.js environment. In the future, we would like to make sure that NextAuth.js can fully run at the [Edge](https://nextjs.org/docs/api-reference/edge-runtime)
|
||||||
|
- Only supports the `"jwt"` [session strategy](/configuration/options#session). We need to wait until databases at the Edge become mature enough to ensure a fast experience. (If you know of an Edge-compatible database, we would like if you proposed a new [Adapter](https://authjs.dev/guides/creating-a-database-adapter))
|
||||||
@@ -0,0 +1,538 @@
|
|||||||
|
---
|
||||||
|
id: options
|
||||||
|
title: Options
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
### NEXTAUTH_URL
|
||||||
|
|
||||||
|
When deploying to production, set the `NEXTAUTH_URL` environment variable to the canonical URL of your site.
|
||||||
|
|
||||||
|
```
|
||||||
|
NEXTAUTH_URL=https://example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
If your Next.js application uses a custom base path, specify the route to the API endpoint in full. More information about the usage of custom base path [here](/getting-started/client#custom-base-path).
|
||||||
|
|
||||||
|
_e.g. `NEXTAUTH_URL=https://example.com/custom-route/api/auth`_
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
When you're using a custom base path, you will need to pass the `basePath` page prop to the `<SessionProvider>`. More information [here](/getting-started/client#custom-base-path).
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Using [System Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) we automatically detect when you deploy to [Vercel](https://vercel.com) so you don't have to define this variable. Make sure **Automatically expose System Environment Variables** is checked in your Project Settings.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### NEXTAUTH_SECRET
|
||||||
|
|
||||||
|
Used to encrypt the NextAuth.js JWT, and to hash [email verification tokens](https://authjs.dev/guides/creating-a-database-adapter#verification-tokens). This is the default value for the `secret` option in [NextAuth](/configuration/options#secret) and [Middleware](/configuration/nextjs#secret). Alternatively, you can also set `AUTH_SECRET`, which is an alias, and is the preferred naming going forward.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
You can run `npx auth secret` - our [CLI](https://cli.authjs.dev) - in your project's root, and it will autogenerate a random value and put it in your `.env.local` file.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### NEXTAUTH_URL_INTERNAL
|
||||||
|
|
||||||
|
If provided, server-side calls will use this instead of `NEXTAUTH_URL`. Useful in environments when the server doesn't have access to the canonical URL of your site. Defaults to `NEXTAUTH_URL`.
|
||||||
|
|
||||||
|
```
|
||||||
|
NEXTAUTH_URL_INTERNAL=http://10.240.8.16
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
Options are passed to NextAuth.js when initializing it in an API route.
|
||||||
|
|
||||||
|
### providers
|
||||||
|
|
||||||
|
- **Default value**: `[]`
|
||||||
|
- **Required**: _Yes_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
An array of authentication providers for signing in (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order. This can be one of the built-in providers or an object with a custom provider.
|
||||||
|
|
||||||
|
See the [providers documentation](/configuration/providers/oauth) for a list of supported providers and how to use them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### secret
|
||||||
|
|
||||||
|
- **Default value**: `string` (_SHA hash of the "options" object_) in development, no default in production.
|
||||||
|
- **Required**: _Yes, in production!_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
A random string is used to hash tokens, sign/encrypt cookies and generate cryptographic keys.
|
||||||
|
|
||||||
|
If you set [`NEXTAUTH_SECRET`](#nextauth_secret) as an environment variable, you don't have to define this option.
|
||||||
|
|
||||||
|
If no value is specified in development (and there is no `NEXTAUTH_SECRET` variable either), it uses a hash for all configuration options, including OAuth Client ID / Secrets for entropy.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Not providing any `secret` or `NEXTAUTH_SECRET` will throw [an error](/errors#no_secret) in production.
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can quickly create a good value on the command line via this `openssl` command.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If you rely on the default secret generation in development, you might notice JWT decryption errors, since the secret changes whenever you change your configuration. Defining an explicit secret will make this problem go away. We will likely make this option mandatory, even in development, in the future.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### session
|
||||||
|
|
||||||
|
- **Default value**: `object`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
The `session` object and all properties on it are optional.
|
||||||
|
|
||||||
|
Default values for this option are shown below:
|
||||||
|
|
||||||
|
```js
|
||||||
|
session: {
|
||||||
|
// Choose how you want to save the user session.
|
||||||
|
// The default is `"jwt"`, an encrypted JWT (JWE) stored in the session cookie.
|
||||||
|
// If you use an `adapter` however, we default it to `"database"` instead.
|
||||||
|
// You can still force a JWT session by explicitly defining `"jwt"`.
|
||||||
|
// When using `"database"`, the session cookie will only contain a `sessionToken` value,
|
||||||
|
// which is used to look up the session in the database.
|
||||||
|
strategy: "database",
|
||||||
|
|
||||||
|
// Seconds - How long until an idle session expires and is no longer valid.
|
||||||
|
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||||||
|
|
||||||
|
// Seconds - Throttle how frequently to write to database to extend a session.
|
||||||
|
// Use it to limit write operations. Set to 0 to always update the database.
|
||||||
|
// Note: This option is ignored if using JSON Web Tokens
|
||||||
|
updateAge: 24 * 60 * 60, // 24 hours
|
||||||
|
|
||||||
|
// The session token is usually either a random UUID or string, however if you
|
||||||
|
// need a more customized session token string, you can define your own generate function.
|
||||||
|
generateSessionToken: () => {
|
||||||
|
return randomUUID?.() ?? randomBytes(32).toString("hex")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### jwt
|
||||||
|
|
||||||
|
- **Default value**: `object`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
JSON Web Tokens can be used for session tokens if enabled with `session: { strategy: "jwt" }` option. JSON Web Tokens are enabled by default if you have not specified an adapter. JSON Web Tokens are encrypted (JWE) by default. We recommend you keep this behaviour. See the [Override JWT `encode` and `decode` methods](#override-jwt-encode-and-decode-methods) advanced option.
|
||||||
|
|
||||||
|
#### JSON Web Token Options
|
||||||
|
|
||||||
|
```js
|
||||||
|
jwt: {
|
||||||
|
// The maximum age of the NextAuth.js issued JWT in seconds.
|
||||||
|
// Defaults to `session.maxAge`.
|
||||||
|
maxAge: 60 * 60 * 24 * 30,
|
||||||
|
// You can define your own encode/decode functions for signing and encryption
|
||||||
|
async encode() {},
|
||||||
|
async decode() {},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
An example JSON Web Token contains a payload like this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
name: 'Iain Collins',
|
||||||
|
email: 'me@iaincollins.com',
|
||||||
|
picture: 'https://example.com/image.jpg',
|
||||||
|
iat: 1594601838,
|
||||||
|
exp: 1597193838
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### JWT Helper
|
||||||
|
|
||||||
|
You can use the built-in `getToken()` helper method to verify and decrypt the token, like this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { getToken } from "next-auth/jwt"
|
||||||
|
|
||||||
|
const secret = process.env.NEXTAUTH_SECRET
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
// if using `NEXTAUTH_SECRET` env variable, we detect it, and you won't actually need to `secret`
|
||||||
|
// const token = await getToken({ req })
|
||||||
|
const token = await getToken({ req, secret })
|
||||||
|
console.log("JSON Web Token", token)
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
_For convenience, this helper function is also able to read and decode tokens passed from the `Authorization: 'Bearer token'` HTTP header._
|
||||||
|
|
||||||
|
**Required**
|
||||||
|
|
||||||
|
The getToken() helper requires the following options:
|
||||||
|
|
||||||
|
- `req` - (object) Request object
|
||||||
|
- `secret` - (string) JWT Secret. Use `NEXTAUTH_SECRET` instead.
|
||||||
|
|
||||||
|
You must also pass _any options configured on the `jwt` option_ to the helper.
|
||||||
|
|
||||||
|
e.g. Including custom session `maxAge` and custom signing and/or encryption keys or options
|
||||||
|
|
||||||
|
**Optional**
|
||||||
|
|
||||||
|
It also supports the following options:
|
||||||
|
|
||||||
|
- `secureCookie` - (boolean) Use secure prefixed cookie name
|
||||||
|
|
||||||
|
By default, the helper function will attempt to determine if it should use the secure prefixed cookie (e.g. `true` in production and `false` in development, unless NEXTAUTH_URL contains an HTTPS URL).
|
||||||
|
|
||||||
|
- `cookieName` - (string) Session token cookie name
|
||||||
|
|
||||||
|
The `secureCookie` option is ignored if `cookieName` is explicitly specified.
|
||||||
|
|
||||||
|
- `raw` - (boolean) Get raw token (not decoded)
|
||||||
|
|
||||||
|
If set to `true` returns the raw token without decrypting or verifying it.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
When using a custom session token `cookieName`, the same name should also be provided to `getToken`. If you are using the Next.js [`withAuth`](/configuration/nextjs#middleware) middleware, you will also need to configure this using the same `cookieName`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The JWT is stored in the Session Token cookie, the same cookie used for tokens with database sessions.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### pages
|
||||||
|
|
||||||
|
- **Default value**: `{}`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Specify URLs to be used if you want to create custom sign in, sign out and error pages.
|
||||||
|
|
||||||
|
Pages specified will override the corresponding built-in page.
|
||||||
|
|
||||||
|
_For example:_
|
||||||
|
|
||||||
|
```js
|
||||||
|
pages: {
|
||||||
|
signIn: '/auth/signin',
|
||||||
|
signOut: '/auth/signout',
|
||||||
|
error: '/auth/error', // Error code passed in query string as ?error=
|
||||||
|
verifyRequest: '/auth/verify-request', // (used for check email message)
|
||||||
|
newUser: '/auth/new-user' // New users will be directed here on first sign in (leave the property out if not of interest)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
When using this configuration, ensure that these pages actually exist. For example `error: '/auth/error'` refers to a page file at `pages/auth/error.js`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
See the documentation for the [pages option](/configuration/pages) for more information.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### callbacks
|
||||||
|
|
||||||
|
- **Default value**: `object`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Callbacks are asynchronous functions you can use to control what happens when an action is performed.
|
||||||
|
|
||||||
|
Callbacks are extremely powerful, especially in scenarios involving JSON Web Tokens as they allow you to implement access controls without a database and to integrate with external databases or APIs.
|
||||||
|
|
||||||
|
You can specify a handler for any of the callbacks below.
|
||||||
|
|
||||||
|
```js
|
||||||
|
callbacks: {
|
||||||
|
async signIn({ user, account, profile, email, credentials }) {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
async redirect({ url, baseUrl }) {
|
||||||
|
return baseUrl
|
||||||
|
},
|
||||||
|
async session({ session, token, user }) {
|
||||||
|
return session
|
||||||
|
},
|
||||||
|
async jwt({ token, user, account, profile, isNewUser }) {
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [callbacks documentation](/configuration/callbacks) for more information on how to use the callback functions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### events
|
||||||
|
|
||||||
|
- **Default value**: `object`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Events are asynchronous functions that do not return a response, they are useful for audit logging.
|
||||||
|
|
||||||
|
You can specify a handler for any of these events below - e.g. for debugging or to create an audit log.
|
||||||
|
|
||||||
|
The content of the message object varies depending on the flow (e.g. OAuth or Email authentication flow, JWT or database sessions, etc). See the [events documentation](/configuration/events) for more information on the form of each message object and how to use the events functions.
|
||||||
|
|
||||||
|
```js
|
||||||
|
events: {
|
||||||
|
async signIn(message) { /* on successful sign in */ },
|
||||||
|
async signOut(message) { /* on signout */ },
|
||||||
|
async createUser(message) { /* user created */ },
|
||||||
|
async updateUser(message) { /* user updated - e.g. their email was verified */ },
|
||||||
|
async linkAccount(message) { /* account (e.g. Twitter) linked to a user */ },
|
||||||
|
async session(message) { /* session is active */ },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### adapter
|
||||||
|
|
||||||
|
- **Default value**: none
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
By default NextAuth.js does not include an adapter any longer. If you would like to persist user / account data, please install one of the many available adapters. More information can be found in the [adapter documentation](https://authjs.dev/getting-started/database).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### debug
|
||||||
|
|
||||||
|
- **Default value**: `false`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Set debug to `true` to enable debug messages for authentication and database operations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### logger
|
||||||
|
|
||||||
|
- **Default value**: `console`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Override any of the logger levels (`undefined` levels will use the built-in logger), and intercept logs in NextAuth.js. You can use this to send NextAuth.js logs to a third-party logging service.
|
||||||
|
|
||||||
|
The `code` parameter for `error` and `warn` are explained in the [Warnings](/warnings) and [Errors](/errors) pages respectively.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js title="/pages/api/auth/[...nextauth].js"
|
||||||
|
import log from "logging-service"
|
||||||
|
|
||||||
|
export default NextAuth({
|
||||||
|
...
|
||||||
|
logger: {
|
||||||
|
error(code, metadata) {
|
||||||
|
log.error(code, metadata)
|
||||||
|
},
|
||||||
|
warn(code) {
|
||||||
|
log.warn(code)
|
||||||
|
},
|
||||||
|
debug(code, metadata) {
|
||||||
|
log.debug(code, metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If the `debug` level is defined by the user, it will be called regardless of the `debug: false` [option](#debug).
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### theme
|
||||||
|
|
||||||
|
- **Default value**: `object`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Changes the color scheme theme of [pages](/configuration/pages) as well as allows some minor customization. Set `theme.colorScheme` to `"light"`, if you want to force pages to always be light. Set to `"dark"`, if you want to force pages to always be dark. Set to `"auto"`, (or leave this option out) if you want the pages to follow the preferred system theme. (Uses the [prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media query.)
|
||||||
|
|
||||||
|
In addition, you can define a logo URL in `theme.logo` which will be rendered above the main card in the default signin/signout/error/verify-request pages, as well as a `theme.brandColor` which will affect the accent color of these pages.
|
||||||
|
|
||||||
|
The sign-in button's background color will match the `brandColor` and defaults to `"#346df1"`. The text color is `#fff` by default, but if your brand color gives a weak contrast, correct it with the `buttonText` color option.
|
||||||
|
|
||||||
|
```js
|
||||||
|
theme: {
|
||||||
|
colorScheme: "auto", // "auto" | "dark" | "light"
|
||||||
|
brandColor: "", // Hex color code
|
||||||
|
logo: "", // Absolute URL to image
|
||||||
|
buttonText: "" // Hex color code
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Advanced Options
|
||||||
|
|
||||||
|
Advanced options are passed the same way as basic options, but may have complex implications or side effects. You should try to avoid using advanced options unless you are very comfortable using them.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### useSecureCookies
|
||||||
|
|
||||||
|
- **Default value**: `true` for HTTPS sites / `false` for HTTP sites
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
When set to `true` (the default for all site URLs that start with `https://`) then all cookies set by NextAuth.js will only be accessible from HTTPS URLs.
|
||||||
|
|
||||||
|
This option defaults to `false` on URLs that start with `http://` (e.g. `http://localhost:3000`) for developer convenience.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Properties on any custom `cookies` that are specified override this option.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Setting this option to _false_ in production is a security risk and may allow sessions to be hijacked if used in production. It is intended to support development and testing. Using this option is not recommended.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### cookies
|
||||||
|
|
||||||
|
- **Default value**: `{}`
|
||||||
|
- **Required**: _No_
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
Cookies in NextAuth.js are chunked by default, meaning that once they reach the 4kb limit, we will create a new cookie with the `.{number}` suffix and reassemble the cookies in the correct order when parsing / reading them. This was introduced to avoid size constraints which can occur when users want to store additional data in their sessionToken, for example.
|
||||||
|
|
||||||
|
You can override the default cookie names and options for any of the cookies used by NextAuth.js.
|
||||||
|
|
||||||
|
This is an advanced option and using it is not recommended as you may break authentication or introduce security flaws into your application.
|
||||||
|
|
||||||
|
You can specify one or more cookies with custom properties, but if you specify custom options for a cookie you must provide all the options for that cookie.
|
||||||
|
|
||||||
|
If you use this feature, you will likely want to create conditional behaviour to support setting different cookies policies in development and production builds, as you will be opting out of the built-in dynamic policy.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
An example of a use case for this option is to support sharing session tokens across subdomains.
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
cookies: {
|
||||||
|
sessionToken: {
|
||||||
|
name: `__Secure-next-auth.session-token`,
|
||||||
|
options: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: 'lax',
|
||||||
|
path: '/',
|
||||||
|
secure: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callbackUrl: {
|
||||||
|
name: `__Secure-next-auth.callback-url`,
|
||||||
|
options: {
|
||||||
|
sameSite: 'lax',
|
||||||
|
path: '/',
|
||||||
|
secure: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
csrfToken: {
|
||||||
|
name: `__Host-next-auth.csrf-token`,
|
||||||
|
options: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: 'lax',
|
||||||
|
path: '/',
|
||||||
|
secure: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pkceCodeVerifier: {
|
||||||
|
name: `${cookiePrefix}next-auth.pkce.code_verifier`,
|
||||||
|
options: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: 'lax',
|
||||||
|
path: '/',
|
||||||
|
secure: true,
|
||||||
|
maxAge: 900
|
||||||
|
}
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
name: `${cookiePrefix}next-auth.state`,
|
||||||
|
options: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: "lax",
|
||||||
|
path: "/",
|
||||||
|
secure: true,
|
||||||
|
maxAge: 900
|
||||||
|
},
|
||||||
|
},
|
||||||
|
nonce: {
|
||||||
|
name: `${cookiePrefix}next-auth.nonce`,
|
||||||
|
options: {
|
||||||
|
httpOnly: true,
|
||||||
|
sameSite: "lax",
|
||||||
|
path: "/",
|
||||||
|
secure: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Using a custom cookie policy may introduce security flaws into your application and is intended as an option for advanced users who understand the implications. Using this option is not recommended.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Override JWT `encode` and `decode` methods
|
||||||
|
|
||||||
|
NextAuth.js uses encrypted JSON Web Tokens ([JWE](https://datatracker.ietf.org/doc/html/rfc7516)) by default. Unless you have a good reason, we recommend keeping this behaviour. Although you can override this using the `encode` and `decode` methods. Both methods must be defined at the same time.
|
||||||
|
|
||||||
|
**IMPORTANT: If you use middleware to protect routes, make sure the same method is also set in the [`_middleware.ts` options](/configuration/nextjs#custom-jwt-decode-method)**
|
||||||
|
|
||||||
|
```js
|
||||||
|
jwt: {
|
||||||
|
async encode(params: {
|
||||||
|
token: JWT
|
||||||
|
secret: string
|
||||||
|
maxAge: number
|
||||||
|
}): Promise<string> {
|
||||||
|
// return a custom encoded JWT string
|
||||||
|
return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
|
||||||
|
},
|
||||||
|
async decode(params: {
|
||||||
|
token: string
|
||||||
|
secret: string
|
||||||
|
}): Promise<JWT | null> {
|
||||||
|
// return a `JWT` object, or `null` if decoding failed
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
---
|
||||||
|
id: pages
|
||||||
|
title: Pages
|
||||||
|
---
|
||||||
|
|
||||||
|
NextAuth.js automatically creates simple, unbranded authentication pages for handling Sign in, Sign out, Email Verification and displaying error messages.
|
||||||
|
|
||||||
|
The options displayed on the sign-up page are automatically generated based on the providers specified in the options passed to NextAuth.js.
|
||||||
|
|
||||||
|
To add a custom login page, you can use the `pages` option:
|
||||||
|
|
||||||
|
```javascript title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
pages: {
|
||||||
|
signIn: '/auth/signin',
|
||||||
|
signOut: '/auth/signout',
|
||||||
|
error: '/auth/error', // Error code passed in query string as ?error=
|
||||||
|
verifyRequest: '/auth/verify-request', // (used for check email message)
|
||||||
|
newUser: '/auth/new-user' // New users will be directed here on first sign in (leave the property out if not of interest)
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
When using this configuration, ensure that these pages actually exist. For example `error: '/auth/error'` refers to a page file at `pages/auth/error.js`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Error codes
|
||||||
|
|
||||||
|
We purposefully restrict the returned error codes for increased security.
|
||||||
|
|
||||||
|
### Error page
|
||||||
|
|
||||||
|
The following errors are passed as error query parameters to the default or overridden error page:
|
||||||
|
|
||||||
|
- **Configuration**: There is a problem with the server configuration. Check if your [options](/configuration/options#options) are correct.
|
||||||
|
- **AccessDenied**: Usually occurs, when you restricted access through the [`signIn` callback](/configuration/callbacks#sign-in-callback), or [`redirect` callback](/configuration/callbacks#redirect-callback)
|
||||||
|
- **Verification**: Related to the Email provider. The token has expired or has already been used
|
||||||
|
- **Default**: Catch all, will apply, if none of the above matched
|
||||||
|
|
||||||
|
Example: `/auth/error?error=Configuration`
|
||||||
|
|
||||||
|
### Sign-in page
|
||||||
|
|
||||||
|
The following errors are passed as error query parameters to the default or overridden sign-in page:
|
||||||
|
|
||||||
|
- **OAuthSignin**: Error in constructing an authorization URL ([1](https://github.com/nextauthjs/next-auth/blob/457952bb5abf08b09861b0e5da403080cd5525be/src/server/lib/signin/oauth.js), [2](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/lib/oauth/pkce-handler.ts), [3](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/lib/oauth/state-handler.ts)),
|
||||||
|
- **OAuthCallback**: Error in handling the response ([1](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/lib/oauth/callback.ts), [2](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/lib/oauth/pkce-handler.ts), [3](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/lib/oauth/state-handler.ts)) from an OAuth provider.
|
||||||
|
- **OAuthCreateAccount**: Could not create OAuth provider user in the database.
|
||||||
|
- **EmailCreateAccount**: Could not create email provider user in the database.
|
||||||
|
- **Callback**: Error in the [OAuth callback handler route](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/routes/callback.ts)
|
||||||
|
- **OAuthAccountNotLinked**: If the email on the account is already linked, but not with this OAuth account
|
||||||
|
- **EmailSignin**: Sending the e-mail with the verification token failed
|
||||||
|
- **CredentialsSignin**: The `authorize` callback returned `null` in the [Credentials provider](/providers/credentials). We don't recommend providing information about which part of the credentials were wrong, as it might be abused by malicious hackers.
|
||||||
|
- **SessionRequired**: The content of this page requires you to be signed in at all times. See [useSession](/getting-started/client#require-session) for configuration.
|
||||||
|
- **Default**: Catch all, will apply, if none of the above matched
|
||||||
|
|
||||||
|
Example: `/auth/signin?error=Default`
|
||||||
|
|
||||||
|
## Theming
|
||||||
|
|
||||||
|
By default, the built-in pages will follow the system theme, utilizing the [`prefer-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) Media Query. You can override this to always use a dark or light theme, through the [`theme.colorScheme` option](/configuration/options#theme).
|
||||||
|
|
||||||
|
In addition, you can define a `theme.brandColor` to define a custom accent color for these built-in pages. You can also define a URL to a logo in `theme.logo` which will be rendered above the primary card in these pages.
|
||||||
|
|
||||||
|
#### Sign In
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### Sign Out
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### OAuth Sign in
|
||||||
|
|
||||||
|
In order to get the available authentication providers and the URLs to use for them, you can make a request to the API endpoint `/api/auth/providers`:
|
||||||
|
|
||||||
|
```tsx title="pages/auth/signin.tsx"
|
||||||
|
import type {
|
||||||
|
GetServerSidePropsContext,
|
||||||
|
InferGetServerSidePropsType,
|
||||||
|
} from "next"
|
||||||
|
import { getProviders, signIn } from "next-auth/react"
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
import { authOptions } from "../api/auth/[...nextauth]"
|
||||||
|
|
||||||
|
export default function SignIn({
|
||||||
|
providers,
|
||||||
|
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{Object.values(providers).map((provider) => (
|
||||||
|
<div key={provider.name}>
|
||||||
|
<button onClick={() => signIn(provider.id)}>
|
||||||
|
Sign in with {provider.name}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
|
const session = await getServerSession(context.req, context.res, authOptions)
|
||||||
|
|
||||||
|
// If the user is already logged in, redirect.
|
||||||
|
// Note: Make sure not to redirect to the same page
|
||||||
|
// To avoid an infinite loop!
|
||||||
|
if (session) {
|
||||||
|
return { redirect: { destination: "/" } }
|
||||||
|
}
|
||||||
|
|
||||||
|
const providers = await getProviders()
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: { providers: providers ?? [] },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
There is another, more fully styled example signin page available [here](https://github.com/ndom91/next-auth-example-sign-in-page).
|
||||||
|
|
||||||
|
### Email Sign in
|
||||||
|
|
||||||
|
If you create a custom sign in form for email sign in, you will need to submit both fields for the **email** address and **csrfToken** from **/api/auth/csrf** in a POST request to **/api/auth/signin/email**.
|
||||||
|
|
||||||
|
```tsx title="pages/auth/email-signin.tsx"
|
||||||
|
import type {
|
||||||
|
GetServerSidePropsContext,
|
||||||
|
InferGetServerSidePropsType,
|
||||||
|
} from "next"
|
||||||
|
import { getCsrfToken } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function SignIn({
|
||||||
|
csrfToken,
|
||||||
|
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
|
return (
|
||||||
|
<form method="post" action="/api/auth/signin/email">
|
||||||
|
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
|
||||||
|
<label>
|
||||||
|
Email address
|
||||||
|
<input type="email" id="email" name="email" />
|
||||||
|
</label>
|
||||||
|
<button type="submit">Sign in with Email</button>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
|
const csrfToken = await getCsrfToken(context)
|
||||||
|
return {
|
||||||
|
props: { csrfToken },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the `signIn()` function which will handle obtaining the CSRF token for you:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
signIn("email", { email: "jsmith@example.com" })
|
||||||
|
```
|
||||||
|
|
||||||
|
### Credentials Sign in
|
||||||
|
|
||||||
|
If you create a sign in form for credentials based authentication, you will need to pass a **csrfToken** from **/api/auth/csrf** in a POST request to **/api/auth/callback/credentials**.
|
||||||
|
|
||||||
|
```tsx title="pages/auth/credentials-signin.tsx"
|
||||||
|
import type {
|
||||||
|
GetServerSidePropsContext,
|
||||||
|
InferGetServerSidePropsType,
|
||||||
|
} from "next"
|
||||||
|
import { getCsrfToken } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function SignIn({
|
||||||
|
csrfToken,
|
||||||
|
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
|
return (
|
||||||
|
<form method="post" action="/api/auth/callback/credentials">
|
||||||
|
<input name="csrfToken" type="hidden" defaultValue={csrfToken} />
|
||||||
|
<label>
|
||||||
|
Username
|
||||||
|
<input name="username" type="text" />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Password
|
||||||
|
<input name="password" type="password" />
|
||||||
|
</label>
|
||||||
|
<button type="submit">Sign in</button>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
csrfToken: await getCsrfToken(context),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the `signIn()` function which will handle obtaining the CSRF token for you:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
signIn("credentials", { username: "jsmith", password: "1234" })
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Remember to put any custom pages in a folder outside **/pages/api** which is reserved for API code. As per the examples above, a location convention suggestion is `pages/auth/...`.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
---
|
||||||
|
id: credentials
|
||||||
|
title: Credentials
|
||||||
|
---
|
||||||
|
|
||||||
|
### How to
|
||||||
|
|
||||||
|
The Credentials provider allows you to handle signing in with arbitrary credentials, such as a username and password, two-factor authentication or hardware device (e.g. YubiKey U2F / FIDO).
|
||||||
|
|
||||||
|
It is intended to support use cases where you have an existing system you need to authenticate users against.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
import CredentialsProvider from "next-auth/providers/credentials"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
CredentialsProvider({
|
||||||
|
// The name to display on the sign in form (e.g. 'Sign in with...')
|
||||||
|
name: 'Credentials',
|
||||||
|
// The credentials is used to generate a suitable form on the sign in page.
|
||||||
|
// You can specify whatever fields you are expecting to be submitted.
|
||||||
|
// e.g. domain, username, password, 2FA token, etc.
|
||||||
|
// You can pass any HTML attribute to the <input> tag through the object.
|
||||||
|
credentials: {
|
||||||
|
username: { label: "Username", type: "text", placeholder: "jsmith" },
|
||||||
|
password: { label: "Password", type: "password" }
|
||||||
|
},
|
||||||
|
async authorize(credentials, req) {
|
||||||
|
// You need to provide your own logic here that takes the credentials
|
||||||
|
// submitted and returns either a object representing a user or value
|
||||||
|
// that is false/null if the credentials are invalid.
|
||||||
|
// e.g. return { id: 1, name: 'J Smith', email: 'jsmith@example.com' }
|
||||||
|
// You can also use the `req` object to obtain additional parameters
|
||||||
|
// (i.e., the request IP address)
|
||||||
|
const res = await fetch("/your/endpoint", {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(credentials),
|
||||||
|
headers: { "Content-Type": "application/json" }
|
||||||
|
})
|
||||||
|
const user = await res.json()
|
||||||
|
|
||||||
|
// If no error and we have user data, return it
|
||||||
|
if (res.ok && user) {
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
// Return null if user data could not be retrieved
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Credentials provider documentation](/providers/credentials) for more information.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The Credentials provider can only be used if JSON Web Tokens are enabled for sessions. Users authenticated with the Credentials provider are not persisted in the database.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Name | Description | Type | Required |
|
||||||
|
| :---------: | :-----------------------------------------------: | :-----------------------------------: | :------: |
|
||||||
|
| id | Unique ID for the provider | `string` | Yes |
|
||||||
|
| name | Descriptive name for the provider | `string` | Yes |
|
||||||
|
| type | Type of provider, in this case `credentials` | `"credentials"` | Yes |
|
||||||
|
| credentials | The credentials to sign-in with | `Object` | Yes |
|
||||||
|
| authorize | Callback to execute once user is to be authorized | `(credentials, req) => Promise<User>` | Yes |
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
id: email
|
||||||
|
title: Email
|
||||||
|
---
|
||||||
|
|
||||||
|
### Install nodemailer
|
||||||
|
|
||||||
|
```bash npm2yarn2pnpm
|
||||||
|
npm install nodemailer
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to
|
||||||
|
|
||||||
|
The Email provider sends "magic links" via email that the user can click on to sign in.
|
||||||
|
You have likely seen them before if you have used software like Slack.
|
||||||
|
|
||||||
|
Adding support for signing in via email in addition to one or more OAuth services provides a way for users to sign in if they lose access to their OAuth account (e.g. if it is locked or deleted).
|
||||||
|
|
||||||
|
Configuration is similar to other providers, but the options are different:
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
import EmailProvider from "next-auth/providers/email"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
EmailProvider({
|
||||||
|
server: process.env.EMAIL_SERVER,
|
||||||
|
from: process.env.EMAIL_FROM,
|
||||||
|
// maxAge: 24 * 60 * 60, // How long email links are valid for (default 24h)
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Email provider documentation](/providers/email) for more information on how to configure email sign in.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The email provider requires a database, it cannot be used without one.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
| Name | Description | Type | Required |
|
||||||
|
| :---------------------: | :---------------------------------------------------------------------------------: | :------------------------------: | :------: |
|
||||||
|
| id | Unique ID for the provider | `string` | No |
|
||||||
|
| name | Descriptive name for the provider | `string` | No |
|
||||||
|
| type | Type of provider, in this case `email` | `"email"` | No |
|
||||||
|
| server | Path or object pointing to the email server | `string` or `Object` | No |
|
||||||
|
| sendVerificationRequest | Callback to execute to send a verification request, default uses nodemailer | `(params) => Promise<undefined>` | No |
|
||||||
|
| from | The email address from which emails are sent, default: "<no-reply@example.com>" | `string` | No |
|
||||||
|
| maxAge | How long until the e-mail can be used to log the user in seconds. Defaults to 1 day | `number` | No |
|
||||||
@@ -0,0 +1,428 @@
|
|||||||
|
---
|
||||||
|
id: oauth
|
||||||
|
title: OAuth
|
||||||
|
---
|
||||||
|
|
||||||
|
Authentication Providers in **NextAuth.js** are OAuth definitions that allow your users to sign in with their favorite preexisting logins. You can use any of our many predefined providers, or write your own custom OAuth configuration.
|
||||||
|
|
||||||
|
- [Using a built-in OAuth Provider](#built-in-providers) (e.g Github, Twitter, Google, etc...)
|
||||||
|
- [Using a custom OAuth Provider](#using-a-custom-provider)
|
||||||
|
|
||||||
|
:::note
|
||||||
|
NextAuth.js is designed to work with any OAuth service, it supports **OAuth 1.0**, **1.0A**, **2.0** and **OpenID Connect** and has built-in support for most popular sign-in services.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Without going into too much detail, the OAuth flow generally has 6 parts:
|
||||||
|
|
||||||
|
1. The application requests authorization to access service resources from the user
|
||||||
|
2. If the user authorized the request, the application receives an authorization grant
|
||||||
|
3. The application requests an access token from the authorization server (API) by presenting authentication of its own identity, and the authorization grant
|
||||||
|
4. If the application identity is authenticated and the authorization grant is valid, the authorization server (API) issues an access token to the application. Authorization is complete.
|
||||||
|
5. The application requests the resource from the resource server (API) and presents the access token for authentication
|
||||||
|
6. If the access token is valid, the resource server (API) serves the resource to the application
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant Browser
|
||||||
|
participant App Server
|
||||||
|
participant Auth Server (Github)
|
||||||
|
Note left of Browser: User clicks on "Sign in"
|
||||||
|
Browser->>App Server: GET<br/>"api/auth/signin"
|
||||||
|
App Server->>App Server: Computes the available<br/>sign in providers<br/>from the "providers" option
|
||||||
|
App Server->>Browser: Redirects to Sign in page
|
||||||
|
Note left of Browser: Sign in options<br/>are shown the user<br/>(Github, Twitter, etc...)
|
||||||
|
Note left of Browser: User clicks on<br/>"Sign in with Github"
|
||||||
|
Browser->>App Server: POST<br/>"api/auth/signin/github"
|
||||||
|
App Server->>App Server: Computes sign in<br/>options for Github<br/>(scopes, callback URL, etc...)
|
||||||
|
App Server->>Auth Server (Github): GET<br/>"github.com/login/oauth/authorize"
|
||||||
|
Note left of Auth Server (Github): Sign in options<br> are supplied as<br/>query params<br/>(clientId, <br/>scope, etc...)
|
||||||
|
Auth Server (Github)->>Browser: Shows sign in page<br/>in Github.com<br/>to the user
|
||||||
|
Note left of Browser: User inserts their<br/>credentials in Github
|
||||||
|
Browser->>Auth Server (Github): Github validates the inserted credentials
|
||||||
|
Auth Server (Github)->>Auth Server (Github): Generates one time access code<br/>and calls callback<br>URL defined in<br/>App settings
|
||||||
|
Auth Server (Github)->>App Server: GET<br/>"api/auth/callback/github?code=123"
|
||||||
|
App Server->>App Server: Grabs code<br/>to exchange it for<br/>access token
|
||||||
|
App Server->>Auth Server (Github): POST<br/>"github.com/login/oauth/access_token"<br/>{code: 123}
|
||||||
|
Auth Server (Github)->>Auth Server (Github): Verifies code is<br/>valid and generates<br/>access token
|
||||||
|
Auth Server (Github)->>App Server: { access_token: 16C7x... }
|
||||||
|
App Server->>App Server: Generates session token<br/>and stores session
|
||||||
|
App Server->>Browser: You're now logged in!
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details, check out Aaron Parecki's blog post [OAuth2 Simplified](https://aaronparecki.com/oauth-2-simplified/) or Postman's blog post [OAuth 2.0: Implicit Flow is Dead, Try PKCE Instead](https://blog.postman.com/pkce-oauth-how-to/).
|
||||||
|
|
||||||
|
## How to
|
||||||
|
|
||||||
|
1. Register your application at the developer portal of your provider. There are usually links to the portals included in the aforementioned documentation pages for each supported provider with details on how to register your application.
|
||||||
|
|
||||||
|
2. The redirect URI (sometimes called Callback URL) should follow this format:
|
||||||
|
|
||||||
|
```
|
||||||
|
[origin]/api/auth/callback/[provider]
|
||||||
|
```
|
||||||
|
|
||||||
|
`[provider]` refers to the `id` of your provider (see [options](#options)). For example, Twitter on `localhost` this would be:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://localhost:3000/api/auth/callback/twitter
|
||||||
|
```
|
||||||
|
|
||||||
|
Using Google in our example application would look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://next-auth-example.vercel.app/api/auth/callback/google
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Create a `.env` file at the root of your project and add the client ID and client secret. For Twitter this would be:
|
||||||
|
|
||||||
|
```
|
||||||
|
TWITTER_ID=YOUR_TWITTER_CLIENT_ID
|
||||||
|
TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Now you can add the provider settings to the NextAuth.js options object. You can add as many OAuth providers as you like, as you can see `providers` is an array.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
import TwitterProvider from "next-auth/providers/twitter"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
TwitterProvider({
|
||||||
|
clientId: process.env.TWITTER_ID,
|
||||||
|
clientSecret: process.env.TWITTER_SECRET
|
||||||
|
})
|
||||||
|
],
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Once a provider has been setup, you can sign in at the following URL: `[origin]/api/auth/signin`. This is an unbranded auto-generated page with all the configured providers.
|
||||||
|
|
||||||
|
<img src="/img/signin.png" alt="Signin Screenshot" />
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
Whenever you configure a custom or a built-in OAuth provider, you have the following options available:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface OAuthConfig {
|
||||||
|
/**
|
||||||
|
* OpenID Connect (OIDC) compliant providers can configure
|
||||||
|
* this instead of `authorize`/`token`/`userinfo` options
|
||||||
|
* without further configuration needed in most cases.
|
||||||
|
* You can still use the `authorize`/`token`/`userinfo`
|
||||||
|
* options for advanced control.
|
||||||
|
*
|
||||||
|
* [Authorization Server Metadata](https://datatracker.ietf.org/doc/html/rfc8414#section-3)
|
||||||
|
*/
|
||||||
|
wellKnown?: string
|
||||||
|
/**
|
||||||
|
* The login process will be initiated by sending the user to this URL.
|
||||||
|
*
|
||||||
|
* [Authorization endpoint](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1)
|
||||||
|
*/
|
||||||
|
authorization: EndpointHandler<AuthorizationParameters>
|
||||||
|
/**
|
||||||
|
* Endpoint that returns OAuth 2/OIDC tokens and information about them.
|
||||||
|
* This includes `access_token`, `id_token`, `refresh_token`, etc.
|
||||||
|
*
|
||||||
|
* [Token endpoint](https://datatracker.ietf.org/doc/html/rfc6749#section-3.2)
|
||||||
|
*/
|
||||||
|
token: EndpointHandler<
|
||||||
|
UrlParams,
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parameters extracted from the request to the `/api/auth/callback/:providerId` endpoint.
|
||||||
|
* Contains params like `state`.
|
||||||
|
*/
|
||||||
|
params: CallbackParamsType
|
||||||
|
/**
|
||||||
|
* When using this custom flow, make sure to do all the necessary security checks.
|
||||||
|
* This object contains parameters you have to match against the request to make sure it is valid.
|
||||||
|
*/
|
||||||
|
checks: OAuthChecks
|
||||||
|
},
|
||||||
|
{ tokens: TokenSet }
|
||||||
|
>
|
||||||
|
/**
|
||||||
|
* When using an OAuth 2 provider, the user information must be requested
|
||||||
|
* through an additional request from the userinfo endpoint.
|
||||||
|
*
|
||||||
|
* [Userinfo endpoint](https://www.oauth.com/oauth2-servers/signing-in-with-google/verifying-the-user-info)
|
||||||
|
*/
|
||||||
|
userinfo?: EndpointHandler<UrlParams, { tokens: TokenSet }, Profile>
|
||||||
|
type: "oauth"
|
||||||
|
/**
|
||||||
|
* Used in URLs to refer to a certain provider.
|
||||||
|
* @example /api/auth/callback/twitter // where the `id` is "twitter"
|
||||||
|
*/
|
||||||
|
id: string
|
||||||
|
version: string
|
||||||
|
profile(profile: P, tokens: TokenSet): Awaitable<User>
|
||||||
|
checks?: ChecksType | ChecksType[]
|
||||||
|
clientId: string
|
||||||
|
clientSecret: string
|
||||||
|
/**
|
||||||
|
* If set to `true`, the user information will be extracted
|
||||||
|
* from the `id_token` claims, instead of
|
||||||
|
* making a request to the `userinfo` endpoint.
|
||||||
|
*
|
||||||
|
* `id_token` is usually present in OpenID Connect (OIDC) compliant providers.
|
||||||
|
*
|
||||||
|
* [`id_token` explanation](https://www.oauth.com/oauth2-servers/openid-connect/id-tokens)
|
||||||
|
*/
|
||||||
|
idToken?: boolean
|
||||||
|
region?: string
|
||||||
|
issuer?: string
|
||||||
|
client?: Partial<ClientMetadata>
|
||||||
|
allowDangerousEmailAccountLinking?: boolean
|
||||||
|
/**
|
||||||
|
* Object containing the settings for the styling of the providers sign-in buttons
|
||||||
|
*/
|
||||||
|
style: ProviderStyleType
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `authorization` option
|
||||||
|
|
||||||
|
Configure how to construct the request to the [_Authorization endpoint_](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1).
|
||||||
|
|
||||||
|
There are two ways to use this option:
|
||||||
|
|
||||||
|
1. You can either set `authorization` to be a full URL, like `"https://example.com/oauth/authorization?scope=email"`.
|
||||||
|
2. Use an object with `url` and `params` like so
|
||||||
|
```js
|
||||||
|
authorization: {
|
||||||
|
url: "https://example.com/oauth/authorization",
|
||||||
|
params: { scope: "email" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If your Provider is OpenID Connect (OIDC) compliant, we recommend using the `wellKnown` option instead.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### `token` option
|
||||||
|
|
||||||
|
Configure how to construct the request to the [_Token endpoint_](https://datatracker.ietf.org/doc/html/rfc6749#section-3.2).
|
||||||
|
|
||||||
|
There are three ways to use this option:
|
||||||
|
|
||||||
|
1. You can either set `token` to be a full URL, like `"https://example.com/oauth/token?some=param"`.
|
||||||
|
2. Use an object with `url` and `params` like so
|
||||||
|
```js
|
||||||
|
token: {
|
||||||
|
url: "https://example.com/oauth/token",
|
||||||
|
params: { some: "param" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
3. Completely take control of the request:
|
||||||
|
```js
|
||||||
|
token: {
|
||||||
|
url: "https://example.com/oauth/token",
|
||||||
|
async request(context) {
|
||||||
|
// context contains useful properties to help you make the request.
|
||||||
|
const tokens = await makeTokenRequest(context)
|
||||||
|
return { tokens }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Option 3. should not be necessary in most cases, but if your provider does not follow the spec, or you have some very unique constraints it can be useful. Try to avoid it, if possible.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If your Provider is OpenID Connect (OIDC) compliant, we recommend using the `wellKnown` option instead.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### `userinfo` option
|
||||||
|
|
||||||
|
A `userinfo` endpoint returns information about the logged-in user. It is not part of the OAuth specification, but usually available for most providers.
|
||||||
|
|
||||||
|
There are three ways to use this option:
|
||||||
|
|
||||||
|
1. You can either set `userinfo` to be a full URL, like `"https://example.com/oauth/userinfo?some=param"`.
|
||||||
|
2. Use an object with `url` and `params` like so
|
||||||
|
```js
|
||||||
|
userinfo: {
|
||||||
|
url: "https://example.com/oauth/userinfo",
|
||||||
|
params: { some: "param" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
3. Completely take control of the request:
|
||||||
|
```js
|
||||||
|
userinfo: {
|
||||||
|
url: "https://example.com/oauth/userinfo",
|
||||||
|
// The result of this method will be the input to the `profile` callback.
|
||||||
|
async request(context) {
|
||||||
|
// context contains useful properties to help you make the request.
|
||||||
|
return await makeUserinfoRequest(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Option 3. should not be necessary in most cases, but if your provider does not follow the spec, or you have some very unique constraints it can be useful. Try to avoid it, if possible.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
In the rare case you don't care about what this endpoint returns, or your provider does not have one, you could create a noop function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
userinfo: {
|
||||||
|
request: () => {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If your Provider is OpenID Connect (OIDC) compliant, we recommend using the `wellKnown` option instead. OIDC usually returns an `id_token` from the `token` endpoint. `next-auth` can decode the `id_token` to get the user information, instead of making an additional request to the `userinfo` endpoint. Just set `idToken: true` at the top-level of your provider configuration. If not set, `next-auth` will still try to contact this endpoint.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### `client` option
|
||||||
|
|
||||||
|
An advanced option, hopefully you won't need it in most cases. `next-auth` uses `openid-client` under the hood, see the docs on this option [here](https://github.com/panva/node-openid-client/blob/main/docs/README.md#new-clientmetadata-jwks-options).
|
||||||
|
|
||||||
|
### `allowDangerousEmailAccountLinking` option
|
||||||
|
|
||||||
|
Normally, when you sign in with an OAuth provider and another account with the same email address already exists, the accounts are not linked automatically. Automatic account linking on sign in is not secure between arbitrary providers and is disabled by default (see our [Security FAQ](https://next-auth.js.org/faq#security)). However, it may be desirable to allow automatic account linking if you trust that the provider involved has securely verified the email address associated with the account. Just set `allowDangerousEmailAccountLinking: true` in your provider configuration to enable automatic account linking.
|
||||||
|
|
||||||
|
If the user is already signed in with any provider, when using `signIn` again via a different provider, the new provider account _will_ be linked automatically to the same authenticated user. This happens regardless of the primary emails for each provider accounts. This flow is not affected by the `allowDangerousEmailAccountLinking` option.
|
||||||
|
|
||||||
|
## Using a custom provider
|
||||||
|
|
||||||
|
You can use an OAuth provider that isn't built-in by using a custom object.
|
||||||
|
|
||||||
|
As an example of what this looks like, this is the provider object returned for the Google provider:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
id: "google",
|
||||||
|
name: "Google",
|
||||||
|
type: "oauth",
|
||||||
|
wellKnown: "https://accounts.google.com/.well-known/openid-configuration",
|
||||||
|
authorization: { params: { scope: "openid email profile" } },
|
||||||
|
idToken: true,
|
||||||
|
checks: ["pkce", "state"],
|
||||||
|
profile(profile) {
|
||||||
|
return {
|
||||||
|
id: profile.sub,
|
||||||
|
name: profile.name,
|
||||||
|
email: profile.email,
|
||||||
|
image: profile.picture,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, if your provider supports OpenID Connect and the `/.well-known/openid-configuration` endpoint contains support for the `grant_type`: `authorization_code`, you only need to pass the URL to that configuration file and define some basic fields like `name` and `type`.
|
||||||
|
|
||||||
|
Otherwise, you can pass a more full set of URLs for each OAuth2.0 flow step, for example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
{
|
||||||
|
id: "kakao",
|
||||||
|
name: "Kakao",
|
||||||
|
type: "oauth",
|
||||||
|
authorization: "https://kauth.kakao.com/oauth/authorize",
|
||||||
|
token: "https://kauth.kakao.com/oauth/token",
|
||||||
|
userinfo: "https://kapi.kakao.com/v2/user/me",
|
||||||
|
profile(profile) {
|
||||||
|
return {
|
||||||
|
id: profile.id,
|
||||||
|
name: profile.kakao_account?.profile.nickname,
|
||||||
|
email: profile.kakao_account?.email,
|
||||||
|
image: profile.kakao_account?.profile.profile_image_url,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace all the options in this JSON object with the ones from your custom provider - be sure to give it a unique ID and specify the required URLs, and finally add it to the providers array when initializing the library:
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
import TwitterProvider from "next-auth/providers/twitter"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
TwitterProvider({
|
||||||
|
clientId: process.env.TWITTER_ID,
|
||||||
|
clientSecret: process.env.TWITTER_SECRET,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
id: 'customProvider',
|
||||||
|
name: 'CustomProvider',
|
||||||
|
type: 'oauth',
|
||||||
|
scope: '' // Make sure to request the users email address
|
||||||
|
...
|
||||||
|
}
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Built-in providers
|
||||||
|
|
||||||
|
NextAuth.js comes with a set of built-in providers. You can find them [here](https://github.com/nextauthjs/next-auth/tree/v4/packages/next-auth/src/providers). Each built-in provider has its own documentation page:
|
||||||
|
|
||||||
|
<div className="provider-name-list">
|
||||||
|
{Object.entries(require("../../../providers.json"))
|
||||||
|
.filter(([key]) => !["email", "credentials"].includes(key))
|
||||||
|
.sort(([, a], [, b]) => a.localeCompare(b))
|
||||||
|
.map(([key, name]) => (
|
||||||
|
<span key={key}>
|
||||||
|
<a href={`/providers/${key}`}>{name}</a>
|
||||||
|
<span className="provider-name-list__comma">,</span>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### Override default options
|
||||||
|
|
||||||
|
For built-in providers, in most cases you will only need to specify the `clientId` and `clientSecret`. If you need to override any of the defaults, add your own [options](#options).
|
||||||
|
|
||||||
|
Even if you are using a built-in provider, you can override any of these options to tweak the default configuration.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The user provided options are deeply merged with the default options. That means you only have to override part of the options that you need to be different. For example if you want different scopes, overriding `authorization.params.scope` is enough, instead of the whole `authorization` option.
|
||||||
|
:::
|
||||||
|
|
||||||
|
```js title=/api/auth/[...nextauth].js
|
||||||
|
import Auth0Provider from "next-auth/providers/auth0"
|
||||||
|
|
||||||
|
Auth0Provider({
|
||||||
|
clientId: process.env.CLIENT_ID,
|
||||||
|
clientSecret: process.env.CLIENT_SECRET,
|
||||||
|
issuer: process.env.ISSUER,
|
||||||
|
authorization: { params: { scope: "openid your_custom_scope" } },
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Another example, the `profile` callback will return `id`, `name`, `email` and `picture` by default, but you might need more information from the provider. After setting the correct scopes, you can then do something like this:
|
||||||
|
|
||||||
|
```js title=/api/auth/[...nextauth].js
|
||||||
|
import GoogleProvider from "next-auth/providers/google"
|
||||||
|
|
||||||
|
GoogleProvider({
|
||||||
|
clientId: process.env.GOOGLE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||||
|
profile(profile) {
|
||||||
|
return {
|
||||||
|
// Return all the profile information you need.
|
||||||
|
// The only truly required field is `id`
|
||||||
|
// to be able identify the account when added to a database
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
An example of how to enable automatic account linking:
|
||||||
|
|
||||||
|
```js title=/api/auth/[...nextauth].js
|
||||||
|
import GoogleProvider from "next-auth/providers/google"
|
||||||
|
|
||||||
|
GoogleProvider({
|
||||||
|
clientId: process.env.GOOGLE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
||||||
|
allowDangerousEmailAccountLinking: true,
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
id: contributors
|
||||||
|
title: Contributors
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core team
|
||||||
|
|
||||||
|
Without these people, the project could not have become one of the most used authentication library in its category.
|
||||||
|
|
||||||
|
- [Iain Collins](https://github.com/iaincollins) - Author
|
||||||
|
- [Balázs Orbán](https://github.com/balazsorban44) - **Lead Maintainer**
|
||||||
|
- [Nico Domino](https://github.com/ndom91) - Maintainer (Documentation, Core)
|
||||||
|
- [Lluis Agusti](https://github.com/lluia) - Maintainer (Documentation, Testing, TypeScript)
|
||||||
|
- [Thang Huu Vu](https://github.com/ThangHuuVu) - Maintainer (Core, TypeScript)
|
||||||
|
|
||||||
|
## Special thanks
|
||||||
|
|
||||||
|
Special thanks to Lori Karikari for creating most of the original provider configurations to Fredrik Pettersen for creating the original Prisma Adapter, to Gerald Nolan for adding support for Sign in with Apple, and to Jefferson Bledsoe for working on original testing automations.
|
||||||
|
|
||||||
|
- [Lori Karikari](https://github.com/LoriKarikari)
|
||||||
|
- [Fredrik Pettersen](https://github.com/Fumler)
|
||||||
|
- [Gerald Nolan](https://github.com/geraldnolan)
|
||||||
|
- [Jefferson Bledsoe](https://github.com/JeffersonBledsoe)
|
||||||
|
|
||||||
|
## Other contributors
|
||||||
|
|
||||||
|
NextAuth.js as it exists today has been possible thanks to the work of many individual contributors.
|
||||||
|
|
||||||
|
Thank you to the [dozens of individual contributors](https://github.com/nextauthjs/next-auth/graphs/contributors) who have help shaped NextAuth.js.
|
||||||
|
|
||||||
|
## Open Collective
|
||||||
|
|
||||||
|
You can find NextAuth.js on Open Collective. We are very thankful for all of our existing contributors and would be delighted if you or your company would decide to join them.
|
||||||
|
|
||||||
|
More information can be found at: https://opencollective.com/nextauth
|
||||||
|
|
||||||
|
## History
|
||||||
|
|
||||||
|
- NextAuth.js was originally developed by <a href="https://github.com/iaincollins">Iain Collins</a> in 2016 for Next.js.
|
||||||
|
|
||||||
|
- In 2020, NextAuth.js was rebuilt from the ground up to support Serverless, with support for MySQL, Postgres and MongoDB, JSON Web Tokens and built in support for over a dozen authentication providers.
|
||||||
|
|
||||||
|
- In 2021, efforts have started to move NextAuth.js to other frameworks and to support as many databases and providers as possible.
|
||||||
|
|
||||||
|
- In 2025, NextAuth.js was acquired by and is now owned and maintained by <a href="https://better-auth.com">Better Auth Inc.</a>
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
# Deployment
|
||||||
|
|
||||||
|
Deploying NextAuth.js only requires a few steps. It can be run anywhere a Next.js application can. Therefore, in a default configuration using only JWT session strategy, i.e. without a database, you will only need these few things in addition to your application:
|
||||||
|
|
||||||
|
1. NextAuth.js environment variables
|
||||||
|
|
||||||
|
- `NEXTAUTH_SECRET`
|
||||||
|
- `NEXTAUTH_URL`
|
||||||
|
|
||||||
|
2. NextAuth.js API Route and its configuration (`/pages/api/auth/[...nextauth].js`).
|
||||||
|
- OAuth Provider `clientId` / `clientSecret`
|
||||||
|
|
||||||
|
Deploying a modern JavaScript application using NextAuth.js consists of making sure your environment variables are set correctly as well as the configuration in the NextAuth.js API route is setup, as well as any configuration (like Callback URLs, etc.) are correctly done in your OAuth provider(s) themselves.
|
||||||
|
|
||||||
|
See below for more detailed provider settings.
|
||||||
|
|
||||||
|
## Vercel
|
||||||
|
|
||||||
|
1. Make sure to expose the Vercel [System Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) in your project settings.
|
||||||
|
2. Create a `NEXTAUTH_SECRET` environment variable for all environments.
|
||||||
|
- You can use `openssl rand -base64 32` or https://generate-secret.vercel.app/32 to generate a random value.
|
||||||
|
- You **do not** need the `NEXTAUTH_URL` environment variable in Vercel.
|
||||||
|
3. Add your provider's client ID and client secret to environment variables. _(Skip this step if not using an [OAuth Provider](/configuration/providers/oauth))_
|
||||||
|
4. Deploy!
|
||||||
|
|
||||||
|
Example repository: https://github.com/nextauthjs/next-auth-example
|
||||||
|
|
||||||
|
A few notes about deploying to Vercel. The environment variables are read server-side, so you do not need to prefix them with `NEXT_PUBLIC_`. When deploying here, you do not need to explicitly set the `NEXTAUTH_URL` environment variable. With other providers **you will** need to also set this environment variable.
|
||||||
|
|
||||||
|
### Securing a preview deployment
|
||||||
|
|
||||||
|
Securing a preview deployment (with an OAuth provider) comes with some critical obstacles. Most OAuth providers only allow a single redirect/callback URL, or at least a set of full static URLs. Meaning you cannot set the value before publishing the site and you cannot use wildcard subdomains in the callback URL settings of your OAuth provider. Here are a few ways you can still use NextAuth.js to secure your Preview Deployments.
|
||||||
|
|
||||||
|
#### Using the Credentials Provider
|
||||||
|
|
||||||
|
You could check in your `/pages/api/auth/[...nextauth].js` API route / configuration file to see if you're currently in a Vercel preview environment, and if so, enable a simple "credential provider", meaning username/password. Vercel offers a few built-in [system environment variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) which you could check against, like `VERCEL_ENV`. This would allow you to use this basic, for testing only, authentication strategy in your preview deployments.
|
||||||
|
|
||||||
|
Some things to be aware of here, include:
|
||||||
|
|
||||||
|
- Do not let this potential testing-only user have access to any critical data
|
||||||
|
- If possible, maybe do not even connect this preview deployment to your production database
|
||||||
|
|
||||||
|
##### Example
|
||||||
|
|
||||||
|
```js title="/pages/api/auth/[...nextauth].js"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
import GoogleProvider from "next-auth/providers/google"
|
||||||
|
import CredentialsProvider from "next-auth/providers/credentials"
|
||||||
|
|
||||||
|
export default NextAuth({
|
||||||
|
providers: [
|
||||||
|
process.env.VERCEL_ENV === "preview"
|
||||||
|
? CredentialsProvider({
|
||||||
|
name: "Credentials",
|
||||||
|
credentials: {
|
||||||
|
username: {
|
||||||
|
label: "Username",
|
||||||
|
type: "text",
|
||||||
|
placeholder: "jsmith",
|
||||||
|
},
|
||||||
|
password: { label: "Password", type: "password" },
|
||||||
|
},
|
||||||
|
async authorize() {
|
||||||
|
return {
|
||||||
|
id: 1,
|
||||||
|
name: "J Smith",
|
||||||
|
email: "jsmith@example.com",
|
||||||
|
image: "https://i.pravatar.cc/150?u=jsmith@example.com",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
: GoogleProvider({
|
||||||
|
clientId: process.env.GOOGLE_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_SECRET,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using the branch based preview URL
|
||||||
|
|
||||||
|
Preview deployments at Vercel are often available via multiple URLs. For example, PR's merged to `master` or `main`, will be available via commit and PR specific preview URLs, but also the branch specific preview URLs. This branch specific URL will obviously not change as long as you work with that same branch. Therefore, you could add to your OAuth provider your `{project}-git-main-{user}.vercel.app` preview URL. As this will stay constant for that branch, you can reuse that preview deployment / URL for testing any authentication related deployments.
|
||||||
|
|
||||||
|
## Netlify
|
||||||
|
|
||||||
|
Netlify is very similar to Vercel in that you can deploy a Next.js project without almost any extra work.
|
||||||
|
|
||||||
|
In order to setup NextAuth.js correctly here, you will want to make sure you add your `NEXTAUTH_SECRET` environment variable in the project settings. If you are using the [Essential Next.js Build Plugin](https://github.com/netlify/netlify-plugin-nextjs) within your project, you **do not** need to set the `NEXTAUTH_URL` environment variable as it is set automatically as part of the build process.
|
||||||
|
|
||||||
|
Netlify also exposes some [system environment variables](https://docs.netlify.com/configure-builds/environment-variables/) from which you can check which `NODE_ENV` you are currently in and much more.
|
||||||
|
|
||||||
|
After this, just make sure you either have your OAuth provider setup correctly with `clientId` / `clientSecret`'s and callback URLs.
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
---
|
||||||
|
id: errors
|
||||||
|
title: Errors
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a list of errors output from NextAuth.js.
|
||||||
|
|
||||||
|
All errors indicate an unexpected problem, you should not expect to see errors.
|
||||||
|
|
||||||
|
If you are seeing any of these errors in the console, something is wrong.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client
|
||||||
|
|
||||||
|
These errors are returned from the client. As the client is [Universal JavaScript (or "Isomorphic JavaScript")](https://en.wikipedia.org/wiki/Isomorphic_JavaScript) it can be run on the client or server, so these errors can occur both in the terminal and in the browser console.
|
||||||
|
|
||||||
|
#### CLIENT_SESSION_ERROR
|
||||||
|
|
||||||
|
This error occurs when the `SessionProvider` Context has a problem fetching session data.
|
||||||
|
|
||||||
|
#### CLIENT_FETCH_ERROR
|
||||||
|
|
||||||
|
This can happen for multiple reasons. Make sure that you [configured](/configuration/initialization) NextAuth.js correctly, and if you used [`NEXTAUTH_URL`](https://next-auth.js.org/configuration/options#nextauth_url) that it's correctly set.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Server
|
||||||
|
|
||||||
|
These errors are displayed on the terminal.
|
||||||
|
|
||||||
|
### OAuth
|
||||||
|
|
||||||
|
#### OAUTH_GET_ACCESS_TOKEN_ERROR
|
||||||
|
|
||||||
|
This occurs when there was an error in the POST request to the OAuth provider and we were not able to retrieve the access token.
|
||||||
|
|
||||||
|
Please double check your provider settings.
|
||||||
|
|
||||||
|
#### OAUTH_V1_GET_ACCESS_TOKEN_ERROR
|
||||||
|
|
||||||
|
This error is explicitly related to older OAuth v1.x providers, if you are using one of these, please double check all available settings.
|
||||||
|
|
||||||
|
#### OAUTH_GET_PROFILE_ERROR
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
#### OAUTH_PARSE_PROFILE_ERROR
|
||||||
|
|
||||||
|
This error is a result of either a problem with the provider response or the user canceling the action with the provider, unfortunately, we can't discern which with the information we have.
|
||||||
|
|
||||||
|
This error should also log the exception and available `profileData` to further aid debugging.
|
||||||
|
|
||||||
|
#### OAUTH_CALLBACK_HANDLER_ERROR
|
||||||
|
|
||||||
|
This error will occur when there was an issue parsing the JSON request body, for example.
|
||||||
|
|
||||||
|
There should also be further details logged when this occurs, such as the error is thrown, and the request body itself to aid in debugging.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Signin / Callback
|
||||||
|
|
||||||
|
#### SIGNIN_OAUTH_ERROR
|
||||||
|
|
||||||
|
This error occurs during the redirection to the authorization URL of the OAuth provider. Possible causes:
|
||||||
|
|
||||||
|
1. Cookie handling
|
||||||
|
Either PKCE code verifier or the generation of the CSRF token hash in the internal state failed.
|
||||||
|
|
||||||
|
If set, check your [`cookies` configuration](/configuration/options#cookies), and make sure the browser is not blocking/restricting cookies.
|
||||||
|
|
||||||
|
2. OAuth misconfiguration
|
||||||
|
|
||||||
|
Please check your OAuth provider and make sure your URLs and other options are correctly set.
|
||||||
|
|
||||||
|
If you are using an OAuth v1 provider, check your OAuth v1 provider settings, especially the OAuth token and OAuth token secret.
|
||||||
|
|
||||||
|
3. `openid-client` version mismatch
|
||||||
|
|
||||||
|
If you are seeing `expected 200 OK with body but no body was returned`, it might have happened due to `openid-client` (which is a dependency we rely on) node version mismatch. For instance, `openid-client` requires `>=14.2.0` for `lts/fermium` and has similar limits for the other versions. For the full list of the compatible node versions please see [package.json](https://github.com/panva/node-openid-client/blob/2a84e46992e1ebeaf685c3f87b65663d126e81aa/package.json#L78).
|
||||||
|
|
||||||
|
#### OAUTH_CALLBACK_ERROR
|
||||||
|
|
||||||
|
This can occur during the handling of the callback if the `code_verifier` cookie was not found or an invalid state was returned from the OAuth provider.
|
||||||
|
|
||||||
|
#### SIGNIN_EMAIL_ERROR
|
||||||
|
|
||||||
|
This error can occur when a user tries to sign in via an email link; for example, if the email token could not be generated or the verification request failed.
|
||||||
|
|
||||||
|
Please double check your email settings.
|
||||||
|
|
||||||
|
#### CALLBACK_EMAIL_ERROR
|
||||||
|
|
||||||
|
This can occur during the email callback process. Specifically, if there was an error signing the user in via email, encoding the jwt, etc.
|
||||||
|
|
||||||
|
Please double check your Email settings.
|
||||||
|
|
||||||
|
#### EMAIL_REQUIRES_ADAPTER_ERROR
|
||||||
|
|
||||||
|
The Email authentication provider can only be used if a database is configured.
|
||||||
|
|
||||||
|
This is required to store the verification token. Please see the [email provider](/providers/email#configuration) for more details.
|
||||||
|
|
||||||
|
#### CALLBACK_CREDENTIALS_JWT_ERROR
|
||||||
|
|
||||||
|
The Credentials Provider can only be used if JSON Web Tokens are used for sessions.
|
||||||
|
|
||||||
|
JSON Web Tokens are used for Sessions by default if you have not specified a database. However, if you are using a database, then Database Sessions are enabled by default and you need to [explicitly enable JWT Sessions](/configuration/options#session) to use the Credentials Provider.
|
||||||
|
|
||||||
|
If you are using a Credentials Provider, NextAuth.js will not persist users or sessions in a database - user accounts used with the Credentials Provider must be created and managed outside of NextAuth.js.
|
||||||
|
|
||||||
|
In _most cases_ it does not make sense to specify a database in NextAuth.js options and support a Credentials Provider.
|
||||||
|
|
||||||
|
#### CALLBACK_CREDENTIALS_HANDLER_ERROR
|
||||||
|
|
||||||
|
This error occurs when there was no `authorize()` handler defined on the credential authentication provider.
|
||||||
|
|
||||||
|
#### PKCE_ERROR
|
||||||
|
|
||||||
|
The provider you tried to use failed when setting [PKCE or Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636#section-4).
|
||||||
|
The `code_verifier` is saved in a cookie called (by default) `__Secure-next-auth.pkce.code_verifier` which expires after 15 minutes.
|
||||||
|
Check if `cookies.pkceCodeVerifier` is configured correctly.
|
||||||
|
|
||||||
|
The default `code_challenge_method` is `"S256"`. This is currently not configurable to `"plain"`, [as per RFC7636](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2):
|
||||||
|
> If the client is capable of using "S256", it MUST use "S256", as
|
||||||
|
S256" is Mandatory To Implement (MTI) on the server.
|
||||||
|
|
||||||
|
#### INVALID_CALLBACK_URL_ERROR
|
||||||
|
|
||||||
|
The `callbackUrl` provided was either invalid or not defined. See [specifying a `callbackUrl`](/getting-started/client#specifying-a-callbackurl) for more information.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Session Handling
|
||||||
|
|
||||||
|
#### JWT_SESSION_ERROR
|
||||||
|
|
||||||
|
JWEDecryptionFailed: NextAuth.js needs `NEXTAUTH_SECRET` environment variable to encrypt JWTs and to hash email verification tokens. This can also occur if you have changed the `NEXTAUTH_SECRET`, but you still had an active session with the old secret. Logging in again solves the issue.
|
||||||
|
|
||||||
|
JWTKeySupport: the key does not support HS512 verify algorithm
|
||||||
|
|
||||||
|
The algorithm used for generating your key isn't listed as supported. You can generate a HS512 key using
|
||||||
|
|
||||||
|
```
|
||||||
|
jose newkey -s 512 -t oct -a HS512
|
||||||
|
```
|
||||||
|
|
||||||
|
#### SESSION_ERROR
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Signout
|
||||||
|
|
||||||
|
#### SIGNOUT_ERROR
|
||||||
|
|
||||||
|
This error occurs when there was an issue deleting the session from the database, for example.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
#### MISSING_NEXTAUTH_API_ROUTE_ERROR
|
||||||
|
|
||||||
|
This error happens when `[...nextauth].js` file is not found inside `pages/api/auth`.
|
||||||
|
|
||||||
|
Make sure the file is there and the filename is written correctly.
|
||||||
|
|
||||||
|
#### NO_SECRET
|
||||||
|
|
||||||
|
In production, we expect you to define a `secret` property in your configuration. In development, this is shown as a warning for convenience. [Read more](/configuration/options#secret)
|
||||||
|
|
||||||
|
|
||||||
|
#### AUTH_ON_ERROR_PAGE_ERROR
|
||||||
|
|
||||||
|
You have a custom error page defined that was rendered due to an error, but the page also required authentication. To avoid an infinite redirect loop, NextAuth.js bailed out and rendered its default error page instead.
|
||||||
|
|
||||||
|
If you are using a Middleware, make sure you include the same `pages` configuration in your `middleware.ts` and `[...nextauth].ts` files. Or use the `matcher` option to only require authentication for certain sites (and exclude your custom error page).
|
||||||
|
|
||||||
|
If you do not use a Middleware, make sure you don't try redirecting the user to the sign-in page when hitting your custom error page.
|
||||||
|
|
||||||
|
Useful links:
|
||||||
|
|
||||||
|
- https://next-auth.js.org/configuration/nextjs#pages
|
||||||
|
- https://next-auth.js.org/configuration/pages
|
||||||
|
- https://nextjs.org/docs/advanced-features/middleware#matcher
|
||||||
|
|
||||||
@@ -0,0 +1,377 @@
|
|||||||
|
---
|
||||||
|
id: faq
|
||||||
|
title: Frequently Asked Questions
|
||||||
|
---
|
||||||
|
|
||||||
|
## About NextAuth.js
|
||||||
|
|
||||||
|
### Is NextAuth.js commercial software?
|
||||||
|
|
||||||
|
NextAuth.js is an open source project built by individual contributors.
|
||||||
|
|
||||||
|
It is not commercial software and is not associated with a commercial organization.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>What databases does NextAuth.js support?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
You can use NextAuth.js with MySQL, MariaDB, Postgres, MongoDB and SQLite or without a database. (See also: [Databases](/configuration/databases))
|
||||||
|
|
||||||
|
You can use also NextAuth.js with any database using a custom database adapter, or by using a custom credentials authentication provider - e.g. to support signing in with a username and password stored in an existing database.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>What authentication services does NextAuth.js support?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
<p>NextAuth.js includes built-in support for signing in with
|
||||||
|
{Object.values(require("../providers.json")).sort().join(", ")}.
|
||||||
|
(See also: <a href="/configuration/providers/oauth">Providers</a>)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
NextAuth.js also supports email for passwordless sign in, which is useful for account recovery or for people who are not able to use an account with the configured OAuth services (e.g. due to service outage, account suspension or otherwise becoming locked out of an account).
|
||||||
|
|
||||||
|
You can also use a custom based provider to support signing in with a username and password stored in an external database and/or using two factor authentication.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Does NextAuth.js support signing in with a username and password?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js is designed to avoid the need to store passwords for user accounts.
|
||||||
|
|
||||||
|
If you have an existing database of usernames and passwords, you can use a custom credentials provider to allow signing in with a username and password stored in an existing database.
|
||||||
|
|
||||||
|
_If you use a custom credentials provider user accounts will not be persisted in a database by NextAuth.js (even if one is configured). The option to use JSON Web Tokens for session tokens (which allow sign in without using a session database) must be enabled to use a custom credentials provider._
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Can I use NextAuth.js with a framework different than Next.js?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js was originally designed for use with Next.js and Serverless. However, today you could use the NextAuth.js core with any other framework. Checkout the examples for <a href="https://github.com/nextauthjs/next-auth/tree/main/apps/playground-gatsby" target="_blank">Gatsby</a> and <a href="https://sveltekit.authjs.dev/" target="_blank">SvelteKit</a>. If you would add another integration with other frameworks, feel free to work on it and send a pull request. Make sure to check if there's any on-going work before opening a new issue.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Can session generated by NextAuth.js be used by another website?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
**Same domain**: you can create a website that handles sign-in with NextAuth.js and then access those sessions on a website that does not use NextAuth.js as long as the websites are on the same domain.
|
||||||
|
|
||||||
|
**Same root domain, different subdomains**: If you use NextAuth.js on a website with a different subdomain than the rest of your website (e.g. `auth.example.com` vs. `www.example.com`) you will need to set a custom cookie domain policy for the Session Token cookie. (See also: [Cookies](/configuration/options#cookies)).
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Changing the default cookies domain policy can lead to security issues if done incorrectly. Make sure you're aware of the implications before proceeding.
|
||||||
|
:::
|
||||||
|
|
||||||
|
A working example can be found at <a href="https://github.com/vercel/examples/tree/main/solutions/subdomain-auth" target="_blank">this example repo</a>.
|
||||||
|
|
||||||
|
**Different root domains**: NextAuth.js does not currently support automatically signing into sites on different top-level domains (e.g. `www.example.com` vs. `www.example.org`) using a single session.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Can I use NextAuth.js with React Native?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js is designed as a secure, confidential client and implements a server side authentication flow.
|
||||||
|
|
||||||
|
It is not intended to be used in native applications on desktop or mobile applications, which typically implement public clients (e.g. with client / secrets embedded in the application).
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Is NextAuth.js supporting TypeScript?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Yes! Check out the [TypeScript docs](/getting-started/typescript)
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Is NextAuth.js compatible with Next.js 12 Middleware?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
[Next.js Middleware](https://nextjs.org/docs/middleware) is supported. Head over to the [this page](/configuration/nextjs#middleware)
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Databases
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>What databases are supported by NextAuth.js?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js can be used with MySQL, Postgres, MongoDB, SQLite and compatible databases (e.g. MariaDB, Amazon Aurora, Amazon DocumentDB…) or with no database.
|
||||||
|
|
||||||
|
It also provides an Adapter API which allows you to connect it to any database.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>What does NextAuth.js use databases for?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Databases in NextAuth.js are used for persisting users, OAuth accounts, email sign in tokens and sessions.
|
||||||
|
|
||||||
|
Specifying a database is optional if you don't need to persist user data or support email sign in. If you don't specify a database then JSON Web Tokens will be enabled for session storage and used to store session data.
|
||||||
|
|
||||||
|
If you are using a database with NextAuth.js, you can still explicitly enable JSON Web Tokens for sessions (instead of using database sessions).
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Should I use a database?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
- Using NextAuth.js without a database works well for internal tools - where you need to control who is able to sign in, but when you do not need to create user accounts for them in your application.
|
||||||
|
|
||||||
|
- Using NextAuth.js with a database is usually a better approach for a consumer facing application where you need to persist accounts (e.g. for billing, to contact customers, etc).
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>What database should I use?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Managed database solutions for MySQL, Postgres and MongoDB (and compatible databases) are well supported from cloud providers such as Amazon, Google, Microsoft and Atlas.
|
||||||
|
|
||||||
|
If you are deploying directly to a particular cloud platform you may also want to consider serverless database offerings they have (e.g. [Amazon Aurora Serverless on AWS](https://aws.amazon.com/rds/aurora/serverless/)).
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Parts of this section has been moved to its [own page](/security).
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>How do I get Refresh Tokens and Access Tokens for an OAuth account?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js provides a solution for authentication, session management and user account creation.
|
||||||
|
|
||||||
|
NextAuth.js records Refresh Tokens and Access Tokens on sign in (if supplied by the provider) and it will pass them, along with the User ID, Provider and Provider Account ID, to either:
|
||||||
|
|
||||||
|
1. A database - if a database connection string is provided
|
||||||
|
2. The JSON Web Token callback - if JWT sessions are enabled (e.g. if no database specified)
|
||||||
|
|
||||||
|
You can then look them up from the database or persist them to the JSON Web Token.
|
||||||
|
|
||||||
|
Note: NextAuth.js does not currently handle Access Token rotation for OAuth providers for you, however you can check out [this tutorial](https://authjs.dev/guides/refresh-token-rotation) if you want to implement it.
|
||||||
|
|
||||||
|
We also have an [example repository](https://github.com/nextauthjs/next-auth-refresh-token-example) / project based upon NextAuth.js v4 where we demonstrate how to use a refresh token to refresh the provided access token.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>When I sign in with another account with the same email address, why are accounts not linked automatically?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Automatic account linking on sign in is not secure between arbitrary providers - with the exception of allowing users to sign in via an email addresses as a fallback (as they must verify their email address as part of the flow).
|
||||||
|
|
||||||
|
When an email address is associated with an OAuth account it does not necessarily mean that it has been verified as belonging to account holder — how email address verification is handled is not part of the OAuth specification and varies between providers (e.g. some do not verify first, some do verify first, others return metadata indicating the verification status).
|
||||||
|
|
||||||
|
With automatic account linking on sign in, this can be exploited by bad actors to hijack accounts by creating an OAuth account associated with the email address of another user.
|
||||||
|
|
||||||
|
For this reason it is not secure to automatically link accounts between arbitrary providers on sign in, which is why this feature is generally not provided by authentication service.
|
||||||
|
|
||||||
|
Automatic account linking is seen on some sites, sometimes insecurely. It can be technically possible to do automatic account linking securely if you trust all the providers involved to ensure they have securely verified the email address associated with the account, but requires placing trust (and transferring the risk) to those providers to handle the process securely.
|
||||||
|
|
||||||
|
Examples of scenarios where this is secure include with an OAuth provider you control (e.g. that only authorizes users internal to your organization) or with a provider you explicitly trust to have verified the users email address.
|
||||||
|
|
||||||
|
Automatic account linking is supported on a per-provider basis via `allowDangerousEmailAccountLinking`.
|
||||||
|
|
||||||
|
Providing support for secure account linking and unlinking of additional providers - which can only be done if a user is already signed in already - was originally a feature in v1.x but has not been present since v2.0, is planned to return in a future release.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If the user first signs in using Email and then tries to sign in again using an OAuth provider, NextAuth.js default behavior is to allow account linking even if the OAuth account's email address does not match the previous email address of the user.
|
||||||
|
:::
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Feature Requests
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>Why doesn't NextAuth.js support [a particular feature]?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js is an open source project built by individual contributors who are volunteers writing code and providing support in their spare time.
|
||||||
|
|
||||||
|
If you would like NextAuth.js to support a particular feature, the best way to help make it happen is to raise a feature request describing the feature and offer to work with other contributors to develop and test it.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3 style={{display:"inline-block"}}>I disagree with a design decision, how can I change your mind?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
Product design decisions on NextAuth.js are made by core team members.
|
||||||
|
|
||||||
|
You can raise suggestions as feature requests / requests for enhancement.
|
||||||
|
|
||||||
|
Requests that provide the detail requested in the template and follow the format requested may be more likely to be supported, as additional detail prompted in the templates often provides important context.
|
||||||
|
|
||||||
|
Ultimately if your request is not accepted or is not actively in development, you are always free to fork the project under the terms of the ISC License.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## JSON Web Tokens
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3>Does NextAuth.js use JSON Web Tokens?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js by default uses JSON Web Tokens for saving the user's session. However, if you use a [database adapter](https://authjs.dev/getting-started/database), the database will be used to persist the user's session. You can force the usage of JWT when using a database [through the configuration options](/configuration/options#session). Since v4 all our JWT tokens are now encrypted by default with A256GCM.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3>What are the advantages of JSON Web Tokens?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
JSON Web Tokens can be used for session tokens, but are also used for lots of other things, such as sending signed objects between services in authentication flows.
|
||||||
|
|
||||||
|
- Advantages of using a JWT as a session token include that they do not require a database to store sessions, this can be faster and cheaper to run and easier to scale.
|
||||||
|
|
||||||
|
- JSON Web Tokens in NextAuth.js are secured using cryptographic encryption (JWE) to store the included information directly in a JWT session token. You may then use the token to pass information between services and APIs on the same domain without having to contact a database to verify the included information.
|
||||||
|
|
||||||
|
- You can use JWT to securely store information you do not mind the client knowing even without encryption, as the JWT is stored in a server-readable-only cookie so data in the JWT is not accessible to third party JavaScript running on your site.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3>What are the disadvantages of JSON Web Tokens?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
- You cannot as easily expire a JSON Web Token - doing so requires maintaining a server side blocklist of invalid tokens (at least until they expire) and checking every token against the list every time a token is presented.
|
||||||
|
|
||||||
|
Shorter session expiry times are used when using JSON Web Tokens as session tokens to allow sessions to be invalidated sooner and simplify this problem.
|
||||||
|
|
||||||
|
NextAuth.js client includes advanced features to mitigate the downsides of using shorter session expiry times on the user experience, including automatic session token rotation, optionally sending keep alive messages to prevent short lived sessions from expiring if there is an window or tab open, background re-validation, and automatic tab/window syncing that keeps sessions in sync across windows any time session state changes or a window or tab gains or loses focus.
|
||||||
|
|
||||||
|
- As with database session tokens, JSON Web Tokens are limited in the amount of data you can store in them. There is typically a limit of around 4096 bytes per cookie, though the exact limit varies between browsers, proxies and hosting services. If you want to support most browsers, then do not exceed 4096 bytes per cookie. If you want to save more data, you will need to persist your sessions in a database (Source: [browsercookielimits.iain.guru](http://browsercookielimits.iain.guru/))
|
||||||
|
|
||||||
|
The more data you try to store in a token and the more other cookies you set, the closer you will come to this limit. Since v4 we have implemented cookie chunking so that cookies over the 4kb limit get split and reassembled upon parsing. However since this data needs to be transmitted on every request, if you wish to store more than ~4 KB of data you're probably at the point where you want to store a unique ID in the token and persist the data elsewhere (e.g. in a server-side key/value store).
|
||||||
|
|
||||||
|
- Data stored in an encrypted JSON Web Token (JWE) may be compromised at some point.
|
||||||
|
|
||||||
|
Even if appropriately configured, information stored in an encrypted JWT should not be assumed to be impossible to decrypt at some point - e.g. due to the discovery of a defect or advances in technology.
|
||||||
|
|
||||||
|
Avoid storing any data in a token that might be problematic if it were to be decrypted in the future.
|
||||||
|
|
||||||
|
- If you do not explicitly specify a secret for NextAuth.js, existing sessions will be invalidated any time your NextAuth.js configuration changes, as NextAuth.js will default to an auto-generated secret. Since v4 this only impacts development and generating a secret is required in production.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3>Are JSON Web Tokens secure?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
By default tokens are not signed (JWS) but are encrypted (JWE). Since v4 we have implemented cookie chunking so that cookies over the 4kb limit get split and reassembled upon parsing.
|
||||||
|
|
||||||
|
You can specify other valid algorithms - [as specified in RFC 7518](https://tools.ietf.org/html/rfc7517) - with either a secret (for symmetric encryption) or a public/private key pair (for asymmetric encryption).
|
||||||
|
|
||||||
|
NextAuth.js will generate keys for you, but this will generate a warning at start up.
|
||||||
|
|
||||||
|
Using explicit public/private keys for signing is strongly recommended.
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<h3>What signing and encryption standards does NextAuth.js support?</h3>
|
||||||
|
</summary>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
NextAuth.js includes a largely complete implementation of JSON Object Signing and Encryption (JOSE):
|
||||||
|
|
||||||
|
- [RFC 7515 - JSON Web Signature (JWS)](https://tools.ietf.org/html/rfc7515)
|
||||||
|
- [RFC 7516 - JSON Web Encryption (JWE)](https://tools.ietf.org/html/rfc7516)
|
||||||
|
- [RFC 7517 - JSON Web Key (JWK)](https://tools.ietf.org/html/rfc7517)
|
||||||
|
- [RFC 7518 - JSON Web Algorithms (JWA)](https://tools.ietf.org/html/rfc7518)
|
||||||
|
- [RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)
|
||||||
|
|
||||||
|
This incorporates support for:
|
||||||
|
|
||||||
|
- [RFC 7638 - JSON Web Key Thumbprint](https://tools.ietf.org/html/rfc7638)
|
||||||
|
- [RFC 7787 - JSON JWS Unencoded Payload Option](https://tools.ietf.org/html/rfc7797)
|
||||||
|
- [RFC 8037 - CFRG Elliptic Curve ECDH and Signatures](https://tools.ietf.org/html/rfc8037)
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
@@ -0,0 +1,656 @@
|
|||||||
|
---
|
||||||
|
id: client
|
||||||
|
title: Client API
|
||||||
|
---
|
||||||
|
|
||||||
|
The NextAuth.js client library makes it easy to interact with sessions from React applications.
|
||||||
|
|
||||||
|
#### Example Session Object
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
user: {
|
||||||
|
name: string
|
||||||
|
email: string
|
||||||
|
image: string
|
||||||
|
},
|
||||||
|
expires: Date // This is the expiry of the session, not any of the tokens within the session
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The session data returned to the client does not contain sensitive information such as the Session Token or OAuth tokens. It contains a minimal payload that includes enough data needed to display information on a page about the user who is signed in for presentation purposes (e.g name, email, image).
|
||||||
|
|
||||||
|
You can use the [session callback](/configuration/callbacks#session-callback) to customize the session object returned to the client if you need to return additional data in the session object.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The `expires` value is rotated, meaning whenever the session is retrieved from the [REST API](/getting-started/rest-api), this value will be updated as well, to avoid session expiry.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## useSession()
|
||||||
|
|
||||||
|
- Client Side: **Yes**
|
||||||
|
- Server Side: No
|
||||||
|
|
||||||
|
The `useSession()` React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
|
||||||
|
|
||||||
|
Make sure that [`<SessionProvider>`](#sessionprovider) is added to `pages/_app.js`.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Component() {
|
||||||
|
const { data: session, status } = useSession()
|
||||||
|
|
||||||
|
if (status === "authenticated") {
|
||||||
|
return <p>Signed in as {session.user.email}</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <a href="/api/auth/signin">Sign in</a>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`useSession()` returns an object containing two values: `data` and `status`:
|
||||||
|
|
||||||
|
- **`data`**: This can be three values: [`Session`](https://github.com/nextauthjs/next-auth/blob/8ff4b260143458c5d8a16b80b11d1b93baa0690f/types/index.d.ts#L437-L444) / `undefined` / `null`.
|
||||||
|
- when the session hasn't been fetched yet, `data` will be `undefined`
|
||||||
|
- in case it failed to retrieve the session, `data` will be `null`
|
||||||
|
- in case of success, `data` will be [`Session`](https://github.com/nextauthjs/next-auth/blob/8ff4b260143458c5d8a16b80b11d1b93baa0690f/types/index.d.ts#L437-L444).
|
||||||
|
- **`status`**: enum mapping to three possible session states: `"loading" | "authenticated" | "unauthenticated"`
|
||||||
|
|
||||||
|
### Require session
|
||||||
|
|
||||||
|
Due to the way Next.js handles `getServerSideProps` and `getInitialProps`, every protected page load has to make a server-side request to check if the session is valid and then generate the requested page (SSR). This increases server load, and if you are good with making the requests from the client, there is an alternative. You can use `useSession` in a way that makes sure you always have a valid session. If after the initial loading state there was no session found, you can define the appropriate action to respond.
|
||||||
|
|
||||||
|
The default behavior is to redirect the user to the sign-in page, from where - after a successful login - they will be sent back to the page they started on. You can also define an `onUnauthenticated()` callback, if you would like to do something else:
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```jsx title="pages/protected.jsx"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Admin() {
|
||||||
|
const { status } = useSession({
|
||||||
|
required: true,
|
||||||
|
onUnauthenticated() {
|
||||||
|
// The user is not authenticated, handle it here.
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (status === "loading") {
|
||||||
|
return "Loading or not authenticated..."
|
||||||
|
}
|
||||||
|
|
||||||
|
return "User is logged in"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Client Session Handling
|
||||||
|
|
||||||
|
Due to the way Next.js handles `getServerSideProps` / `getInitialProps`, every protected page load has to make a server-side request to check if the session is valid and then generate the requested page. This alternative solution allows for showing a loading state on the initial check and every page transition afterward will be client-side, without having to check with the server and regenerate pages.
|
||||||
|
|
||||||
|
```js title="pages/admin.jsx"
|
||||||
|
export default function AdminDashboard() {
|
||||||
|
const { data: session } = useSession()
|
||||||
|
// session is always non-null inside this page, all the way down the React tree.
|
||||||
|
return "Some super secret dashboard"
|
||||||
|
}
|
||||||
|
|
||||||
|
AdminDashboard.auth = true
|
||||||
|
```
|
||||||
|
|
||||||
|
```jsx title="pages/_app.jsx"
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session}>
|
||||||
|
{Component.auth ? (
|
||||||
|
<Auth>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</Auth>
|
||||||
|
) : (
|
||||||
|
<Component {...pageProps} />
|
||||||
|
)}
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Auth({ children }) {
|
||||||
|
// if `{ required: true }` is supplied, `status` can only be "loading" or "authenticated"
|
||||||
|
const { status } = useSession({ required: true })
|
||||||
|
|
||||||
|
if (status === "loading") {
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It can be easily extended/modified to support something like an options object for role based authentication on pages. An example:
|
||||||
|
|
||||||
|
```jsx title="pages/admin.jsx"
|
||||||
|
AdminDashboard.auth = {
|
||||||
|
role: "admin",
|
||||||
|
loading: <AdminLoadingSkeleton />,
|
||||||
|
unauthorized: "/login-with-different-user", // redirect to this url
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Because of how `_app` is written, it won't unnecessarily contact the `/api/auth/session` endpoint for pages that do not require authentication.
|
||||||
|
|
||||||
|
More information can be found in the following [GitHub Issue](https://github.com/nextauthjs/next-auth/issues/1210).
|
||||||
|
|
||||||
|
### Updating the session
|
||||||
|
|
||||||
|
The `useSession()` hook exposes a `update(data?: any): Promise<Session | null>` method that can be used to update the session, without reloading the page.
|
||||||
|
|
||||||
|
You can optionally pass an arbitrary object as the first argument, which will be accessible on the server to merge with the session object.
|
||||||
|
|
||||||
|
If you are not passing any argument, the session will be reloaded from the server. (This is useful if you want to update the session after a server-side mutation, like updating in the database.)
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
The data object is coming from the client, so it needs to be validated on the server before saving.
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```tsx title="pages/profile.tsx"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const { data: session, status, update } = useSession()
|
||||||
|
|
||||||
|
if (status === "authenticated") {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>Signed in as {session.user.name}</p>
|
||||||
|
|
||||||
|
{/* Update the value by sending it to the backend. */}
|
||||||
|
<button onClick={() => update({ name: "John Doe" })}>Edit name</button>
|
||||||
|
{/*
|
||||||
|
* Only trigger a session update, assuming you already updated the value server-side.
|
||||||
|
* All `useSession().data` references will be updated.
|
||||||
|
*/}
|
||||||
|
<button onClick={() => update()}>Edit name</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <a href="/api/auth/signin">Sign in</a>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Assuming a `strategy: "jwt"` is used, the `update()` method will trigger a `jwt` callback with the `trigger: "update"` option. You can use this to update the session object on the server.
|
||||||
|
|
||||||
|
```ts title="pages/api/auth/[...nextauth].ts"
|
||||||
|
...
|
||||||
|
export default NextAuth({
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
// Using the `...rest` parameter to be able to narrow down the type based on `trigger`
|
||||||
|
jwt({ token, trigger, session }) {
|
||||||
|
if (trigger === "update" && session?.name) {
|
||||||
|
// Note, that `session` can be any arbitrary object, remember to validate it!
|
||||||
|
token.name = session.name
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Assuming a `strategy: "database"` is used, the `update()` method will trigger the `session` callback with the `trigger: "update"` option. You can use this to update the session object on the server.
|
||||||
|
|
||||||
|
```ts title="pages/api/auth/[...nextauth].ts"
|
||||||
|
...
|
||||||
|
const adapter = PrismaAdapter(prisma)
|
||||||
|
export default NextAuth({
|
||||||
|
...
|
||||||
|
adapter,
|
||||||
|
callbacks: {
|
||||||
|
// Using the `...rest` parameter to be able to narrow down the type based on `trigger`
|
||||||
|
async session({ session, trigger, newSession }) {
|
||||||
|
// Note, that `rest.session` can be any arbitrary object, remember to validate it!
|
||||||
|
if (trigger === "update" && newSession?.name) {
|
||||||
|
// You can update the session in the database if it's not already updated.
|
||||||
|
// await adapter.updateUser(session.user.id, { name: newSession.name })
|
||||||
|
|
||||||
|
// Make sure the updated value is reflected on the client
|
||||||
|
session.name = newSession.name
|
||||||
|
}
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Refetching the session
|
||||||
|
|
||||||
|
[`SessionProvider#refetchInterval`](#refetch-interval) and [`SessionProvider#refetchOnWindowFocus`](#refetch-on-window-focus) can be replaced with the `update()` method too.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The `update()` method won't sync between tabs as the `refetchInterval` and `refetchOnWindowFocus` options do.
|
||||||
|
:::
|
||||||
|
|
||||||
|
```tsx title="pages/profile.tsx"
|
||||||
|
import { useEffect } from "react"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const { data: session, status, update } = useSession()
|
||||||
|
|
||||||
|
// Polling the session every 1 hour
|
||||||
|
useEffect(() => {
|
||||||
|
// TIP: You can also use `navigator.onLine` and some extra event handlers
|
||||||
|
// to check if the user is online and only update the session if they are.
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine
|
||||||
|
const interval = setInterval(() => update(), 1000 * 60 * 60)
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
}, [update])
|
||||||
|
|
||||||
|
// Listen for when the page is visible, if the user switches tabs
|
||||||
|
// and makes our tab visible again, re-fetch the session
|
||||||
|
useEffect(() => {
|
||||||
|
const visibilityHandler = () =>
|
||||||
|
document.visibilityState === "visible" && update()
|
||||||
|
window.addEventListener("visibilitychange", visibilityHandler, false)
|
||||||
|
return () =>
|
||||||
|
window.removeEventListener("visibilitychange", visibilityHandler, false)
|
||||||
|
}, [update])
|
||||||
|
|
||||||
|
return <pre>{JSON.stringify(session, null, 2)}</pre>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## getSession()
|
||||||
|
|
||||||
|
- Client Side: **Yes**
|
||||||
|
- Server Side: **No** (See: [`getServerSession()`](/configuration/nextjs#getserversession)
|
||||||
|
|
||||||
|
NextAuth.js provides a `getSession()` helper which should be called **client side only** to return the current active session.
|
||||||
|
|
||||||
|
On the server side, **this is still available to use**, however, we recommend using `getServerSession` going forward. The idea behind this is to avoid an additional unnecessary `fetch` call on the server side. For more information, please check out [this issue](https://github.com/nextauthjs/next-auth/issues/1535).
|
||||||
|
|
||||||
|
This helper is helpful in case you want to read the session outside of the context of React.
|
||||||
|
|
||||||
|
When called, `getSession()` will send a request to `/api/auth/session` and returns a promise with a [session object](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/core/types.ts#L407-L425), or `null` if no session exists.
|
||||||
|
|
||||||
|
```js
|
||||||
|
async function myFunction() {
|
||||||
|
const session = await getSession()
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Read the tutorial [securing pages and API routes](/tutorials/securing-pages-and-api-routes) to know how to fetch the session in server side calls using `getServerSession()`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## getCsrfToken()
|
||||||
|
|
||||||
|
- Client Side: **Yes**
|
||||||
|
- Server Side: **Yes**
|
||||||
|
|
||||||
|
The `getCsrfToken()` method returns the current Cross Site Request Forgery Token (CSRF Token) required to make POST requests (e.g. for signing in and signing out).
|
||||||
|
|
||||||
|
You likely only need to use this if you are not using the built-in `signIn()` and `signOut()` methods.
|
||||||
|
|
||||||
|
#### Client Side Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
async function myFunction() {
|
||||||
|
const csrfToken = await getCsrfToken()
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Server Side Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { getCsrfToken } from "next-auth/react"
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
const csrfToken = await getCsrfToken({ req })
|
||||||
|
/* ... */
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## getProviders()
|
||||||
|
|
||||||
|
- Client Side: **Yes**
|
||||||
|
- Server Side: **Yes**
|
||||||
|
|
||||||
|
The `getProviders()` method returns the list of providers currently configured for sign in.
|
||||||
|
|
||||||
|
It calls `/api/auth/providers` and returns a list of the currently configured authentication providers.
|
||||||
|
|
||||||
|
It can be useful if you are creating a dynamic custom sign in page.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### API Route
|
||||||
|
|
||||||
|
```jsx title="pages/api/example.js"
|
||||||
|
import { getProviders } from "next-auth/react"
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
const providers = await getProviders()
|
||||||
|
console.log("Providers", providers)
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Unlike `getCsrfToken()`, when calling `getProviders()` server side, you don't need to pass anything, just as calling it client side.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## signIn()
|
||||||
|
|
||||||
|
- Client Side: **Yes**
|
||||||
|
- Server Side: No
|
||||||
|
|
||||||
|
Using the `signIn()` method ensures the user ends back on the page they started on after completing a sign in flow. It will also handle CSRF Tokens for you automatically when signing in with email.
|
||||||
|
|
||||||
|
The `signIn()` method can be called from the client in different ways, as shown below.
|
||||||
|
|
||||||
|
### Redirects to sign in page when clicked
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { signIn } from "next-auth/react"
|
||||||
|
|
||||||
|
export default () => <button onClick={() => signIn()}>Sign in</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Starts OAuth sign-in flow when clicked
|
||||||
|
|
||||||
|
By default, when calling the `signIn()` method with no arguments, you will be redirected to the NextAuth.js sign-in page. If you want to skip that and get redirected to your provider's page immediately, call the `signIn()` method with the provider's `id`.
|
||||||
|
|
||||||
|
For example to sign in with Google:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { signIn } from "next-auth/react"
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<button onClick={() => signIn("google")}>Sign in with Google</button>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Starts Email sign-in flow when clicked
|
||||||
|
|
||||||
|
When using it with the email flow, pass the target `email` as an option.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { signIn } from "next-auth/react"
|
||||||
|
|
||||||
|
export default ({ email }) => (
|
||||||
|
<button onClick={() => signIn("email", { email })}>Sign in with Email</button>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specifying a `callbackUrl`
|
||||||
|
|
||||||
|
The `callbackUrl` specifies to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
|
||||||
|
|
||||||
|
You can specify a different `callbackUrl` by specifying it as the second argument of `signIn()`. This works for all providers.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
- `signIn(undefined, { callbackUrl: '/foo' })`
|
||||||
|
- `signIn('google', { callbackUrl: 'http://localhost:3000/bar' })`
|
||||||
|
- `signIn('email', { email, callbackUrl: 'http://localhost:3000/foo' })`
|
||||||
|
|
||||||
|
The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect-callback). By default it requires the URL to be an absolute URL at the same host name, or a relative url starting with a slash. If it does not match it will redirect to the homepage. You can define your own [redirect callback](/configuration/callbacks#redirect-callback) to allow other URLs.
|
||||||
|
|
||||||
|
### Using the `redirect: false` option
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The redirect option is only available for `credentials` and `email` providers.
|
||||||
|
:::
|
||||||
|
|
||||||
|
In some cases, you might want to deal with the sign in response on the same page and disable the default redirection. For example, if an error occurs (like wrong credentials given by the user), you might want to handle the error on the same page. For that, you can pass `redirect: false` in the second parameter object.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
- `signIn('credentials', { redirect: false, password: 'password' })`
|
||||||
|
- `signIn('email', { redirect: false, email: 'bill@fillmurray.com' })`
|
||||||
|
|
||||||
|
`signIn` will then return a Promise, that resolves to the following:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Will be different error codes,
|
||||||
|
* depending on the type of error.
|
||||||
|
*/
|
||||||
|
error: string | undefined
|
||||||
|
/**
|
||||||
|
* HTTP status code,
|
||||||
|
* hints the kind of error that happened.
|
||||||
|
*/
|
||||||
|
status: number
|
||||||
|
/**
|
||||||
|
* `true` if the signin was successful
|
||||||
|
*/
|
||||||
|
ok: boolean
|
||||||
|
/**
|
||||||
|
* `null` if there was an error,
|
||||||
|
* otherwise the url the user
|
||||||
|
* should have been redirected to.
|
||||||
|
*/
|
||||||
|
url: string | null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Additional parameters
|
||||||
|
|
||||||
|
It is also possible to pass additional parameters to the `/authorize` endpoint through the third argument of `signIn()`.
|
||||||
|
|
||||||
|
See the [Authorization Request OIDC spec](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) for some ideas. (These are not the only possible ones, all parameters will be forwarded)
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
- `signIn("identity-server4", null, { prompt: "login" })` _always ask the user to re-authenticate_
|
||||||
|
- `signIn("auth0", null, { login_hint: "info@example.com" })` _hints the e-mail address to the provider_
|
||||||
|
|
||||||
|
:::note
|
||||||
|
You can also set these parameters through [`provider.authorizationParams`](/configuration/providers/oauth#options).
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The following parameters are always overridden server-side: `redirect_uri`, `state`
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## signOut()
|
||||||
|
|
||||||
|
- Client Side: **Yes**
|
||||||
|
- Server Side: No
|
||||||
|
|
||||||
|
In order to logout, use the `signOut()` method to ensure the user ends back on the page they started on after completing the sign out flow. It also handles CSRF tokens for you automatically.
|
||||||
|
|
||||||
|
It reloads the page in the browser when complete.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { signOut } from "next-auth/react"
|
||||||
|
|
||||||
|
export default () => <button onClick={() => signOut()}>Sign out</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specifying a `callbackUrl`
|
||||||
|
|
||||||
|
As with the `signIn()` function, you can specify a `callbackUrl` parameter by passing it as an option.
|
||||||
|
|
||||||
|
e.g. `signOut({ callbackUrl: 'http://localhost:3000/foo' })`
|
||||||
|
|
||||||
|
The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect-callback). By default, it requires the URL to be an absolute URL at the same host name, or you can also supply a relative URL starting with a slash. If it does not match it will redirect to the homepage. You can define your own [redirect callback](/configuration/callbacks#redirect-callback) to allow other URLs.
|
||||||
|
|
||||||
|
### Using the `redirect: false` option
|
||||||
|
|
||||||
|
If you pass `redirect: false` to `signOut`, the page will not reload. The session will be deleted, and the `useSession` hook is notified, so any indication about the user will be shown as logged out automatically. It can give a very nice experience for the user.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If you need to redirect to another page but you want to avoid a page reload, you can try:
|
||||||
|
`const data = await signOut({redirect: false, callbackUrl: "/foo"})`
|
||||||
|
where `data.url` is the validated URL you can redirect the user to without any flicker by using Next.js's `useRouter().push(data.url)`
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SessionProvider
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you are using the App Router, we encourage you to use [`getServerSession`](/configuration/nextjs#getserversession) in server contexts instead. (`SessionProvider` _can_ be used in the App Router, which might be the easier choice if you are migrating from pages.)
|
||||||
|
:::
|
||||||
|
|
||||||
|
Using the supplied `<SessionProvider>` allows instances of `useSession()` to share the session object across components, by using [React Context](https://react.dev/learn/passing-data-deeply-with-context) under the hood. It also takes care of keeping the session updated and synced between tabs/windows.
|
||||||
|
|
||||||
|
```jsx title="pages/_app.js"
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you pass the `session` page prop to the `<SessionProvider>` – as in the example above – you can avoid checking the session twice on pages that support both server and client side rendering.
|
||||||
|
|
||||||
|
This only works on pages where you provide the correct `pageProps`, however. This is normally done in `getInitialProps` or `getServerSideProps` on an individual page basis like so:
|
||||||
|
|
||||||
|
```js title="pages/index.js"
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
import { authOptions } from './api/auth/[...nextauth]'
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
export async function getServerSideProps({ req, res }) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
session: await getServerSession(req, res, authOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If every one of your pages needs to be protected, you can do this in `getInitialProps` in `_app`, otherwise you can do it on a page-by-page basis. Alternatively, you can do per page authentication checks client side, instead of having each authentication check be blocking (SSR) by using the method described below in [alternative client session handling](#custom-client-session-handling).
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
The session state is automatically synchronized across all open tabs/windows and they are all updated whenever they gain or lose focus or the state changes (e.g. a user signs in or out) when `refetchOnWindowFocus` is `true`.
|
||||||
|
|
||||||
|
If you have session expiry times of 30 days (the default) or more then you probably don't need to change any of the default options in the Provider. If you need to, you can trigger an update of the session object across all tabs/windows by calling [`getSession()`](/getting-started/client#getsession) from a client side function.
|
||||||
|
|
||||||
|
However, if you need to customize the session behavior and/or are using short session expiry times, you can pass options to the provider to customize the behavior of the `useSession()` hook.
|
||||||
|
|
||||||
|
```jsx title="pages/_app.js"
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SessionProvider
|
||||||
|
session={session}
|
||||||
|
// Default base path if your app lives at the root "/"
|
||||||
|
basePath="/"
|
||||||
|
// Re-fetch session every 5 minutes
|
||||||
|
refetchInterval={5 * 60}
|
||||||
|
// Re-fetches session when window is focused
|
||||||
|
refetchOnWindowFocus={true}
|
||||||
|
>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
**These options have no effect on clients that are not signed in.**
|
||||||
|
|
||||||
|
Every tab/window maintains its own copy of the local session state; the session is not stored in shared storage like localStorage or sessionStorage. Any update in one tab/window triggers a message to other tabs/windows to update their own session state.
|
||||||
|
|
||||||
|
Using low values for `refetchInterval` will increase network traffic and load on authenticated clients and may impact hosting costs and performance.
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Base path
|
||||||
|
|
||||||
|
If you are using a custom base path, and your application entry point is not at the root of the domain "/" but something else, for example "/my-app/" you can use the `basePath` prop to make NextAuth.js aware of that so that all redirects and session handling work as expected.
|
||||||
|
|
||||||
|
#### Refetch interval
|
||||||
|
|
||||||
|
See [Session Refetching](#refetching-the-session) for an alternative option.
|
||||||
|
|
||||||
|
The `refetchInterval` option can be used to contact the server to avoid a session expiring.
|
||||||
|
|
||||||
|
When `refetchInterval` is set to `0` (the default) there will be no session polling.
|
||||||
|
|
||||||
|
If set to any value other than zero, it specifies in seconds how often the client should contact the server to update the session state. If the session state has expired when it is triggered, all open tabs/windows will be updated to reflect this.
|
||||||
|
|
||||||
|
The value for `refetchInterval` should always be lower than the value of the session `maxAge` [session option](/configuration/options#session).
|
||||||
|
|
||||||
|
By default, session polling will keep trying, even when the device has no internet access. To circumvent this, you can also set `refetchWhenOffline` to `false`. This will use [`navigator.onLine`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine) to only poll when the device is online.
|
||||||
|
|
||||||
|
#### Refetch On Window Focus
|
||||||
|
|
||||||
|
See [Session Refetching](#refetching-the-session) for an alternative option.
|
||||||
|
|
||||||
|
The `refetchOnWindowFocus` option can be used to control whether it automatically updates the session state when you switch a focus on tabs/windows.
|
||||||
|
|
||||||
|
When `refetchOnWindowFocus` is set to `true` (the default) tabs/windows will be updated and initialize the components' state when they gain or lose focus.
|
||||||
|
|
||||||
|
However, if it was set to `false`, it stops re-fetching the session and the components will stay as it is.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
See [**the Next.js documentation**](https://nextjs.org/docs/advanced-features/custom-app) for more information on **\_app.js** in Next.js applications.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Custom base path
|
||||||
|
|
||||||
|
When your Next.js application uses a custom base path, set the `NEXTAUTH_URL` environment variable to the route to the API endpoint in full - as in the example below and as explained [here](/configuration/options#nextauth_url).
|
||||||
|
|
||||||
|
Also, make sure to pass the `basePath` page prop to the `<SessionProvider>` – as in the example below – so your custom base path is fully configured and used by NextAuth.js.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
In this example, the custom base path used is `/custom-route`.
|
||||||
|
|
||||||
|
```
|
||||||
|
NEXTAUTH_URL=https://example.com/custom-route/api/auth
|
||||||
|
```
|
||||||
|
|
||||||
|
```jsx title="pages/_app.js"
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session} basePath="/custom-route/api/auth">
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
---
|
||||||
|
id: example
|
||||||
|
title: Getting Started
|
||||||
|
---
|
||||||
|
|
||||||
|
The example code below describes how to add authentication to a Next.js app.
|
||||||
|
|
||||||
|
## New Project
|
||||||
|
|
||||||
|
The easiest way to get started is to clone the [example app](https://github.com/nextauthjs/next-auth-example) and follow the instructions in README.md. You can try out a live demo at [https://next-auth-example.vercel.app/](https://next-auth-example.vercel.app/)
|
||||||
|
|
||||||
|
## Existing Project
|
||||||
|
|
||||||
|
### Install NextAuth
|
||||||
|
|
||||||
|
```bash npm2yarn2pnpm
|
||||||
|
npm install next-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
:::info
|
||||||
|
If you are using TypeScript, NextAuth.js comes with its types definitions within the package. To learn more about TypeScript for `next-auth`, check out the [TypeScript documentation](/getting-started/typescript)
|
||||||
|
:::
|
||||||
|
|
||||||
|
|
||||||
|
### Add API route
|
||||||
|
|
||||||
|
To add NextAuth.js to a project create a file called `[...nextauth].js` in `pages/api/auth`. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
|
||||||
|
|
||||||
|
If you're using [Next.js 13.2](https://nextjs.org/blog/next-13-2#custom-route-handlers) or above with the new App Router (`app/`), you can initialize the configuration using the new [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) by following our [guide](https://next-auth.js.org/configuration/initialization#route-handlers-app).
|
||||||
|
|
||||||
|
```javascript title="pages/api/auth/[...nextauth].js" showLineNumbers
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
import GithubProvider from "next-auth/providers/github"
|
||||||
|
|
||||||
|
export const authOptions = {
|
||||||
|
// Configure one or more authentication providers
|
||||||
|
providers: [
|
||||||
|
GithubProvider({
|
||||||
|
clientId: process.env.GITHUB_ID,
|
||||||
|
clientSecret: process.env.GITHUB_SECRET,
|
||||||
|
}),
|
||||||
|
// ...add more providers here
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NextAuth(authOptions)
|
||||||
|
```
|
||||||
|
|
||||||
|
All requests to `/api/auth/*` (`signIn`, `callback`, `signOut`, etc.) will automatically be handled by NextAuth.js.
|
||||||
|
|
||||||
|
**Further Reading**:
|
||||||
|
|
||||||
|
- See the [options documentation](/configuration/options) for more details on how to configure providers, databases and other options.
|
||||||
|
- Read more about how to add authentication providers [here](/providers).
|
||||||
|
|
||||||
|
#### Configure Shared session state
|
||||||
|
|
||||||
|
To be able to use `useSession` first you'll need to expose the session context, [`<SessionProvider />`](/getting-started/client#sessionprovider), at the top level of your application:
|
||||||
|
|
||||||
|
```jsx title="pages/_app.jsx" showLineNumbers
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Instances of `useSession` will then have access to the session data and status. The `<SessionProvider />` also takes care of keeping the session updated and synced between browser tabs and windows.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Check out the [client documentation](/getting-started/client) to see how you can improve the user experience and page performance by using the NextAuth.js client.
|
||||||
|
If you are using the Next.js App Router, please note that `<SessionProvider />` requires a client component and therefore cannot be put inside the root layout. For more details, check out the [Next.js documentation](https://nextjs.org/docs/app/getting-started/layouts-and-pages).
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Frontend - Add React Hook
|
||||||
|
|
||||||
|
The [`useSession()`](/getting-started/client#usesession) React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
|
||||||
|
|
||||||
|
```jsx title="components/login-btn.jsx" showLineNumbers
|
||||||
|
import { useSession, signIn, signOut } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Component() {
|
||||||
|
const { data: session } = useSession()
|
||||||
|
if (session) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
Signed in as {session.user.email} <br />
|
||||||
|
<button onClick={() => signOut()}>Sign out</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
Not signed in <br />
|
||||||
|
<button onClick={() => signIn()}>Sign in</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the `useSession` hook from anywhere in your application (e.g. in a header component).
|
||||||
|
|
||||||
|
### Backend - API Route
|
||||||
|
|
||||||
|
To protect an API Route, you can use the [`getServerSession()`](/configuration/nextjs#unstable_getserversession) method.
|
||||||
|
|
||||||
|
```javascript title="pages/api/restricted.js" showLineNumbers
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
import { authOptions } from "./auth/[...nextauth]"
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
const session = await getServerSession(req, res, authOptions)
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
res.send({
|
||||||
|
content:
|
||||||
|
"This is protected content. You can access this content because you are signed in.",
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.send({
|
||||||
|
error: "You must be signed in to view the protected content on this page.",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extensibility
|
||||||
|
|
||||||
|
#### Using NextAuth.js Callbacks
|
||||||
|
|
||||||
|
NextAuth.js allows you to hook into various parts of the authentication flow via our [built-in callbacks](/configuration/callbacks).
|
||||||
|
|
||||||
|
For example, to pass a value from the sign-in to the frontend, client-side, you can use a combination of the [`session`](/configuration/callbacks#session-callback) and [`jwt`](/configuration/callbacks#jwt-callback) callback like so:
|
||||||
|
|
||||||
|
```javascript title="pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async jwt({ token, account }) {
|
||||||
|
// Persist the OAuth access_token to the token right after signin
|
||||||
|
if (account) {
|
||||||
|
// highlight-next-line
|
||||||
|
token.accessToken = account.access_token
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
},
|
||||||
|
async session({ session, token, user }) {
|
||||||
|
// Send properties to the client, like an access_token from a provider.
|
||||||
|
// highlight-next-line
|
||||||
|
session.accessToken = token.accessToken
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Now whenever you call [`getSession`](/getting-started/client#getsession) or [`useSession`](/getting-started/client#usesession), the data object which is returned will include the `accessToken` value.
|
||||||
|
|
||||||
|
```jsx title="components/accessToken.jsx" showLineNumbers
|
||||||
|
import { useSession, signIn, signOut } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Component() {
|
||||||
|
// highlight-next-line
|
||||||
|
const { data } = useSession()
|
||||||
|
const { accessToken } = data
|
||||||
|
|
||||||
|
return <div>Access Token: {accessToken}</div>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuring callback URL (OAuth only)
|
||||||
|
|
||||||
|
If you are using an OAuth provider either through one of our [built-in providers](/configuration/providers/oauth)
|
||||||
|
or through a [custom provider](/configuration/providers/oauth#using-a-custom-provider), you'll need to configure
|
||||||
|
a callback URL in your provider's settings. Each provider has a "Configuration" section that should give you pointers on how to do that.
|
||||||
|
|
||||||
|
Follow [these steps](/configuration/providers/oauth#how-to) to learn how to integrate with an OAuth provider.
|
||||||
|
|
||||||
|
## Deploying to production
|
||||||
|
|
||||||
|
When deploying your site set the `NEXTAUTH_URL` environment variable to the canonical URL of the website.
|
||||||
|
|
||||||
|
```
|
||||||
|
NEXTAUTH_URL=https://example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
In production, this needs to be set as an environment variable on the service you use to deploy your app.
|
||||||
|
|
||||||
|
To set environment variables on Vercel, you can use the [dashboard](https://vercel.com/dashboard) or the `vercel env pull` [command](https://vercel.com/docs/build-step#development-environment-variables).
|
||||||
|
:::
|
||||||
|
|
||||||
|
For more information please check out our [deployment page](/deployment).
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
id: introduction
|
||||||
|
title: Introduction
|
||||||
|
---
|
||||||
|
|
||||||
|
## About NextAuth.js
|
||||||
|
|
||||||
|
NextAuth.js is a complete open-source authentication solution for [Next.js](http://nextjs.org/) applications.
|
||||||
|
|
||||||
|
It is designed from the ground up to support Next.js and Serverless.
|
||||||
|
|
||||||
|
[Check out the example code](/getting-started/example) to see how easy it is to use NextAuth.js for authentication.
|
||||||
|
|
||||||
|
### Flexible and easy to use
|
||||||
|
|
||||||
|
- Designed to work with any [OAuth service, it supports OAuth 1.0, 1.0A, 2.0 and OpenID Connect](/providers)
|
||||||
|
- Built-in support for [many popular sign-in services](/configuration/providers/oauth)
|
||||||
|
- Supports [email / passwordless authentication](/providers/email)
|
||||||
|
- Supports stateless authentication with [any backend](https://authjs.dev/getting-started/database) (Active Directory, LDAP, etc)
|
||||||
|
- Supports both JSON Web Tokens and database sessions
|
||||||
|
- Designed for Serverless but runs anywhere (AWS Lambda, Docker, Heroku, etc…)
|
||||||
|
|
||||||
|
### Own your own data
|
||||||
|
|
||||||
|
NextAuth.js can be used with or without a database.
|
||||||
|
|
||||||
|
- An open-source solution that allows you to keep control of your data
|
||||||
|
- Supports Bring Your Own Database (BYOD) and can be used with any database
|
||||||
|
- Built-in support for [MySQL, MariaDB, Postgres, SQL Server, MongoDB and SQLite](/configuration/databases)
|
||||||
|
- Works great with databases from popular hosting providers
|
||||||
|
- Can also be used _without a database_ (e.g. OAuth + JWT)
|
||||||
|
|
||||||
|
_Note: Email sign-in requires a database to be configured to store single-use verification tokens._
|
||||||
|
|
||||||
|
### Secure by default
|
||||||
|
|
||||||
|
- Promotes the use of passwordless sign-in mechanisms
|
||||||
|
- Designed to be secure by default and encourage best practices for safeguarding user data
|
||||||
|
- Uses Cross-Site Request Forgery Tokens on POST routes (sign in, sign out)
|
||||||
|
- Default cookie policy aims for the most restrictive policy appropriate for each cookie
|
||||||
|
- When JSON Web Tokens are enabled, they are encrypted by default (JWE) with A256GCM
|
||||||
|
- Auto-generates symmetric signing and encryption keys for developer convenience
|
||||||
|
- Features tab/window syncing and keepalive messages to support short-lived sessions
|
||||||
|
- Attempts to implement the latest guidance published by [Open Web Application Security Project](https://owasp.org/)
|
||||||
|
|
||||||
|
Advanced options allow you to define your own routines to handle controlling what accounts are allowed to sign in, for encoding and decoding JSON Web Tokens and to set custom cookie security policies and session properties, so you can control who can sign in and how often sessions have to be re-validated.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
NextAuth.js is now owned and maintained by [Better Auth Inc.](https://better-auth.com) The project continues to be open source and is only possible [thanks to contributors](/contributors).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
[Check out the example code](/getting-started/example) to see how easy it is to use NextAuth.js for authentication.
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
id: rest-api
|
||||||
|
title: REST API
|
||||||
|
---
|
||||||
|
|
||||||
|
NextAuth.js exposes a REST API that is used by the NextAuth.js client.
|
||||||
|
|
||||||
|
#### `GET` /api/auth/signin
|
||||||
|
|
||||||
|
Displays the built-in/unbranded sign-in page.
|
||||||
|
|
||||||
|
#### `POST` /api/auth/signin/:provider
|
||||||
|
|
||||||
|
Starts a provider-specific sign-in flow.
|
||||||
|
|
||||||
|
The POST submission requires CSRF token from `/api/auth/csrf`.
|
||||||
|
|
||||||
|
In case of an OAuth provider, calling this endpoint will initiate the Authorization Request to your Identity Provider.
|
||||||
|
Learn more about this in the [OAuth specification](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1).
|
||||||
|
|
||||||
|
In case of using the Email provider, calling this endpoint will send a sign-in URL to the user's e-mail address.
|
||||||
|
|
||||||
|
This endpoint is also used by the [`signIn`](/getting-started/client#signin) method internally.
|
||||||
|
|
||||||
|
#### `GET`/`POST` /api/auth/callback/:provider
|
||||||
|
|
||||||
|
Handles returning requests from OAuth services during sign-in.
|
||||||
|
|
||||||
|
For OAuth 2.0 providers that support the `checks: ["state"]` option, the state parameter is checked against the one that was generated when the sign in flow was started - this uses a hash of the CSRF token which MUST match for both the `POST` and `GET` calls during sign-in.
|
||||||
|
|
||||||
|
Learn more about this in the [OAuth specification](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2).
|
||||||
|
|
||||||
|
#### `GET` /api/auth/signout
|
||||||
|
|
||||||
|
Displays the built-in/unbranded sign out page.
|
||||||
|
|
||||||
|
#### `POST` /api/auth/signout
|
||||||
|
|
||||||
|
Handles signing the user out - this is a `POST` submission to prevent malicious links from triggering signing a user out without their consent. The user session will be invalidated/removed from the cookie/database, depending on the flow you chose to [store sessions](/configuration/options#session).
|
||||||
|
|
||||||
|
The `POST` submission requires CSRF token from `/api/auth/csrf`.
|
||||||
|
|
||||||
|
This endpoint is also used by the [`signOut`](/getting-started/client#signout) method internally.
|
||||||
|
|
||||||
|
#### `GET` /api/auth/session
|
||||||
|
|
||||||
|
Returns client-safe session object - or an empty object if there is no session.
|
||||||
|
|
||||||
|
The contents of the session object that is returned are configurable with the [`session` callback](/configuration/callbacks#session-callback).
|
||||||
|
|
||||||
|
#### `GET` /api/auth/csrf
|
||||||
|
|
||||||
|
Returns object containing CSRF token. In NextAuth.js, CSRF protection is present on all authentication routes. It uses the "double submit cookie method", which uses a signed HttpOnly, host-only cookie.
|
||||||
|
|
||||||
|
The CSRF token returned by this endpoint must be passed as form variable named `csrfToken` in all `POST` submissions to any API endpoint.
|
||||||
|
|
||||||
|
#### `GET` /api/auth/providers
|
||||||
|
|
||||||
|
Returns a list of configured OAuth services and details (e.g. sign in and callback URLs) for each service.
|
||||||
|
|
||||||
|
It is useful to dynamically generate custom sign up pages and to check what callback URLs are configured for each OAuth provider that is configured.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The default base path is `/api/auth` but it is configurable by specifying a custom path in `NEXTAUTH_URL`
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
`NEXTAUTH_URL=https://example.com/myapp/api/authentication`
|
||||||
|
|
||||||
|
`/api/auth/signin` -> `/myapp/api/authentication/signin`
|
||||||
|
:::
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
---
|
||||||
|
id: typescript
|
||||||
|
title: TypeScript
|
||||||
|
---
|
||||||
|
|
||||||
|
NextAuth.js has its own type definitions to use in your TypeScript projects safely. Even if you don't use TypeScript, IDEs like VSCode will pick this up to provide you with a better developer experience. While you are typing, you will get suggestions about what certain objects/functions look like, and sometimes links to documentation, examples, and other valuable resources.
|
||||||
|
|
||||||
|
Check out the example repository showcasing how to use `next-auth` on a Next.js application with TypeScript:
|
||||||
|
https://github.com/nextauthjs/next-auth-example
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Adapters
|
||||||
|
|
||||||
|
If you're writing your own custom Adapter, you can take advantage of the types to make sure your implementation conforms to what's expected:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { Adapter } from "next-auth/adapters"
|
||||||
|
|
||||||
|
function MyAdapter(): Adapter {
|
||||||
|
return {
|
||||||
|
// your adapter methods here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When writing your own custom Adapter in plain JavaScript, note that you can use **JSDoc** to get helpful editor hints and auto-completion like so:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/** @return { import("next-auth/adapters").Adapter } */
|
||||||
|
function MyAdapter() {
|
||||||
|
return {
|
||||||
|
// your adapter methods here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
This will work in code editors with a strong TypeScript integration like VSCode or WebStorm. It might not work if you're using more lightweight editors like VIM or Atom.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Module Augmentation
|
||||||
|
|
||||||
|
`next-auth` comes with certain types/interfaces that are shared across submodules. Good examples are `Session` and `JWT`. Ideally, you should only need to create these types at a single place, and TS should pick them up in every location where they are referenced. Luckily, Module Augmentation is exactly that, which can do this for us. Define your shared interfaces in a single place, and get type-safety across your application when using `next-auth` (or one of its submodules).
|
||||||
|
|
||||||
|
### Main module
|
||||||
|
|
||||||
|
Let's look at `Session`:
|
||||||
|
|
||||||
|
```ts title="pages/api/auth/[...nextauth].ts"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
export default NextAuth({
|
||||||
|
callbacks: {
|
||||||
|
session({ session, token, user }) {
|
||||||
|
return session // The return type will match the one returned in `useSession()`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts title="pages/index.ts"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function IndexPage() {
|
||||||
|
// `session` will match the returned value of `callbacks.session()` from `NextAuth()`
|
||||||
|
const { data: session } = useSession()
|
||||||
|
|
||||||
|
return (
|
||||||
|
// Your component
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To extend/augment this type, create a `types/next-auth.d.ts` file in your project:
|
||||||
|
|
||||||
|
```ts title="types/next-auth.d.ts"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
declare module "next-auth" {
|
||||||
|
/**
|
||||||
|
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
|
||||||
|
*/
|
||||||
|
interface Session {
|
||||||
|
user: {
|
||||||
|
/** The user's postal address. */
|
||||||
|
address: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Extend default interface properties
|
||||||
|
|
||||||
|
By default, TypeScript will merge new interface properties and overwrite existing ones. In this case, the default session user properties will be overwritten, with the new one defined above.
|
||||||
|
|
||||||
|
If you want to keep the default session user properties, you need to add them back into the newly declared interface:
|
||||||
|
|
||||||
|
```ts title="types/next-auth.d.ts"
|
||||||
|
import NextAuth, { DefaultSession } from "next-auth"
|
||||||
|
|
||||||
|
declare module "next-auth" {
|
||||||
|
/**
|
||||||
|
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
|
||||||
|
*/
|
||||||
|
interface Session {
|
||||||
|
user: {
|
||||||
|
/** The user's postal address. */
|
||||||
|
address: string
|
||||||
|
} & DefaultSession["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Popular interfaces to augment
|
||||||
|
|
||||||
|
Although you can augment almost anything, here are some of the more common interfaces that you might want to override in the `next-auth` module:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
/**
|
||||||
|
* The shape of the user object returned in the OAuth providers' `profile` callback,
|
||||||
|
* or the second parameter of the `session` callback, when using a database.
|
||||||
|
*/
|
||||||
|
interface User {}
|
||||||
|
/**
|
||||||
|
* Usually contains information about the provider being used
|
||||||
|
* and also extends `TokenSet`, which is different tokens returned by OAuth Providers.
|
||||||
|
*/
|
||||||
|
interface Account {}
|
||||||
|
/** The OAuth profile returned from your provider */
|
||||||
|
interface Profile {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure that the `types` folder is added to [`typeRoots`](https://www.typescriptlang.org/tsconfig/#typeRoots) in your project's `tsconfig.json` file.
|
||||||
|
|
||||||
|
### Submodules
|
||||||
|
|
||||||
|
The `JWT` interface can be found in the `next-auth/jwt` submodule:
|
||||||
|
|
||||||
|
```ts title="types/next-auth.d.ts"
|
||||||
|
import { JWT } from "next-auth/jwt"
|
||||||
|
|
||||||
|
declare module "next-auth/jwt" {
|
||||||
|
/** Returned by the `jwt` callback and `getToken`, when using JWT sessions */
|
||||||
|
interface JWT {
|
||||||
|
/** OpenID ID Token */
|
||||||
|
idToken?: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Useful links
|
||||||
|
|
||||||
|
1. [TypeScript documentation: Module Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
|
||||||
|
2. [Digital Ocean: Module Augmentation in TypeScript](https://www.digitalocean.com/community/tutorials/typescript-module-augmentation)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions of any kind are always welcome, especially for TypeScript. Please keep in mind that we are a small team working on this project in our free time. We will try our best to give support, but if you think you have a solution for a problem, please open a PR!
|
||||||
|
|
||||||
|
:::note
|
||||||
|
When contributing to TypeScript, if the actual JavaScript user API does not change in a breaking manner, we reserve the right to push any TypeScript change in a minor release. This ensures that we can keep on a faster release cycle.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,613 @@
|
|||||||
|
---
|
||||||
|
id: upgrade-v4
|
||||||
|
title: Upgrade Guide (v4)
|
||||||
|
---
|
||||||
|
|
||||||
|
NextAuth.js version 4 includes a few breaking changes from the last major version (3.x). So we're here to help you upgrade your applications as smoothly as possible. It should be possible to upgrade from any version of 3.x to the latest 4 release by following the next few migration steps.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Version 4 has been released to GA 🚨
|
||||||
|
|
||||||
|
We encourage users to try it out and report any and all issues they come across.
|
||||||
|
:::
|
||||||
|
|
||||||
|
You can upgrade to the new version by running:
|
||||||
|
|
||||||
|
```bash npm2yarn2pnpm
|
||||||
|
npm install next-auth
|
||||||
|
```
|
||||||
|
|
||||||
|
## `next-auth/jwt`
|
||||||
|
|
||||||
|
We no longer have a default export in `next-auth/jwt`.
|
||||||
|
To comply with this, change the following:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- import jwt from "next-auth/jwt"
|
||||||
|
+ import { getToken } from "next-auth/jwt"
|
||||||
|
```
|
||||||
|
|
||||||
|
## `next-auth/react`
|
||||||
|
|
||||||
|
We've renamed the client-side import source to `next-auth/react`. To comply with this change, you will simply have to rename anywhere you were using `next-auth/client`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- import { useSession } from "next-auth/client"
|
||||||
|
+ import { useSession } from "next-auth/react"
|
||||||
|
```
|
||||||
|
|
||||||
|
We've also made the following changes to the names of the exports:
|
||||||
|
|
||||||
|
- `setOptions`: Not exposed anymore, use [`SessionProvider` props](https://next-auth.js.org/getting-started/client#options)
|
||||||
|
- `options`: Not exposed anymore, [use `SessionProvider` props](https://next-auth.js.org/getting-started/client#options)
|
||||||
|
- `session`: Renamed to `getSession`
|
||||||
|
- `providers`: Renamed to `getProviders`
|
||||||
|
- `csrfToken`: Renamed to `getCsrfToken`
|
||||||
|
- `signin`: Renamed to `signIn`
|
||||||
|
- `signout`: Renamed to `signOut`
|
||||||
|
- `Provider`: Renamed to `SessionProvider`
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.12
|
||||||
|
|
||||||
|
## `SessionProvider`
|
||||||
|
|
||||||
|
Version 4 makes using the `SessionProvider` mandatory. This means that you will have to wrap any part of your application using `useSession` in this provider, if you were not doing so already. The `SessionProvider` has also undergone a few further changes:
|
||||||
|
|
||||||
|
- `Provider` is renamed to `SessionProvider`
|
||||||
|
- The options prop is now flattened as the props of SessionProvider.
|
||||||
|
- `keepAlive` has been renamed to `refetchInterval`.
|
||||||
|
- `clientMaxAge` has been removed in favor of `refetchInterval`, as they overlap in functionality, with the difference that `refetchInterval` will keep re-fetching the session periodically in the background.
|
||||||
|
|
||||||
|
The best practice for wrapping your app in Providers is to do so in your `pages/_app.jsx` file.
|
||||||
|
|
||||||
|
An example use-case with these new changes:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
// `session` comes from `getServerSideProps` or `getInitialProps`.
|
||||||
|
// Avoids flickering/session loading on first load.
|
||||||
|
<SessionProvider session={session} refetchInterval={5 * 60}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.12
|
||||||
|
|
||||||
|
## Providers
|
||||||
|
|
||||||
|
Providers now need to be imported individually.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- import Provider from "next-auth/providers"
|
||||||
|
- Providers.Auth0({...})
|
||||||
|
- Providers.Google({...})
|
||||||
|
+ import Auth0Provider from "next-auth/providers/auth0"
|
||||||
|
+ import GoogleProvider from "next-auth/providers/google"
|
||||||
|
+ Auth0Provider({...})
|
||||||
|
+ GoogleProvider({...})
|
||||||
|
```
|
||||||
|
|
||||||
|
1. The `AzureADB2C` provider has been renamed `AzureAD`.
|
||||||
|
2. The `Basecamp` provider has been removed, see explanation [here](https://github.com/basecamp/api/blob/master/sections/authentication.md#on-authenticating-users-via-oauth).
|
||||||
|
3. The GitHub provider by default now will not request full write access to user profiles. If you need this scope, please add `user` to the scope option manually.
|
||||||
|
|
||||||
|
The following new options are available when defining your Providers in the configuration:
|
||||||
|
|
||||||
|
1. `authorization` (replaces `authorizationUrl`, `authorizationParams`, `scope`)
|
||||||
|
2. `token` replaces (`accessTokenUrl`, `headers`, `params`)
|
||||||
|
3. `userinfo` (replaces `profileUrl`)
|
||||||
|
4. `issuer`(replaces `domain`)
|
||||||
|
|
||||||
|
For more details on their usage, please see [options](/configuration/providers/oauth#options) section of the OAuth Provider documentation.
|
||||||
|
|
||||||
|
When submitting a new OAuth provider to the repository, the `profile` callback is expected to only return these fields from now on: `id`, `name`, `email`, and `image`. If any of these are missing values, they should be set to `null`.
|
||||||
|
|
||||||
|
Also worth noting is that `id` is expected to be returned as a `string` type (For example if your provider returns it as a number, you can cast it by using the `.toString()` method). This makes the returned profile object comply across all providers/accounts/adapters, and hopefully cause less confusion in the future.
|
||||||
|
|
||||||
|
Implemented in: https://github.com/nextauthjs/next-auth/pull/2411
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.20
|
||||||
|
|
||||||
|
## `useSession` Hook
|
||||||
|
|
||||||
|
The `useSession` hook has been updated to return an object. This allows you to test states much more cleanly with the new `status` option.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- const [ session, loading ] = useSession()
|
||||||
|
+ const { data: session, status } = useSession()
|
||||||
|
+ const loading = status === "loading"
|
||||||
|
```
|
||||||
|
|
||||||
|
[Check the docs](https://next-auth.js.org/getting-started/client#usesession) for the possible values of both `session.status` and `session.data`.
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.18
|
||||||
|
|
||||||
|
## Named Parameters
|
||||||
|
|
||||||
|
We have changed the arguments to our callbacks to the named parameters pattern. This way you don't have to use dummy `_` placeholders or other tricks.
|
||||||
|
|
||||||
|
### Callbacks
|
||||||
|
|
||||||
|
The signatures for the callback methods now look like this:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- signIn(user, account, profileOrEmailOrCredentials)
|
||||||
|
+ signIn({ user, account, profile, email, credentials })
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- redirect(url, baseUrl)
|
||||||
|
+ redirect({ url, baseUrl })
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- session(session, tokenOrUser)
|
||||||
|
+ session({ session, token, user })
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- jwt(token, user, account, OAuthProfile, isNewUser)
|
||||||
|
+ jwt({ token, user, account, profile, isNewUser })
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.17
|
||||||
|
|
||||||
|
### Events
|
||||||
|
|
||||||
|
Two event signatures have changed to also use the named parameters pattern, `signOut` and `updateUser`.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
// [...nextauth].js
|
||||||
|
...
|
||||||
|
events: {
|
||||||
|
- signOut(tokenOrSession),
|
||||||
|
+ signOut({ token, session }), // token if using JWT, session if DB persisted sessions.
|
||||||
|
- updateUser(user)
|
||||||
|
+ updateUser({ user })
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.20
|
||||||
|
|
||||||
|
## JWT configuration
|
||||||
|
|
||||||
|
We have removed some of the [configuration options](/configuration/options) when using JSON Web Tokens, [here's the PR](https://github.com/nextauthjs/next-auth/pull/3039) for more context.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
export default NextAuth({
|
||||||
|
// ...
|
||||||
|
jwt: {
|
||||||
|
secret,
|
||||||
|
maxAge,
|
||||||
|
- encryptionKey
|
||||||
|
- signingKey
|
||||||
|
- encryptionKey
|
||||||
|
- verificationOptions
|
||||||
|
encode({
|
||||||
|
token
|
||||||
|
secret
|
||||||
|
maxAge
|
||||||
|
- signingKey
|
||||||
|
- signingOptions
|
||||||
|
- encryptionKey
|
||||||
|
- encryptionOptions
|
||||||
|
- encryption
|
||||||
|
}) {},
|
||||||
|
decode({
|
||||||
|
token
|
||||||
|
secret
|
||||||
|
- maxAge
|
||||||
|
- signingKey
|
||||||
|
- verificationKey
|
||||||
|
- verificationOptions
|
||||||
|
- encryptionKey
|
||||||
|
- decryptionKey
|
||||||
|
- decryptionOptions
|
||||||
|
- encryption
|
||||||
|
}) {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logger API
|
||||||
|
|
||||||
|
The logger API has been simplified to use at most two parameters, where the second is usually an object (`metadata`) containing an `error` object. If you are not using the logger settings you can ignore this change.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
// [...nextauth.js]
|
||||||
|
import log from "some-logger-service"
|
||||||
|
...
|
||||||
|
logger: {
|
||||||
|
- error(code, ...message) {},
|
||||||
|
+ error(code, metadata) {},
|
||||||
|
- warn(code, ...message) {},
|
||||||
|
+ warn(code) {}
|
||||||
|
- debug(code, ...message) {}
|
||||||
|
+ debug(code, metadata) {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.19
|
||||||
|
|
||||||
|
## `nodemailer`
|
||||||
|
|
||||||
|
Like `typeorm` and `prisma`, [`nodemailer`](https://npmjs.com/package/nodemailer) is no longer included as a dependency by default. If you are using the Email provider you must install it in your project manually, or use any other Email library in the [`sendVerificationRequest`](/configuration/providers/email#options-1#:~:text=sendVerificationRequest) callback. This reduces bundle size for those not actually using the Email provider. Remember, when using the Email provider, it is mandatory to also use a database adapter due to the fact that verification tokens need to be persisted longer term for the magic link functionality to work.
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.2
|
||||||
|
|
||||||
|
## Theme
|
||||||
|
|
||||||
|
We have added some basic customization options to our built-in pages like `signin`, `signout`, etc.
|
||||||
|
|
||||||
|
These can be set under the `theme` configuration key. This used to be a string which only controlled the color scheme option. Now it is an object with the following options:
|
||||||
|
|
||||||
|
```js
|
||||||
|
theme: {
|
||||||
|
colorScheme: "auto", // "auto" | "dark" | "light"
|
||||||
|
brandColor: "", // Hex color value
|
||||||
|
logo: "" // Absolute URL to logo image
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The hope is that with some minimal configuration / customization options, users won't immediately feel the need to replace the built-in pages with their own.
|
||||||
|
|
||||||
|
More details and screenshots of the new theme options can be found under [configuration/pages](https://next-auth.js.org/configuration/pages#theming).
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/pull/2788
|
||||||
|
|
||||||
|
## Session
|
||||||
|
|
||||||
|
The `session.jwt: boolean` option has been renamed to `session.strategy: "jwt" | "database"`. The goal is to make the user's options more intuitive:
|
||||||
|
|
||||||
|
1. No adapter, `strategy: "jwt"`: This is the default. The session is saved in a cookie and never persisted anywhere.
|
||||||
|
2. With Adapter, `strategy: "database"`: If an Adapter is defined, this will be the implicit setting. No user config is needed.
|
||||||
|
3. With Adapter, `strategy: "jwt"`: The user can explicitly instruct `next-auth` to use JWT even if a database is available. This can result in faster lookups in compromise of lowered security. Read more about: https://next-auth.js.org/faq#json-web-tokens
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
session: {
|
||||||
|
- jwt: true,
|
||||||
|
+ strategy: "jwt",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/pull/3144
|
||||||
|
|
||||||
|
## Adapters
|
||||||
|
|
||||||
|
Most importantly, the core `next-auth` package no longer ships with `typeorm` or any other database adapter by default. This brings the default bundle size down significantly for those not needing to persist user data to a database.
|
||||||
|
|
||||||
|
You can find the official Adapters in the `packages` directory in the primary monorepo ([nextauthjs/next-auth](https://github.com/nextauthjs/next-auth)). Although you can still [create your own](/tutorials/creating-a-database-adapter) with a new, [simplified Adapter API](https://github.com/nextauthjs/next-auth/pull/2361).
|
||||||
|
|
||||||
|
If you have a database that was created with a `3.x.x` or earlier version of NextAuth.js, you will need to run a migration to update the schema to the new version 4 database model. See the bottom of this migration guide for database specific migration examples.
|
||||||
|
|
||||||
|
1. If you use the built-in TypeORM or Prisma adapters, these have been removed from the core `next-auth` package. Thankfully the migration is easy; you just need to install the external packages for your database and change the import in your `[...nextauth].js`.
|
||||||
|
|
||||||
|
The `database` option has been removed, you must now do the following instead:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
// [...nextauth].js
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
+ import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
|
||||||
|
|
||||||
|
...
|
||||||
|
export default NextAuth({
|
||||||
|
- database: "yourconnectionstring",
|
||||||
|
+ adapter: TypeORMLegacyAdapter("yourconnectionstring")
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
2. The `prisma-legacy` adapter has been removed, please use the [`@next-auth/prisma-adapter`](https://npmjs.com/package/@next-auth/prisma-adapter) instead.
|
||||||
|
|
||||||
|
3. The `typeorm-legacy` adapter has been upgraded to use the newer adapter API, but has retained the `typeorm-legacy` name. We aim to migrate this to individual lighter weight adapters for each database type in the future, or switch out `typeorm`.
|
||||||
|
|
||||||
|
4. MongoDB has been moved to its own adapter under `@next-auth/mongodb-adapter`. See the [MongoDB Adapter docs](https://authjs.dev/getting-started/adapters/mongodb).
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.8 and https://github.com/nextauthjs/next-auth/pull/2361
|
||||||
|
|
||||||
|
### Adapter API
|
||||||
|
|
||||||
|
**This does not require any changes from the user - these are adapter specific changes only**
|
||||||
|
|
||||||
|
The Adapter API has been rewritten and significantly simplified in NextAuth.js v4. The adapters now have less work to do as some functionality has been migrated to the core of NextAuth, like hashing the [verification token](https://authjs.dev/concepts/database-models#verificationtoken).
|
||||||
|
|
||||||
|
If you are an adapter maintainer or are interested in writing your own adapter, you can find more information about this change in https://github.com/nextauthjs/next-auth/pull/2361 and release https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.22.
|
||||||
|
|
||||||
|
### Schema changes
|
||||||
|
|
||||||
|
The way we save data with adapters have slightly changed. With the new Adapter API, we wanted to make it easier to extend your database with additional fields. For example if your User needs an extra `phone` field, it should be enough to add that to your database's schema, and no changes will be necessary in your adapter.
|
||||||
|
|
||||||
|
- `created_at`/`createdAt` and `updated_at`/`updatedAt` fields are removed from all Models.
|
||||||
|
- `user_id`/`userId` consistently named `userId`.
|
||||||
|
- `compound_id`/`compoundId` is removed from Account.
|
||||||
|
- `access_token`/`accessToken` is removed from Session.
|
||||||
|
- `email_verified`/`emailVerified` on User is consistently named `emailVerified`.
|
||||||
|
- `provider_id`/`providerId` renamed to `provider` on Account
|
||||||
|
- `provider_type`/`providerType` renamed to `type` on Account
|
||||||
|
- `provider_account_id`/`providerAccountId` on Account is consistently named `providerAccountId`
|
||||||
|
- `access_token_expires`/`accessTokenExpires` on Account renamed to `expires_at`
|
||||||
|
- New fields on Account: `token_type`, `scope`, `id_token`, `session_state`
|
||||||
|
- `verification_requests` table has been renamed to `verification_tokens`
|
||||||
|
|
||||||
|
<!-- REVIEW: Would something like this below be helpful? -->
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
See the changes
|
||||||
|
</summary>
|
||||||
|
<pre>
|
||||||
|
|
||||||
|
```diff
|
||||||
|
User {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
email
|
||||||
|
+ emailVerified
|
||||||
|
- email_verified
|
||||||
|
image
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
Account {
|
||||||
|
id
|
||||||
|
- compound_id
|
||||||
|
- user_id
|
||||||
|
+ userId
|
||||||
|
- provider_type
|
||||||
|
+ type
|
||||||
|
- provider_id
|
||||||
|
+ provider
|
||||||
|
- provider_account_id
|
||||||
|
+ providerAccountId
|
||||||
|
refresh_token
|
||||||
|
access_token
|
||||||
|
- access_token_expires
|
||||||
|
+ expires_in
|
||||||
|
+ expires_at
|
||||||
|
+ token_type
|
||||||
|
+ scope
|
||||||
|
+ id_token
|
||||||
|
+ session_state
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
Session {
|
||||||
|
id
|
||||||
|
userId
|
||||||
|
expires
|
||||||
|
sessionToken
|
||||||
|
- access_token
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
VerificationToken {
|
||||||
|
id
|
||||||
|
token
|
||||||
|
expires
|
||||||
|
identifier
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
For more info, see the [Models page](https://authjs.dev/concepts/database-models).
|
||||||
|
|
||||||
|
### Database migration
|
||||||
|
|
||||||
|
NextAuth.js v4 has a slightly different database schema compared to v3. If you're using any of our adapters and want to upgrade, you can use on of the below schemas.
|
||||||
|
|
||||||
|
They are designed to be run directly against the database itself. So instead of having one in Prisma syntax, one in TypeORM syntax, etc. we've decided to just make one for each underlying database type. i.e. one for Postgres, one for MySQL, one for MongoDB, etc.
|
||||||
|
|
||||||
|
#### MySQL
|
||||||
|
|
||||||
|
```sql
|
||||||
|
/* ACCOUNT */
|
||||||
|
ALTER TABLE accounts
|
||||||
|
CHANGE "access_token_expires" "expires_at" int
|
||||||
|
CHANGE "user_id" "userId" varchar(255)
|
||||||
|
ADD CONSTRAINT fk_user_id FOREIGN KEY (userId) REFERENCES users(id)
|
||||||
|
RENAME COLUMN "provider_id" "provider"
|
||||||
|
RENAME COLUMN "provider_account_id" "providerAccountId"
|
||||||
|
DROP COLUMN "provider_type"
|
||||||
|
DROP COLUMN "compound_id"
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
DROP COLUMN "created_at"
|
||||||
|
DROP COLUMN "updated_at"
|
||||||
|
|
||||||
|
ADD COLUMN "token_type" varchar(255) NULL
|
||||||
|
ADD COLUMN "scope" varchar(255) NULL
|
||||||
|
ADD COLUMN "id_token" varchar(255) NULL
|
||||||
|
ADD COLUMN "session_state" varchar(255) NULL
|
||||||
|
|
||||||
|
/* Note: These are only needed if you're going to be using the old Twitter OAuth 1.0 provider. */
|
||||||
|
ADD COLUMN "oauth_token_secret" varchar(255) NULL
|
||||||
|
ADD COLUMN "oauth_token" varchar(255) NULL
|
||||||
|
|
||||||
|
/* USER */
|
||||||
|
ALTER TABLE users
|
||||||
|
RENAME COLUMN "email_verified" "emailVerified"
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
DROP COLUMN "created_at"
|
||||||
|
DROP COLUMN "updated_at"
|
||||||
|
|
||||||
|
/* SESSION */
|
||||||
|
ALTER TABLE sessions
|
||||||
|
RENAME COLUMN "session_token" "sessionToken"
|
||||||
|
CHANGE "user_id" "userId" varchar(255)
|
||||||
|
ADD CONSTRAINT fk_user_id FOREIGN KEY (userId) REFERENCES users(id)
|
||||||
|
DROP COLUMN "access_token"
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
DROP COLUMN "created_at"
|
||||||
|
DROP COLUMN "updated_at"
|
||||||
|
|
||||||
|
/* VERIFICATION REQUESTS */
|
||||||
|
ALTER TABLE verification_requests RENAME verification_tokens
|
||||||
|
ALTER TABLE verification_tokens
|
||||||
|
DROP COLUMN id
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
DROP COLUMN "created_at"
|
||||||
|
DROP COLUMN "updated_at"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Postgres
|
||||||
|
|
||||||
|
```sql
|
||||||
|
/* ACCOUNT */
|
||||||
|
ALTER TABLE accounts RENAME COLUMN "user_id" TO "userId";
|
||||||
|
ALTER TABLE accounts RENAME COLUMN "provider_id" TO "provider";
|
||||||
|
ALTER TABLE accounts RENAME COLUMN "provider_account_id" TO "providerAccountId";
|
||||||
|
ALTER TABLE accounts RENAME COLUMN "access_token_expires" TO "expires_at";
|
||||||
|
ALTER TABLE accounts RENAME COLUMN "provider_type" TO "type";
|
||||||
|
|
||||||
|
/* Do conversion of TIMESTAMPTZ to BIGINT */
|
||||||
|
ALTER TABLE accounts ALTER COLUMN "expires_at" TYPE TEXT USING CAST(extract(epoch FROM "expires_at") AS BIGINT)*1000;
|
||||||
|
|
||||||
|
/* Keep id as SERIAL with autoincrement when using ORM. Using new v4 uuid format won't work because of incompatibility */
|
||||||
|
/* ALTER TABLE accounts ALTER COLUMN "id" TYPE TEXT; */
|
||||||
|
/* ALTER TABLE accounts ALTER COLUMN "userId" TYPE TEXT; */
|
||||||
|
ALTER TABLE accounts ALTER COLUMN "type" TYPE TEXT;
|
||||||
|
ALTER TABLE accounts ALTER COLUMN "provider" TYPE TEXT;
|
||||||
|
ALTER TABLE accounts ALTER COLUMN "providerAccountId" TYPE TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE accounts ADD CONSTRAINT fk_user_id FOREIGN KEY ("userId") REFERENCES users(id);
|
||||||
|
ALTER TABLE accounts
|
||||||
|
DROP COLUMN IF EXISTS "compound_id";
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
ALTER TABLE accounts
|
||||||
|
DROP COLUMN IF EXISTS "created_at",
|
||||||
|
DROP COLUMN IF EXISTS "updated_at";
|
||||||
|
|
||||||
|
ALTER TABLE accounts
|
||||||
|
ADD COLUMN IF NOT EXISTS "token_type" TEXT NULL,
|
||||||
|
ADD COLUMN IF NOT EXISTS "scope" TEXT NULL,
|
||||||
|
ADD COLUMN IF NOT EXISTS "id_token" TEXT NULL,
|
||||||
|
ADD COLUMN IF NOT EXISTS "session_state" TEXT NULL;
|
||||||
|
/* Note: These are only needed if you're going to be using the old Twitter OAuth 1.0 provider. */
|
||||||
|
/* ALTER TABLE accounts
|
||||||
|
ADD COLUMN IF NOT EXISTS "oauth_token_secret" TEXT NULL,
|
||||||
|
ADD COLUMN IF NOT EXISTS "oauth_token" TEXT NULL; */
|
||||||
|
|
||||||
|
/* USER */
|
||||||
|
ALTER TABLE users RENAME COLUMN "email_verified" TO "emailVerified";
|
||||||
|
|
||||||
|
/* Keep id as SERIAL with autoincrement when using ORM. Using new v4 uuid format won't work because of incompatibility */
|
||||||
|
/* ALTER TABLE users ALTER COLUMN "id" TYPE TEXT; */
|
||||||
|
ALTER TABLE users ALTER COLUMN "name" TYPE TEXT;
|
||||||
|
ALTER TABLE users ALTER COLUMN "email" TYPE TEXT;
|
||||||
|
ALTER TABLE users ALTER COLUMN "image" TYPE TEXT;
|
||||||
|
/* Do conversion of TIMESTAMPTZ to BIGINT and then TEXT */
|
||||||
|
ALTER TABLE users ALTER COLUMN "emailVerified" TYPE TEXT USING CAST(CAST(extract(epoch FROM "emailVerified") AS BIGINT)*1000 AS TEXT);
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
ALTER TABLE users
|
||||||
|
DROP COLUMN IF EXISTS "created_at",
|
||||||
|
DROP COLUMN IF EXISTS "updated_at";
|
||||||
|
|
||||||
|
/* SESSION */
|
||||||
|
ALTER TABLE sessions RENAME COLUMN "session_token" TO "sessionToken";
|
||||||
|
ALTER TABLE sessions RENAME COLUMN "user_id" TO "userId";
|
||||||
|
|
||||||
|
/* Keep id as SERIAL with autoincrement when using ORM. Using new v4 uuid format won't work because of incompatibility */
|
||||||
|
/* ALTER TABLE sessions ALTER COLUMN "id" TYPE TEXT; */
|
||||||
|
/* ALTER TABLE sessions ALTER COLUMN "userId" TYPE TEXT; */
|
||||||
|
ALTER TABLE sessions ALTER COLUMN "sessionToken" TYPE TEXT;
|
||||||
|
ALTER TABLE sessions ADD CONSTRAINT fk_user_id FOREIGN KEY ("userId") REFERENCES users(id);
|
||||||
|
/* Do conversion of TIMESTAMPTZ to BIGINT and then TEXT */
|
||||||
|
ALTER TABLE sessions ALTER COLUMN "expires" TYPE TEXT USING CAST(CAST(extract(epoch FROM "expires") AS BIGINT)*1000 AS TEXT);
|
||||||
|
ALTER TABLE sessions DROP COLUMN IF EXISTS "access_token";
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
ALTER TABLE sessions
|
||||||
|
DROP COLUMN IF EXISTS "created_at",
|
||||||
|
DROP COLUMN IF EXISTS "updated_at";
|
||||||
|
|
||||||
|
/* VERIFICATION REQUESTS */
|
||||||
|
ALTER TABLE verification_requests RENAME TO verification_tokens;
|
||||||
|
/* Keep id as ORM needs it */
|
||||||
|
/* ALTER TABLE verification_tokens DROP COLUMN IF EXISTS id; */
|
||||||
|
ALTER TABLE verification_tokens ALTER COLUMN "identifier" TYPE TEXT;
|
||||||
|
ALTER TABLE verification_tokens ALTER COLUMN "token" TYPE TEXT;
|
||||||
|
/* Do conversion of TIMESTAMPTZ to BIGINT and then TEXT */
|
||||||
|
ALTER TABLE verification_tokens ALTER COLUMN "expires" TYPE TEXT USING CAST(CAST(extract(epoch FROM "expires") AS BIGINT)*1000 AS TEXT);
|
||||||
|
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||||
|
ALTER TABLE verification_tokens
|
||||||
|
DROP COLUMN IF EXISTS "created_at",
|
||||||
|
DROP COLUMN IF EXISTS "updated_at";
|
||||||
|
```
|
||||||
|
|
||||||
|
#### MongoDB
|
||||||
|
|
||||||
|
MongoDB is a document database and as such new fields will be automatically populated. You do, however, need to update the names of existing fields which are going to be reused.
|
||||||
|
|
||||||
|
```mongo
|
||||||
|
db.getCollection('accounts').updateMany({}, {
|
||||||
|
$rename: {
|
||||||
|
"provider_id": "provider",
|
||||||
|
"provider_account_id": "providerAccountId",
|
||||||
|
"user_id": "userId",
|
||||||
|
"access_token_expires": "expires_at"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
db.getCollection('users').updateMany({}, {
|
||||||
|
$rename: {
|
||||||
|
"email_verified": "emailVerified"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
db.getCollection('sessions').updateMany({}, {
|
||||||
|
$rename: {
|
||||||
|
"session_token": "sessionToken",
|
||||||
|
"user_id": "userId"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Missing `secret`
|
||||||
|
|
||||||
|
NextAuth.js used to generate a secret for convenience, when the user did not define one. This might have been useful in development, but can be a concern in production. We have always been clear about that in the docs, but from now on, if you forget to define a `secret` property in production, we will show the user an error page. Read more about this option [here](https://next-auth.js.org/configuration/options#secret)
|
||||||
|
|
||||||
|
You can generate a secret to be placed in the `secret` configuration option via the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ openssl rand -base64 32
|
||||||
|
```
|
||||||
|
|
||||||
|
Therefore, your NextAuth.js config should look something like this:
|
||||||
|
|
||||||
|
```javascript title="/pages/api/auth/[...nextauth].js"
|
||||||
|
...
|
||||||
|
export default NextAuth({
|
||||||
|
...
|
||||||
|
providers: [...],
|
||||||
|
secret: "LlKq6ZtYbr+hTC073mAmAh9/h2HwMfsFo4hrfCx5mLg=",
|
||||||
|
...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/issues/3143
|
||||||
|
|
||||||
|
## Session `strategy`
|
||||||
|
|
||||||
|
We have always supported two different session strategies. The first being our most popular and default strategy - the JWT based one. The second is the database adapter persisted session strategy. Both have their advantages/disadvantages, you can learn more about them on the [FAQ](https://next-auth.js.org/faq) page.
|
||||||
|
|
||||||
|
Previously, the way you configured this was through the `jwt: boolean` flag in the `session` option. The names `session` and `jwt` might have been a bit overused in the options, and so for a clearer message, we renamed this option to `strategy: "jwt" | "database"`, it is still in the `session` object. This will hopefully better indicate the purpose of this option as well as make very explicit which type of session you are going to use.
|
||||||
|
|
||||||
|
See the [`session` option docs](https://next-auth.js.org/configuration/options#session) for more details.
|
||||||
|
|
||||||
|
Introduced in https://github.com/nextauthjs/next-auth/pull/3144
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
We hope this migration goes smoothly for each and every one of you! If you have any questions or get stuck anywhere, feel free to create [a new issue](https://github.com/nextauthjs/next-auth/issues/new) on GitHub.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
id: basics
|
||||||
|
title: Basics
|
||||||
|
---
|
||||||
|
|
||||||
|
### [Securing pages and API routes](/tutorials/securing-pages-and-api-routes)
|
||||||
|
|
||||||
|
- How to restrict access to pages and API routes.
|
||||||
|
|
||||||
|
### [Usage with class components](/tutorials/usage-with-class-components)
|
||||||
|
|
||||||
|
- How to use `useSession()` hook with class components.
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: fullstack
|
||||||
|
title: Fullstack
|
||||||
|
---
|
||||||
|
|
||||||
|
### [Refresh Token Rotation](https://authjs.dev/guides/refresh-token-rotation)
|
||||||
|
|
||||||
|
- How to implement refresh token rotation.
|
||||||
|
|
||||||
|
### [LDAP Authentication](/tutorials/ldap-auth-example)
|
||||||
|
|
||||||
|
- How to use the Credentials Provider to authenticate against an LDAP database. This approach can be used to authenticate existing user accounts against any backend.
|
||||||
|
|
||||||
|
### [Adding HTTP(S) Proxy Support](/tutorials/corporate-proxy)
|
||||||
|
|
||||||
|
- Add support for HTTP/HTTPS Proxy support to `openid-client` in order to use NextAuth.js behind a corporate proxy or other locked down network.
|
||||||
|
|
||||||
|
### [Using the Email Provider behind Corporate Email Scanning Services](/tutorials/avoid-corporate-link-checking-email-provider)
|
||||||
|
|
||||||
|
- An internal tutorial on modifying the catch-all API Route to gracefully handle `HEAD` requests.
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
### [Custom models with TypeORM](https://authjs.dev/guides/creating-a-database-adapter)
|
||||||
|
|
||||||
|
- How to use models with custom properties using the TypeORM adapter.
|
||||||
|
|
||||||
|
### [Creating a database adapter](/tutorials/creating-a-database-adapter)
|
||||||
|
|
||||||
|
- How to create a custom adapter, to use any database to fetch and store user / account data.
|
||||||
|
|
||||||
|
### [Adding role based login to database session strategy](https://authjs.dev/guides/role-based-access-control)
|
||||||
|
|
||||||
|
- Implement a role based login system by adding a custom session callback.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
id: guides
|
||||||
|
title: Guides
|
||||||
|
---
|
||||||
|
|
||||||
|
# Guides
|
||||||
|
|
||||||
|
We have internal guides in three levels of difficulty.
|
||||||
|
|
||||||
|
- [Basics](/guides/basics)
|
||||||
|
- [Fullstack](/guides/fullstack)
|
||||||
|
- [Testing](/guides/testing)
|
||||||
|
|
||||||
|
If you can't find what you're looking for here, maybe take a look at our third-party [tutorials](/tutorials) page.
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
id: testing
|
||||||
|
title: Testing
|
||||||
|
---
|
||||||
|
|
||||||
|
### [Testing with Cypress](/tutorials/testing-with-cypress)
|
||||||
|
|
||||||
|
- How to write tests using Cypress.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: 42-school
|
||||||
|
title: 42 School
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
42 returns a field on `Account` called `created_at` which is a number. See the [docs](https://api.intra.42.fr/apidoc/guides/getting_started#make-basic-requests). Make sure to add this field to your database schema, in case if you are using an [Adapter](https://next-auth.js.org/adapters).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://api.intra.42.fr/apidoc/guides/web_application_flow
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://profile.intra.42.fr/oauth/applications/new
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **42 School Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [42 School Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/42-school.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import FortyTwoProvider from "next-auth/providers/42-school";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
FortyTwoProvider({
|
||||||
|
clientId: process.env.FORTY_TWO_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FORTY_TWO_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
id: apple
|
||||||
|
title: Apple
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.apple.com/sign-in-with-apple/get-started/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.apple.com/account/resources/identifiers/list/serviceId
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Apple Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Apple Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/apple.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
### Generating a secret
|
||||||
|
|
||||||
|
Apple requires the client secret to be a JWT. To generate one, you can use the following script: https://bal.so/apple-gen-secret.
|
||||||
|
|
||||||
|
For more information, see the [Apple docs](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
|
||||||
|
|
||||||
|
Then, you can paste the result into your `.env.local` file under `APPLE_SECRET`, so you can refer to it from your code:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import AppleProvider from "next-auth/providers/apple";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
AppleProvider({
|
||||||
|
clientId: process.env.APPLE_ID,
|
||||||
|
clientSecret: process.env.APPLE_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The TeamID is located on the top right after logging in.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The KeyID is located after you create the key. Look for it before you download the k8 file.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Testing on a development server
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Apple requires all sites to run HTTPS (including local development instances).
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Apple doesn't allow you to use localhost in domains or subdomains.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Host name resolution
|
||||||
|
|
||||||
|
Edit your host file and point your site to `127.0.0.1`.
|
||||||
|
|
||||||
|
_Linux/macOS_
|
||||||
|
|
||||||
|
```
|
||||||
|
echo '127.0.0.1 dev.example.com' | sudo tee -a /etc/hosts
|
||||||
|
```
|
||||||
|
|
||||||
|
_Windows_ (run PowerShell as administrator)
|
||||||
|
|
||||||
|
```ps
|
||||||
|
Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "127.0.0.1 dev.example.com" -Force
|
||||||
|
```
|
||||||
|
|
||||||
|
More info: [How to edit my host file?](https://phoenixnap.com/kb/how-to-edit-hosts-file-in-windows-mac-or-linux)
|
||||||
|
|
||||||
|
### Create certificate
|
||||||
|
|
||||||
|
Create a directory `certificates` and add the certificate files `localhost.key` and `localhost.crt`, which you generate using OpenSSL:
|
||||||
|
|
||||||
|
_Linux/macOS_
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl req -x509 -out localhost.crt -keyout localhost.key \
|
||||||
|
-newkey rsa:2048 -nodes -sha256 \
|
||||||
|
-subj "/CN=localhost" -extensions EXT -config <( \
|
||||||
|
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
|
||||||
|
```
|
||||||
|
|
||||||
|
_Windows_
|
||||||
|
|
||||||
|
The OpenSSL executable is distributed with [Git](https://git-scm.com/download/win) for Windows. Once installed you will find the openssl.exe file in `C:\Program Files\Git\mingw64\bin`, which you can add to the system PATH environment variable if it’s not already done.
|
||||||
|
|
||||||
|
Add environment variable `OPENSSL_CONF=C:\Program Files\Git\mingw64\ssl\openssl.cnf`
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
req -x509 -out localhost.crt -keyout localhost.key \
|
||||||
|
-newkey rsa:2048 -nodes -sha256 \
|
||||||
|
-subj "/CN=localhost"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy to server
|
||||||
|
|
||||||
|
You can create a `server.js` in the root of your project and run it with `node server.js` to test Sign in with Apple integration locally:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { createServer } = require("https")
|
||||||
|
const { parse } = require("url")
|
||||||
|
const next = require("next")
|
||||||
|
const fs = require("fs")
|
||||||
|
|
||||||
|
const dev = process.env.NODE_ENV !== "production"
|
||||||
|
const app = next({ dev })
|
||||||
|
const handle = app.getRequestHandler()
|
||||||
|
|
||||||
|
const httpsOptions = {
|
||||||
|
key: fs.readFileSync("./certificates/localhost.key"),
|
||||||
|
cert: fs.readFileSync("./certificates/localhost.crt"),
|
||||||
|
}
|
||||||
|
|
||||||
|
app.prepare().then(() => {
|
||||||
|
createServer(httpsOptions, (req, res) => {
|
||||||
|
const parsedUrl = parse(req.url, true)
|
||||||
|
handle(req, res, parsedUrl)
|
||||||
|
}).listen(3000, (err) => {
|
||||||
|
if (err) throw err
|
||||||
|
console.log("> Ready on https://localhost:3000")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Helpful guides
|
||||||
|
|
||||||
|
- [How to setup localhost with HTTPS with a Next.js app](https://medium.com/@anMagpie/secure-your-local-development-server-with-https-next-js-81ac6b8b3d68)
|
||||||
|
|
||||||
|
- [Guide to configuring Sign in with Apple](https://developer.okta.com/blog/2019/06/04/what-the-heck-is-sign-in-with-apple)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
id: atlassian
|
||||||
|
title: Atlassian
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.atlassian.com/cloud/jira/platform/oauth-2-authorization-code-grants-3lo-for-apps/#implementing-oauth-2-0--3lo-
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Atlassian Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Atlassian Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/atlassian.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import AtlassianProvider from "next-auth/providers/atlassian";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
AtlassianProvider({
|
||||||
|
clientId: process.env.ATLASSIAN_CLIENT_ID,
|
||||||
|
clientSecret: process.env.ATLASSIAN_CLIENT_SECRET,
|
||||||
|
authorization: {
|
||||||
|
params: {
|
||||||
|
scope: "write:jira-work read:jira-work read:jira-user offline_access read:me"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
An app can be created at https://developer.atlassian.com/apps/
|
||||||
|
:::
|
||||||
|
|
||||||
|
Under "Apis and features" in the side menu, configure the following for "OAuth 2.0 (3LO)":
|
||||||
|
|
||||||
|
- Redirect URL
|
||||||
|
- http://localhost:3000/api/auth/callback/atlassian
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
To enable access to Jira Platform REST API you must enable User Identity API and add `read:me` to your provider scope option.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
id: auth0
|
||||||
|
title: Auth0
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://auth0.com/docs/api/authentication#authorize-application
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://manage.auth0.com/dashboard
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Auth0 Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Auth0 Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/auth0.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Auth0Provider from "next-auth/providers/auth0";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
Auth0Provider({
|
||||||
|
clientId: process.env.AUTH0_CLIENT_ID,
|
||||||
|
clientSecret: process.env.AUTH0_CLIENT_SECRET,
|
||||||
|
issuer: process.env.AUTH0_ISSUER
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
`issuer` should be the fully qualified URL – e.g. `https://dev-s6clz2lv.eu.auth0.com`
|
||||||
|
:::
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
id: authentik
|
||||||
|
title: Authentik
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://goauthentik.io/docs/providers/oauth2
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Authentik Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Authentik Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/authentik.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import AuthentikProvider from "next-auth/providers/authentik";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
AuthentikProvider({
|
||||||
|
clientId: process.env.AUTHENTIK_ID,
|
||||||
|
clientSecret: process.env.AUTHENTIK_SECRET,
|
||||||
|
issuer: process.env.AUTHENTIK_ISSUER,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
`issuer` should include the slug without a trailing slash – e.g., `https://my-authentik-domain.com/application/o/My_Slug`
|
||||||
|
:::
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
---
|
||||||
|
id: azure-ad-b2c
|
||||||
|
title: Azure Active Directory B2C
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Azure AD B2C returns the following fields on `Account`:
|
||||||
|
|
||||||
|
- `refresh_token_expires_in` (number)
|
||||||
|
- `not_before` (number)
|
||||||
|
- `id_token_expires_in` (number)
|
||||||
|
- `profile_info` (string).
|
||||||
|
|
||||||
|
See their [docs](https://docs.microsoft.com/en-us/azure/active-directory-b2c/access-tokens). Remember to add these fields to your database schema, in case if you are using an [Adapter](https://next-auth.js.org/adapters).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://docs.microsoft.com/azure/active-directory-b2c/tutorial-create-tenant
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Azure Active Directory Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Azure Active Directory Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/azure-ad-b2c.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Configuration (Basic)
|
||||||
|
|
||||||
|
Basic configuration sets up Azure AD B2C to return an ID Token. This should be done as a prerequisite prior to running through the Advanced configuration.
|
||||||
|
|
||||||
|
Step 1: Azure AD B2C Tenant
|
||||||
|
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-tenant
|
||||||
|
|
||||||
|
Step 2: App Registration
|
||||||
|
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-register-applications
|
||||||
|
|
||||||
|
Step 3: User Flow
|
||||||
|
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-create-user-flows
|
||||||
|
|
||||||
|
Note: For the step "User attributes and token claims" you might minimally:
|
||||||
|
|
||||||
|
- Collect attribute:
|
||||||
|
- Email Address
|
||||||
|
- Display Name
|
||||||
|
- Given Name
|
||||||
|
- Surname
|
||||||
|
- Return claim:
|
||||||
|
- Email Addresses
|
||||||
|
- Display Name
|
||||||
|
- Given Name
|
||||||
|
- Surname
|
||||||
|
- Identity Provider
|
||||||
|
- Identity Provider Access Token
|
||||||
|
- User's Object ID
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
In `.env.local` create the following entries:
|
||||||
|
|
||||||
|
```
|
||||||
|
AZURE_AD_B2C_TENANT_NAME=<copy the B2C tenant name here from Step 1>
|
||||||
|
AZURE_AD_B2C_CLIENT_ID=<copy Application (client) ID here from Step 2>
|
||||||
|
AZURE_AD_B2C_CLIENT_SECRET=<copy generated secret value here from Step 2>
|
||||||
|
AZURE_AD_B2C_PRIMARY_USER_FLOW=<copy the name of the signin user flow you created from Step 3>
|
||||||
|
```
|
||||||
|
|
||||||
|
In `pages/api/auth/[...nextauth].js` find or add the AZURE_AD_B2C entries:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
AzureADB2CProvider({
|
||||||
|
tenantId: process.env.AZURE_AD_B2C_TENANT_NAME,
|
||||||
|
clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
|
||||||
|
clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
|
||||||
|
primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
|
||||||
|
authorization: { params: { scope: "offline_access openid" } },
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration (Advanced)
|
||||||
|
|
||||||
|
Advanced configuration sets up Azure AD B2C to return an Authorization Token. This builds on the steps completed in the Basic configuration above.
|
||||||
|
|
||||||
|
Step 4: Add a Web API application
|
||||||
|
https://docs.microsoft.com/en-us/azure/active-directory-b2c/tutorial-single-page-app-webapi?tabs=app-reg-ga
|
||||||
|
|
||||||
|
Note: this is a second app registration (similar to Step 2) but with different setup and configuration.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Nothing in `.env.local` needs to change here. The only update is in `pages/api/auth/[...nextauth].js` where you will need to add the additional scopes that were created in Step 4 above:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import AzureADB2CProvider from "next-auth/providers/azure-ad-b2c";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
AzureADB2CProvider({
|
||||||
|
tenantId: process.env.AZURE_AD_B2C_TENANT_NAME,
|
||||||
|
clientId: process.env.AZURE_AD_B2C_CLIENT_ID,
|
||||||
|
clientSecret: process.env.AZURE_AD_B2C_CLIENT_SECRET,
|
||||||
|
primaryUserFlow: process.env.AZURE_AD_B2C_PRIMARY_USER_FLOW,
|
||||||
|
authorization: { params: { scope: `https://${process.env.AZURE_AD_B2C_TENANT_NAME}.onmicrosoft.com/api/demo.read https://${process.env.AZURE_AD_B2C_TENANT_NAME}.onmicrosoft.com/api/demo.write offline_access openid` } },
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
...
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
id: azure-ad
|
||||||
|
title: Azure Active Directory
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Azure Active Directory returns the following fields on `Account`:
|
||||||
|
|
||||||
|
- `token_type` (string)
|
||||||
|
- `expires_in` (number)
|
||||||
|
- `ext_expires_in` (number)
|
||||||
|
- `access_token` (string).
|
||||||
|
|
||||||
|
Remember to add these fields to your database schema, in case if you are using an [Adapter](https://authjs.dev/getting-started/database).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
### To allow specific Active Directory users access:
|
||||||
|
|
||||||
|
- In https://portal.azure.com/ search for "Microsoft Entra ID", and select your organization.
|
||||||
|
- Next, in the left menu expand the "Manage" accordion and then go to "App Registration" , and create a new one.
|
||||||
|
- Pay close attention to "Who can use this application or access this API?"
|
||||||
|
- This allows you to scope access to specific types of user accounts
|
||||||
|
- Only your tenant, all azure tenants, or all azure tenants and public Microsoft accounts (Skype, Xbox, Outlook.com, etc.)
|
||||||
|
- When asked for a redirection URL, select the platform type "Web" and use `https://yourapplication.com/api/auth/callback/azure-ad` or for development `http://localhost:3000/api/auth/callback/azure-ad`.
|
||||||
|
- After your App Registration is created, under "Client Credential" create your Client secret.
|
||||||
|
- Now copy your:
|
||||||
|
- Application (client) ID
|
||||||
|
- Directory (tenant) ID
|
||||||
|
- Client secret (value)
|
||||||
|
|
||||||
|
In `.env.local` create the following entries:
|
||||||
|
|
||||||
|
```
|
||||||
|
AZURE_AD_CLIENT_ID=<copy Application (client) ID here>
|
||||||
|
AZURE_AD_CLIENT_SECRET=<copy generated client secret value here>
|
||||||
|
AZURE_AD_TENANT_ID=<copy the tenant id here>
|
||||||
|
```
|
||||||
|
|
||||||
|
That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints).
|
||||||
|
|
||||||
|
:::note
|
||||||
|
When you see `ResourceNotFound` error code while accessing an API, make sure to use the correct tenant ID. For instance, when the intended access is for a personal account, the tenant ID should not be provided.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Azure AD returns the profile picture in an ArrayBuffer, instead of just a URL to the image, so our provider converts it to a base64 encoded image string and returns that instead. See: https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples. The default image size is 48x48 to avoid [running out of space](https://next-auth.js.org/faq#:~:text=What%20are%20the%20disadvantages%20of%20JSON%20Web%20Tokens%3F) in case the session is saved as a JWT.
|
||||||
|
:::
|
||||||
|
|
||||||
|
In `pages/api/auth/[...nextauth].js` find or add the `AzureAD` entries:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import AzureADProvider from "next-auth/providers/azure-ad";
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
AzureADProvider({
|
||||||
|
clientId: process.env.AZURE_AD_CLIENT_ID,
|
||||||
|
clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
|
||||||
|
tenantId: process.env.AZURE_AD_TENANT_ID,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
...
|
||||||
|
|
||||||
|
```
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
id: battle.net
|
||||||
|
title: Battle.net
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://develop.battle.net/documentation/guides/using-oauth
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://develop.battle.net/access/clients
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Battle.net Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Battle.net Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/battlenet.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import BattleNetProvider from "next-auth/providers/battlenet";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
BattleNetProvider({
|
||||||
|
clientId: process.env.BATTLENET_CLIENT_ID,
|
||||||
|
clientSecret: process.env.BATTLENET_CLIENT_SECRET,
|
||||||
|
issuer: process.env.BATTLENET_ISSUER
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
`issuer` must be one of these values, based on the [available regions](https://develop.battle.net/documentation/guides/regionality-and-apis):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type BattleNetIssuer =
|
||||||
|
| "https://www.battlenet.com.cn/oauth"
|
||||||
|
| "https://us.battle.net/oauth"
|
||||||
|
| "https://eu.battle.net/oauth"
|
||||||
|
| "https://kr.battle.net/oauth"
|
||||||
|
| "https://tw.battle.net/oauth"
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: box
|
||||||
|
title: Box
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.box.com/reference/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.box.com/guides/sso-identities-and-app-users/connect-okta-to-app-users/configure-box/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Box Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Box Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/box.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import BoxProvider from "next-auth/providers/box";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
BoxProvider({
|
||||||
|
clientId: process.env.BOX_CLIENT_ID,
|
||||||
|
clientSecret: process.env.BOX_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
id: boxyhq-saml
|
||||||
|
title: BoxyHQ SAML
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
BoxyHQ SAML is an open source service that handles the SAML login flow as an OAuth 2.0 flow, abstracting away all the complexities of the SAML protocol.
|
||||||
|
|
||||||
|
You can deploy BoxyHQ SAML as a separate service or embed it into your app using our NPM library. [Check out the documentation for more details](https://boxyhq.com/docs/jackson/deploy)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
SAML login requires a configuration for every tenant of yours. One common method is to use the domain for an email address to figure out which tenant they belong to. You can also use a unique tenant ID (string) from your backend for this, typically some kind of account or organization ID.
|
||||||
|
|
||||||
|
Check out the [documentation](https://boxyhq.com/docs/jackson/saml-flow#2-saml-config-api) for more details.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **BoxyHQ SAML Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [BoxyHQ Provider options](https://github.com/nextauthjs/next-auth/tree/v4/packages/next-auth/src/providers/boxyhq-saml.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import BoxyHQSAMLProvider from "next-auth/providers/boxyhq-saml"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
BoxyHQSAMLProvider({
|
||||||
|
issuer: "http://localhost:5225",
|
||||||
|
clientId: "dummy", // The dummy here is necessary since we'll pass tenant and product custom attributes in the client code
|
||||||
|
clientSecret: "dummy", // The dummy here is necessary since we'll pass tenant and product custom attributes in the client code
|
||||||
|
})
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
On the client side you'll need to pass additional parameters `tenant` and `product` to the `signIn` function. This will allow BoxyHQL SAML to figure out the right SAML configuration and take your user to the right SAML Identity Provider to sign them in.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { signIn } from "next-auth/react";
|
||||||
|
...
|
||||||
|
|
||||||
|
// Map your users's email to a tenant and product
|
||||||
|
const tenant = email.split("@")[1];
|
||||||
|
const product = 'my_awesome_product';
|
||||||
|
...
|
||||||
|
<Button
|
||||||
|
onClick={async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
signIn("boxyhq-saml", {}, { tenant, product });
|
||||||
|
}}>
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
---
|
||||||
|
id: bungie
|
||||||
|
title: Bungie
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://github.com/Bungie-net/api/wiki/OAuth-Documentation
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://www.bungie.net/en/Application
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Bungie Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Bungie Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/bungie.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import BungieProvider from "next-auth/providers/bungie";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
BungieProvider({
|
||||||
|
clientId: process.env.BUNGIE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.BUNGIE_SECRET,
|
||||||
|
headers: {
|
||||||
|
"X-API-Key": process.env.BUNGIE_API_KEY
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Bungie require all sites to run HTTPS (including local development instances).
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Bungie doesn't allow you to use localhost as the website URL, instead you need to use https://127.0.0.1:3000
|
||||||
|
:::
|
||||||
|
|
||||||
|
Navigate to https://www.bungie.net/en/Application and fill in the required details:
|
||||||
|
|
||||||
|
- Application name
|
||||||
|
- Application Status
|
||||||
|
- Website
|
||||||
|
- OAuth Client Type
|
||||||
|
- Confidential
|
||||||
|
- Redirect URL
|
||||||
|
- https://localhost:3000/api/auth/callback/bungie
|
||||||
|
- Scope
|
||||||
|
- `Access items like your Bungie.net notifications, memberships, and recent Bungie.Net forum activity.`
|
||||||
|
- Origin Header
|
||||||
|
|
||||||
|
The following guide may be helpful:
|
||||||
|
|
||||||
|
- [How to setup localhost with HTTPS with a Next.js app](https://medium.com/@anMagpie/secure-your-local-development-server-with-https-next-js-81ac6b8b3d68)
|
||||||
|
|
||||||
|
### Example server
|
||||||
|
|
||||||
|
You will need to edit your host file and point your site at `127.0.0.1`
|
||||||
|
|
||||||
|
[How to edit my host file?](https://phoenixnap.com/kb/how-to-edit-hosts-file-in-windows-mac-or-linux)
|
||||||
|
|
||||||
|
On Windows (Run Powershell as administrator)
|
||||||
|
|
||||||
|
```ps
|
||||||
|
Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "127.0.0.1`tdev.example.com" -Force
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
127.0.0.1 dev.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create certificate
|
||||||
|
|
||||||
|
Creating a certificate for localhost is easy with openssl. Just put the following command in the terminal. The output will be two files: localhost.key and localhost.crt.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl req -x509 -out localhost.crt -keyout localhost.key \
|
||||||
|
-newkey rsa:2048 -nodes -sha256 \
|
||||||
|
-subj "/CN=localhost" -extensions EXT -config <( \
|
||||||
|
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
**Windows**
|
||||||
|
|
||||||
|
The OpenSSL executable is distributed with [Git](https://git-scm.com/download/win]9) for Windows.
|
||||||
|
Once installed you will find the openssl.exe file in `C:/Program Files/Git/mingw64/bin` which you can add to the system PATH environment variable if it’s not already done.
|
||||||
|
|
||||||
|
Add environment variable `OPENSSL_CONF=C:/Program Files/Git/mingw64/ssl/openssl.cnf`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
req -x509 -out localhost.crt -keyout localhost.key \
|
||||||
|
-newkey rsa:2048 -nodes -sha256 \
|
||||||
|
-subj "/CN=localhost"
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Create directory `certificates` and place `localhost.key` and `localhost.crt`
|
||||||
|
|
||||||
|
You can create a `server.js` in the root of your project and run it with `node server.js` to test Sign in with Bungie integration locally:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { createServer } = require("https")
|
||||||
|
const { parse } = require("url")
|
||||||
|
const next = require("next")
|
||||||
|
const fs = require("fs")
|
||||||
|
|
||||||
|
const dev = process.env.NODE_ENV !== "production"
|
||||||
|
const app = next({ dev })
|
||||||
|
const handle = app.getRequestHandler()
|
||||||
|
|
||||||
|
const httpsOptions = {
|
||||||
|
key: fs.readFileSync("./certificates/localhost.key"),
|
||||||
|
cert: fs.readFileSync("./certificates/localhost.crt"),
|
||||||
|
}
|
||||||
|
|
||||||
|
app.prepare().then(() => {
|
||||||
|
createServer(httpsOptions, (req, res) => {
|
||||||
|
const parsedUrl = parse(req.url, true)
|
||||||
|
handle(req, res, parsedUrl)
|
||||||
|
}).listen(3000, (err) => {
|
||||||
|
if (err) throw err
|
||||||
|
console.log("> Ready on https://localhost:3000")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
id: cognito
|
||||||
|
title: Amazon Cognito
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://console.aws.amazon.com/cognito/users/
|
||||||
|
|
||||||
|
You need to select your AWS region to go the the Cognito dashboard.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Amazon Cognito Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Amazon Cognito Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/cognito.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import CognitoProvider from "next-auth/providers/cognito";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
CognitoProvider({
|
||||||
|
clientId: process.env.COGNITO_CLIENT_ID,
|
||||||
|
clientSecret: process.env.COGNITO_CLIENT_SECRET,
|
||||||
|
issuer: process.env.COGNITO_ISSUER,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The issuer is a URL, that looks like this: `https://cognito-idp.{region}.amazonaws.com/{PoolId}`
|
||||||
|
:::
|
||||||
|
|
||||||
|
`PoolId` is from `General Settings` in Cognito, not to be confused with the App Client ID.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Make sure you select all the appropriate client settings or the OAuth flow will not work.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Before you can set these settings, you must [set up an Amazon Cognito hosted domain](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-assign-domain.html). The setting can be found in `App Client/Edit Hosted UI`.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: coinbase
|
||||||
|
title: Coinbase
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.coinbase.com/api/v2
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://www.coinbase.com/settings/api
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Coinbase Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Coinbase Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/coinbase.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import CoinbaseProvider from "next-auth/providers/coinbase";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
CoinbaseProvider({
|
||||||
|
clientId: process.env.COINBASE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.COINBASE_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
This Provider template has a 2 hour access token to it. A refresh token is also returned.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
---
|
||||||
|
id: credentials
|
||||||
|
title: Credentials
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Credentials provider allows you to handle signing in with arbitrary credentials, such as a username and password, domain, or two factor authentication or hardware device (e.g. YubiKey U2F / FIDO).
|
||||||
|
|
||||||
|
It is intended to support use cases where you have an existing system you need to authenticate users against.
|
||||||
|
|
||||||
|
It comes with the constraint that users authenticated in this manner are not persisted in the database, and consequently that the Credentials provider can only be used if JSON Web Tokens are enabled for sessions.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
The functionality provided for credentials based authentication is intentionally limited to discourage use of passwords due to the inherent security risks associated with them and the additional complexity associated with supporting usernames and passwords.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Credentials Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Credentials Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/credentials.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example - Username / Password
|
||||||
|
|
||||||
|
The Credentials provider is specified like other providers, except that you need to define a handler for `authorize()` that accepts credentials submitted via HTTP POST as input and returns either:
|
||||||
|
|
||||||
|
1. A `user` object, which indicates the credentials are valid.
|
||||||
|
|
||||||
|
If you return an object it will be persisted to the JSON Web Token and the user will be signed in, unless a custom `signIn()` callback is configured that subsequently rejects it.
|
||||||
|
|
||||||
|
2. If you return `null` then an error will be displayed advising the user to check their details.
|
||||||
|
|
||||||
|
3. If you throw an Error, the user will be sent to the error page with the error message as a query parameter.
|
||||||
|
|
||||||
|
The Credentials provider's `authorize()` method also provides the request object as the second parameter (see example below).
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth]/route.js"
|
||||||
|
import CredentialsProvider from "next-auth/providers/credentials";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
CredentialsProvider({
|
||||||
|
// The name to display on the sign in form (e.g. "Sign in with...")
|
||||||
|
name: "Credentials",
|
||||||
|
// `credentials` is used to generate a form on the sign in page.
|
||||||
|
// You can specify which fields should be submitted, by adding keys to the `credentials` object.
|
||||||
|
// e.g. domain, username, password, 2FA token, etc.
|
||||||
|
// You can pass any HTML attribute to the <input> tag through the object.
|
||||||
|
credentials: {
|
||||||
|
username: { label: "Username", type: "text", placeholder: "jsmith" },
|
||||||
|
password: { label: "Password", type: "password" }
|
||||||
|
},
|
||||||
|
async authorize(credentials, req) {
|
||||||
|
// Add logic here to look up the user from the credentials supplied
|
||||||
|
const user = { id: "1", name: "J Smith", email: "jsmith@example.com" }
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
// Any object returned will be saved in `user` property of the JWT
|
||||||
|
return user
|
||||||
|
} else {
|
||||||
|
// If you return null then an error will be displayed advising the user to check their details.
|
||||||
|
return null
|
||||||
|
|
||||||
|
// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [callbacks documentation](/configuration/callbacks) for more information on how to interact with the token.
|
||||||
|
|
||||||
|
## Example - Web3 / Signin With Ethereum
|
||||||
|
|
||||||
|
The credentials provider can also be used to integrate with a service like [Sign-in With Ethereum](https://login.xyz).
|
||||||
|
|
||||||
|
For more information, check out the links below:
|
||||||
|
|
||||||
|
- [Tutorial](https://docs.login.xyz/integrations/nextauth.js)
|
||||||
|
- [Example App Repo](https://github.com/spruceid/siwe-next-auth-example).
|
||||||
|
- [Example App Demo](https://siwe-next-auth-example2.vercel.app/).
|
||||||
|
|
||||||
|
## Multiple providers
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
You can specify more than one credentials provider by specifying a unique `id` for each one.
|
||||||
|
|
||||||
|
You can also use them in conjunction with other provider options.
|
||||||
|
|
||||||
|
As with all providers, the order you specify them is the order they are displayed on the sign in page.
|
||||||
|
|
||||||
|
```js
|
||||||
|
providers: [
|
||||||
|
CredentialsProvider({
|
||||||
|
id: "domain-login",
|
||||||
|
name: "Domain Account",
|
||||||
|
async authorize(credentials, req) {
|
||||||
|
const user = {
|
||||||
|
/* add function to get user */
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
},
|
||||||
|
credentials: {
|
||||||
|
domain: {
|
||||||
|
label: "Domain",
|
||||||
|
type: "text ",
|
||||||
|
placeholder: "CORPNET",
|
||||||
|
value: "CORPNET",
|
||||||
|
},
|
||||||
|
username: { label: "Username", type: "text ", placeholder: "jsmith" },
|
||||||
|
password: { label: "Password", type: "password" },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
CredentialsProvider({
|
||||||
|
id: "intranet-credentials",
|
||||||
|
name: "Two Factor Auth",
|
||||||
|
async authorize(credentials, req) {
|
||||||
|
const user = {
|
||||||
|
/* add function to get user */
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
},
|
||||||
|
credentials: {
|
||||||
|
username: { label: "Username", type: "text ", placeholder: "jsmith" },
|
||||||
|
"2fa-key": { label: "2FA Key" },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
/* ... additional providers ... /*/
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: discord
|
||||||
|
title: Discord
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://discord.com/developers/docs/topics/oauth2
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://discord.com/developers/applications
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Discord Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Discord Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/discord.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import DiscordProvider from "next-auth/providers/discord";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
DiscordProvider({
|
||||||
|
clientId: process.env.DISCORD_CLIENT_ID,
|
||||||
|
clientSecret: process.env.DISCORD_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: dropbox
|
||||||
|
title: Dropbox
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.dropbox.com/oauth-guide
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://www.dropbox.com/developers/apps
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Dropbox Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Dropbox Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/dropbox.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import DropboxProvider from "next-auth/providers/dropbox";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
DropboxProvider({
|
||||||
|
clientId: process.env.DROPBOX_CLIENT_ID,
|
||||||
|
clientSecret: process.env.DROPBOX_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
id: duende-identityserver6
|
||||||
|
title: DuendeIdentityServer6
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.duendesoftware.com/identityserver/v6
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **DuendeIdentityServer6 Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [DuendeIdentityServer6 Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/duende-identity-server6.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import DuendeIDS6Provider from "next-auth/providers/duende-identity-server6"
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
DuendeIDS6Provider({
|
||||||
|
clientId: process.env.DUENDE_IDS6_ID,
|
||||||
|
clientSecret: process.env.DUENDE_IDS6_SECRET,
|
||||||
|
issuer: process.env.DUENDE_IDS6_ISSUER,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Demo IdentityServer
|
||||||
|
|
||||||
|
The configuration below is for the demo server at https://demo.duendesoftware.com/
|
||||||
|
|
||||||
|
If you want to try it out, you can copy and paste the configuration below.
|
||||||
|
|
||||||
|
You can sign in to the demo service with either <b>bob/bob</b> or <b>alice/alice</b>.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import DuendeIDS6Provider from "next-auth/providers/duende-identity-server6"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
DuendeIDS6Provider({
|
||||||
|
clientId: "interactive.confidential",
|
||||||
|
clientSecret: "secret",
|
||||||
|
issuer: "https://demo.duendesoftware.com",
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
---
|
||||||
|
id: email
|
||||||
|
title: Email
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Email provider uses email to send "magic links" that can be used to sign in, you will likely have seen these if you have used services like Slack before.
|
||||||
|
|
||||||
|
Adding support for signing in via email in addition to one or more OAuth services provides a way for users to sign in if they lose access to their OAuth account (e.g. if it is locked or deleted).
|
||||||
|
|
||||||
|
The Email provider can be used in conjunction with (or instead of) one or more OAuth providers.
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
|
||||||
|
On initial sign in, a **Verification Token** is sent to the email address provided. By default this token is valid for 24 hours. If the Verification Token is used within that time (i.e. by clicking on the link in the email) an account is created for the user and they are signed in.
|
||||||
|
|
||||||
|
If someone provides the email address of an _existing account_ when signing in, an email is sent and they are signed into the account associated with that email address when they follow the link in the email.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The Email Provider can be used with both JSON Web Tokens and database sessions, but you **must** configure a database to use it. It is not possible to enable email sign in without using a database.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Email Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Email Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/email.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
NextAuth.js lets you send emails either via HTTP or SMTP.
|
||||||
|
|
||||||
|
### HTTP
|
||||||
|
|
||||||
|
Check out our [HTTP-based Email Provider](https://authjs.dev/guides/configuring-http-email) guide.
|
||||||
|
|
||||||
|
### SMTP
|
||||||
|
|
||||||
|
1. NextAuth.js does not include `nodemailer` as a dependency, so you'll need to install it yourself if you want to use the Email Provider. Run `npm install nodemailer` or `yarn add nodemailer`.
|
||||||
|
2. You will need an SMTP account; ideally for one of the [services known to work with `nodemailer`](https://community.nodemailer.com/2-0-0-beta/setup-smtp/well-known-services/).
|
||||||
|
3. There are two ways to configure the SMTP server connection.
|
||||||
|
|
||||||
|
You can either use a connection string or a `nodemailer` configuration object or transport.
|
||||||
|
|
||||||
|
2.1 **Using a connection string**
|
||||||
|
|
||||||
|
Create an `.env` file to the root of your project and add the connection string and email address.
|
||||||
|
|
||||||
|
```js title=".env" {1}
|
||||||
|
EMAIL_SERVER=smtp://username:password@smtp.example.com:587
|
||||||
|
EMAIL_FROM=noreply@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can add the email provider like this:
|
||||||
|
|
||||||
|
```js {3} title="pages/api/auth/[...nextauth].js"
|
||||||
|
import EmailProvider from "next-auth/providers/email";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
EmailProvider({
|
||||||
|
server: process.env.EMAIL_SERVER,
|
||||||
|
from: process.env.EMAIL_FROM
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
2.2 **Using a configuration object**
|
||||||
|
|
||||||
|
In your `.env` file in the root of your project simply add the configuration object options individually:
|
||||||
|
|
||||||
|
```js title=".env"
|
||||||
|
EMAIL_SERVER_USER=username
|
||||||
|
EMAIL_SERVER_PASSWORD=password
|
||||||
|
EMAIL_SERVER_HOST=smtp.example.com
|
||||||
|
EMAIL_SERVER_PORT=587
|
||||||
|
EMAIL_FROM=noreply@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can add the provider settings to the NextAuth.js options object in the Email Provider.
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
import EmailProvider from "next-auth/providers/email";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
EmailProvider({
|
||||||
|
server: {
|
||||||
|
host: process.env.EMAIL_SERVER_HOST,
|
||||||
|
port: process.env.EMAIL_SERVER_PORT,
|
||||||
|
auth: {
|
||||||
|
user: process.env.EMAIL_SERVER_USER,
|
||||||
|
pass: process.env.EMAIL_SERVER_PASSWORD
|
||||||
|
}
|
||||||
|
},
|
||||||
|
from: process.env.EMAIL_FROM
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Do not forget to setup one of the database [adapters](https://authjs.dev/getting-started/database) for storing the Email verification token.
|
||||||
|
|
||||||
|
4. You can now sign in with an email address at `/api/auth/signin`.
|
||||||
|
|
||||||
|
A user account (i.e. an entry in the Users table) will not be created for the user until the first time they verify their email address. If an email address is already associated with an account, the user will be signed in to that account when they use the link in the email.
|
||||||
|
|
||||||
|
## Customizing emails
|
||||||
|
|
||||||
|
You can fully customize the sign in email that is sent by passing a custom function as the `sendVerificationRequest` option to `EmailProvider()`.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
```js {3} title="pages/api/auth/[...nextauth].js"
|
||||||
|
import EmailProvider from "next-auth/providers/email";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
EmailProvider({
|
||||||
|
server: process.env.EMAIL_SERVER,
|
||||||
|
from: process.env.EMAIL_FROM,
|
||||||
|
sendVerificationRequest({
|
||||||
|
identifier: email,
|
||||||
|
url,
|
||||||
|
provider: { server, from },
|
||||||
|
}) {
|
||||||
|
/* your function */
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
The following code shows the complete source for the built-in `sendVerificationRequest()` method:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createTransport } from "nodemailer"
|
||||||
|
|
||||||
|
async function sendVerificationRequest(params) {
|
||||||
|
const { identifier, url, provider, theme } = params
|
||||||
|
const { host } = new URL(url)
|
||||||
|
// NOTE: You are not required to use `nodemailer`, use whatever you want.
|
||||||
|
const transport = createTransport(provider.server)
|
||||||
|
const result = await transport.sendMail({
|
||||||
|
to: identifier,
|
||||||
|
from: provider.from,
|
||||||
|
subject: `Sign in to ${host}`,
|
||||||
|
text: text({ url, host }),
|
||||||
|
html: html({ url, host, theme }),
|
||||||
|
})
|
||||||
|
const failed = result.rejected.concat(result.pending).filter(Boolean)
|
||||||
|
if (failed.length) {
|
||||||
|
throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Email HTML body
|
||||||
|
* Insert invisible space into domains from being turned into a hyperlink by email
|
||||||
|
* clients like Outlook and Apple mail, as this is confusing because it seems
|
||||||
|
* like they are supposed to click on it to sign in.
|
||||||
|
*
|
||||||
|
* @note We don't add the email address to avoid needing to escape it, if you do, remember to sanitize it!
|
||||||
|
*/
|
||||||
|
function html(params: { url: string, host: string, theme: Theme }) {
|
||||||
|
const { url, host, theme } = params
|
||||||
|
|
||||||
|
const escapedHost = host.replace(/\./g, "​.")
|
||||||
|
|
||||||
|
const brandColor = theme.brandColor || "#346df1"
|
||||||
|
const color = {
|
||||||
|
background: "#f9f9f9",
|
||||||
|
text: "#444",
|
||||||
|
mainBackground: "#fff",
|
||||||
|
buttonBackground: brandColor,
|
||||||
|
buttonBorder: brandColor,
|
||||||
|
buttonText: theme.buttonText || "#fff",
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<body style="background: ${color.background};">
|
||||||
|
<table width="100%" border="0" cellspacing="20" cellpadding="0"
|
||||||
|
style="background: ${color.mainBackground}; max-width: 600px; margin: auto; border-radius: 10px;">
|
||||||
|
<tr>
|
||||||
|
<td align="center"
|
||||||
|
style="padding: 10px 0px; font-size: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
|
||||||
|
Sign in to <strong>${escapedHost}</strong>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="padding: 20px 0;">
|
||||||
|
<table border="0" cellspacing="0" cellpadding="0">
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="border-radius: 5px;" bgcolor="${color.buttonBackground}"><a href="${url}"
|
||||||
|
target="_blank"
|
||||||
|
style="font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: ${color.buttonText}; text-decoration: none; border-radius: 5px; padding: 10px 20px; border: 1px solid ${color.buttonBorder}; display: inline-block; font-weight: bold;">Sign
|
||||||
|
in</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"
|
||||||
|
style="padding: 0px 0px 10px 0px; font-size: 16px; line-height: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
|
||||||
|
If you did not request this email you can safely ignore it.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Email Text body (fallback for email clients that don't render HTML, e.g. feature phones) */
|
||||||
|
function text({ url, host }: { url: string, host: string }) {
|
||||||
|
return `Sign in to ${host}\n${url}\n\n`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
If you want to generate great looking email client compatible HTML with React, check out https://mjml.io
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Customizing the Verification Token
|
||||||
|
|
||||||
|
By default, we are generating a random verification token. You can define a `generateVerificationToken` method in your provider options if you want to override it:
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
providers: [
|
||||||
|
EmailProvider({
|
||||||
|
async generateVerificationToken() {
|
||||||
|
return "ABC123"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
## Normalizing the email address
|
||||||
|
|
||||||
|
By default, NextAuth.js will normalize the email address. It treats values as case-insensitive (which is technically not compliant to the [RFC 2821 spec](https://datatracker.ietf.org/doc/html/rfc2821), but in practice this causes more problems than it solves, eg. when looking up users by e-mail from databases.) and also removes any secondary email address that was passed in as a comma-separated list. You can apply your own normalization via the `normalizeIdentifier` method on the `EmailProvider`. The following example shows the default behavior:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
EmailProvider({
|
||||||
|
// ...
|
||||||
|
normalizeIdentifier(identifier: string): string {
|
||||||
|
// Get the first two elements only,
|
||||||
|
// separated by `@` from user input.
|
||||||
|
let [local, domain] = identifier.toLowerCase().trim().split("@")
|
||||||
|
// The part before "@" can contain a ","
|
||||||
|
// but we remove it on the domain part
|
||||||
|
domain = domain.split(",")[0]
|
||||||
|
return `${local}@${domain}`
|
||||||
|
|
||||||
|
// You can also throw an error, which will redirect the user
|
||||||
|
// to the error page with error=EmailSignin in the URL
|
||||||
|
// if (identifier.split("@").length > 2) {
|
||||||
|
// throw new Error("Only one email allowed")
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Always make sure this returns a single e-mail address, even if multiple ones were passed in.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Sending Magic Links To Existing Users
|
||||||
|
|
||||||
|
You can ensure that only existing users are sent a magic login link. You will need to grab the email the user entered and check your database to see if the email already exists in the "User" collection in your database. If it exists, it will send the user a magic link but otherwise, you can send the user to another page, such as "/register".
|
||||||
|
|
||||||
|
```js title="pages/api/auth/[...nextauth].js"
|
||||||
|
import User from "../../../models/User";
|
||||||
|
import db from "../../../utils/db";
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async signIn({ user, account, email }) {
|
||||||
|
await db.connect();
|
||||||
|
const userExists = await User.findOne({
|
||||||
|
email: user.email, //the user object has an email property, which contains the email the user entered.
|
||||||
|
});
|
||||||
|
if (userExists) {
|
||||||
|
return true; //if the email exists in the User collection, email them a magic login link
|
||||||
|
} else {
|
||||||
|
return "/register";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
id: eveonline
|
||||||
|
title: EVE Online
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.eveonline.com/blog/article/sso-to-authenticated-calls
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.eveonline.com/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **EVE Online Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [EVE Online Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/eveonline.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import EVEOnlineProvider from "next-auth/providers/eveonline";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
EVEOnlineProvider({
|
||||||
|
clientId: process.env.EVE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.EVE_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip When creating your application, make sure to select `Authentication Only` as the connection type.
|
||||||
|
|
||||||
|
:::tip If using JWT for the session, you can add the `CharacterID` to the JWT token and session. Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
...
|
||||||
|
options: {
|
||||||
|
jwt: {
|
||||||
|
secret: process.env.JWT_SECRET,
|
||||||
|
},
|
||||||
|
callbacks: {
|
||||||
|
session: async ({ session, token }) => {
|
||||||
|
session.user.id = token.id;
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
id: facebook
|
||||||
|
title: Facebook
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.facebook.com/apps/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Facebook Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Facebook Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/facebook.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import FacebookProvider from "next-auth/providers/facebook";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
FacebookProvider({
|
||||||
|
clientId: process.env.FACEBOOK_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FACEBOOK_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Production applications cannot use localhost URLs to sign in with Facebook. You need to use a dedicated development application in Facebook to use **localhost** callback URLs.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Email address may not be returned for accounts created on mobile.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: faceit
|
||||||
|
title: FACEIT
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://cdn.faceit.com/third_party/docs/FACEIT_Connect_3.0.pdf
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.faceit.com/apps
|
||||||
|
|
||||||
|
Grant type: `Authorization Code`
|
||||||
|
|
||||||
|
Scopes to have basic infos (email, nickname, guid and avatar) : `openid`, `email`, `profile`
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **FACEIT Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [FACEIT Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/faceit.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import FaceItProvider from "next-auth/providers/faceit";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
FaceItProvider({
|
||||||
|
clientId: process.env.FACEIT_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FACEIT_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
id: foursquare
|
||||||
|
title: Foursquare
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.foursquare.com/docs/places-api/authentication/#web-applications
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.foursquare.com/
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Foursquare requires an additional `apiVersion` parameter in [`YYYYMMDD` format](https://developer.foursquare.com/docs/places-api/versioning/), which essentially states "I'm prepared for API changes up to this date".
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Foursquare Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Foursquare Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/foursquare.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import FourSquareProvider from "next-auth/providers/foursquare";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
FourSquareProvider({
|
||||||
|
clientId: process.env.FOURSQUARE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FOURSQUARE_CLIENT_SECRET,
|
||||||
|
apiVersion: "YYYYMMDD"
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: freshbooks
|
||||||
|
title: Freshbooks
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://www.freshbooks.com/api/authenticating-with-oauth-2-0-on-the-new-freshbooks-api
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://my.freshbooks.com/#/developer
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The Freshbooks Provider comes with a set of default options:
|
||||||
|
|
||||||
|
https://www.freshbooks.com/api/start
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import FreshbooksProvider from "next-auth/providers/freshbooks";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
FreshbooksProvider({
|
||||||
|
clientId: process.env.FRESHBOOKS_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FRESHBOOKS_CLIENT_SECRET,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
id: fusionauth
|
||||||
|
title: FusionAuth
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://fusionauth.io/docs/v1/tech/oauth/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **FusionAuth Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [FusionAuth Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/fusionauth.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import FusionAuthProvider from "next-auth/providers/fusionauth";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
FusionAuthProvider({
|
||||||
|
id: "fusionauth",
|
||||||
|
name: "FusionAuth",
|
||||||
|
issuer: process.env.FUSIONAUTH_ISSUER,
|
||||||
|
clientId: process.env.FUSIONAUTH_CLIENT_ID,
|
||||||
|
clientSecret: process.env.FUSIONAUTH_SECRET,
|
||||||
|
tenantId: process.env.FUSIONAUTH_TENANT_ID // Only required if you're using multi-tenancy
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
If you're using multi-tenancy, you need to pass in the `tenantId` option to apply the proper theme.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
An application can be created at https://your-fusionauth-server-url/admin/application.
|
||||||
|
|
||||||
|
For more information, follow the [FusionAuth 5-minute setup guide](https://fusionauth.io/docs/v1/tech/5-minute-setup-guide).
|
||||||
|
:::
|
||||||
|
|
||||||
|
In the OAuth settings for your application, configure the following.
|
||||||
|
|
||||||
|
- Redirect URL
|
||||||
|
- http://localhost:3000/api/auth/callback/fusionauth
|
||||||
|
- Enabled grants
|
||||||
|
- Make sure _Authorization Code_ is enabled.
|
||||||
|
|
||||||
|
If using JSON Web Tokens, you need to make sure the signing algorithm is RS256, you can create an RS256 key pair by
|
||||||
|
going to Settings, Key Master, generate RSA and choosing SHA-256 as algorithm. After that, go to the JWT settings of
|
||||||
|
your application and select this key as Access Token signing key and Id Token signing key.
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
id: github
|
||||||
|
title: GitHub
|
||||||
|
---
|
||||||
|
|
||||||
|
GitHub returns a field on `Account` called `refresh_token_expires_in` which is a number. See their [docs](https://docs.github.com/en/developers/apps/building-github-apps/refreshing-user-to-server-access-tokens#response). Remember to add this field to your database schema, in case if you are using an [Adapter](https://authjs.dev/getting-started/database).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://github.com/settings/apps
|
||||||
|
|
||||||
|
:::info
|
||||||
|
When creating a GitHub App, make sure to set the "Email addresses" account permission to read-only in order to access private email addresses on GitHub.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **GitHub Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [GitHub Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/github.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import GitHubProvider from "next-auth/providers/github";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
GitHubProvider({
|
||||||
|
clientId: process.env.GITHUB_ID,
|
||||||
|
clientSecret: process.env.GITHUB_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Only allows one callback URL per Client ID / Client Secret.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Email address is always returned, even if the user doesn't have a public email address on their profile.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
id: gitlab
|
||||||
|
title: GitLab
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
GitLab returns a field on `Account` called `created_at` which is a number. See their [docs](https://docs.gitlab.com/ee/api/oauth2.html). Remember to add this field as optional to your database schema, in case if you are using an [Adapter](https://next-auth.js.org/adapters).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.gitlab.com/ee/api/oauth2.html
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://gitlab.com/-/profile/applications
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Gitlab Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Gitlab Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/gitlab.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import GitlabProvider from "next-auth/providers/gitlab";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
GitlabProvider({
|
||||||
|
clientId: process.env.GITLAB_CLIENT_ID,
|
||||||
|
clientSecret: process.env.GITLAB_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Enable the _"read_user"_ option in scope if you want to save the users email address on sign up.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
id: google
|
||||||
|
title: Google
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.google.com/identity/protocols/oauth2
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://console.developers.google.com/apis/credentials
|
||||||
|
|
||||||
|
The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path. For example;
|
||||||
|
|
||||||
|
- For production: `https://{YOUR_DOMAIN}/api/auth/callback/google`
|
||||||
|
- For development: `http://localhost:3000/api/auth/callback/google`
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Google Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Google Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/google.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import GoogleProvider from "next-auth/providers/google";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
GoogleProvider({
|
||||||
|
clientId: process.env.GOOGLE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Google only provides Refresh Token to an application the first time a user signs in.
|
||||||
|
|
||||||
|
To force Google to re-issue a Refresh Token, the user needs to remove the application from their account and sign in again:
|
||||||
|
https://myaccount.google.com/permissions
|
||||||
|
|
||||||
|
Alternatively, you can also pass options in the `params` object of `authorization` which will force the Refresh Token to always be provided on sign in, however this will ask all users to confirm if they wish to grant your application access every time they sign in.
|
||||||
|
|
||||||
|
If you need access to the RefreshToken or AccessToken for a Google account and you are not using a database to persist user accounts, this may be something you need to do.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const options = {
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
GoogleProvider({
|
||||||
|
clientId: process.env.GOOGLE_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_SECRET,
|
||||||
|
authorization: {
|
||||||
|
params: {
|
||||||
|
prompt: "consent",
|
||||||
|
access_type: "offline",
|
||||||
|
response_type: "code"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Google also returns a `email_verified` boolean property in the OAuth profile.
|
||||||
|
|
||||||
|
You can use this property to restrict access to people with verified accounts at a particular domain.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const options = {
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async signIn({ account, profile }) {
|
||||||
|
if (account.provider === "google") {
|
||||||
|
return profile.email_verified && profile.email.endsWith("@example.com")
|
||||||
|
}
|
||||||
|
return true // Do different verification for other providers that don't have `email_verified`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
id: hubspot
|
||||||
|
title: HubSpot
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
HubSpot returns a limited amount of information on the token holder (see [docs](https://legacydocs.hubspot.com/docs/methods/oauth2/get-access-token-information)). One other issue is that the name and profile photo cannot be fetched through API as discussed [here](https://community.hubspot.com/t5/APIs-Integrations/Profile-photo-is-not-retrieved-with-User-API/m-p/325521).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.hubspot.com/docs/api/oauth-quickstart-guide
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
You need to have an APP in your Developer Account as described at https://developers.hubspot.com/docs/api/developer-tools-overview
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **HubSpot Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [HubSpot Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/hubspot.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import HubspotProvider from "next-auth/providers/hubspot";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
HubspotProvider({
|
||||||
|
clientId: process.env.HUBSPOT_CLIENT_ID,
|
||||||
|
clientSecret: process.env.HUBSPOT_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
The **Redirect URL** under the **Auth** tab on the HubSpot App Settings page must match the callback url which would be http://localhost:3000/api/auth/callback/hubspot for local development. Only one callback URL per Client ID and Client Secret pair is allowed, so it might be easier to create a new app for local development then fiddle with the url changes.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
id: identity-server4
|
||||||
|
title: IdentityServer4
|
||||||
|
---
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
[IdentityServer4 is discontinued](https://identityserver4.readthedocs.io/en/latest/#:~:text=until%20November%202022.) and only releases security updates until November 2022. You should consider an alternative provider.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://identityserver4.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **IdentityServer4 Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [IdentityServer4 Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/identity-server4.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import IdentityServer4Provider from "next-auth/providers/identity-server4";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
IdentityServer4Provider({
|
||||||
|
id: "identity-server4",
|
||||||
|
name: "IdentityServer4",
|
||||||
|
issuer: process.env.IdentityServer4_Issuer,
|
||||||
|
clientId: process.env.IdentityServer4_CLIENT_ID,
|
||||||
|
clientSecret: process.env.IdentityServer4_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
id: overview
|
||||||
|
title: Overview
|
||||||
|
---
|
||||||
|
|
||||||
|
Authentication Providers in **NextAuth.js** are services that can be used to sign in a user.
|
||||||
|
|
||||||
|
There are four ways a user can be signed in:
|
||||||
|
|
||||||
|
- [Using a built-in OAuth Provider](/configuration/providers/oauth) (e.g Github, Twitter, Google, etc...)
|
||||||
|
- [Using a custom OAuth Provider](/configuration/providers/oauth#using-a-custom-provider)
|
||||||
|
- [Using Email](/configuration/providers/email)
|
||||||
|
- [Using Credentials](/configuration/providers/credentials)
|
||||||
|
|
||||||
|
:::note
|
||||||
|
NextAuth.js is designed to work with any OAuth service, it supports **OAuth 1.0**, **1.0A**, **2.0** and **OpenID Connect (OIDC)** and has built-in support for most popular sign-in services.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
id: instagram
|
||||||
|
title: Instagram
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.facebook.com/docs/instagram-basic-display-api/getting-started
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.facebook.com/apps/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Instagram Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Instagram Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/instagram.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// pages/api/auth/[...nextauth].js
|
||||||
|
import InstagramProvider from "next-auth/providers/instagram";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
InstagramProvider({
|
||||||
|
clientId: process.env.INSTAGRAM_CLIENT_ID,
|
||||||
|
clientSecret: process.env.INSTAGRAM_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
// pages/index.jsx
|
||||||
|
import { signIn } from "next-auth/react"
|
||||||
|
...
|
||||||
|
<button onClick={() => signIn("instagram")}>
|
||||||
|
Sign in
|
||||||
|
</button>
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Email address is not returned by the Instagram API.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Instagram display app required callback URL to be configured in your Facebook app and Facebook required you to use **https** even for localhost! In order to do that, you either need to [add an SSL to your localhost](https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec/) or use a proxy such as [ngrok](https://ngrok.com/docs).
|
||||||
|
:::
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
id: kakao
|
||||||
|
title: Kakao
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.kakao.com/product/kakaoLogin
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.kakao.com/docs/latest/en/kakaologin/common
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Kakao Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Kakao Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/kakao.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import KakaoProvider from "next-auth/providers/kakao";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
KakaoProvider({
|
||||||
|
clientId: process.env.KAKAO_CLIENT_ID,
|
||||||
|
clientSecret: process.env.KAKAO_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Create a provider and a Kakao application at `https://developers.kakao.com/console/app`. In the settings of the app under Kakao Login, activate web app, change consent items and configure callback URL.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
id: keycloak
|
||||||
|
title: Keycloak
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://www.keycloak.org/docs/latest/server_admin/#_oidc_clients
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Create an openid-connect client in Keycloak with "confidential" as the "Access Type".
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Keycloak Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Keycloak Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/keycloak.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import KeycloakProvider from "next-auth/providers/keycloak";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
KeycloakProvider({
|
||||||
|
clientId: process.env.KEYCLOAK_ID,
|
||||||
|
clientSecret: process.env.KEYCLOAK_SECRET,
|
||||||
|
issuer: process.env.KEYCLOAK_ISSUER,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
`issuer` should include the realm – e.g. `https://my-keycloak-domain.com/realms/My_Realm`
|
||||||
|
:::
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
id: line
|
||||||
|
title: LINE
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.line.biz/en/docs/line-login/integrate-line-login/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.line.biz/console/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Line Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Line Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/line.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import LineProvider from "next-auth/providers/line";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
LineProvider({
|
||||||
|
clientId: process.env.LINE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.LINE_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Create a provider and a LINE login channel at `https://developers.line.biz/console/`. In the settings of the channel under LINE Login, activate web app and configure the following:
|
||||||
|
|
||||||
|
- Callback URL
|
||||||
|
- http://localhost:3000/api/auth/callback/line
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
To retrieve email address, you need to apply for Email address permission. Open [Line Developer Console](https://developers.line.biz/console/), go to your Login Channel. Scroll down bottom to find **OpenID Connect** -> **Email address permission**. Click **Apply** and follow the instruction.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: linkedin
|
||||||
|
title: LinkedIn
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://www.linkedin.com/developers/apps/
|
||||||
|
|
||||||
|
From the Auth tab get the client ID and client secret. On the same tab, add redirect URLs such as http://localhost:3000/api/auth/callback/linkedin so LinkedIn can correctly redirect back to your application. Finally, head over to the Products tab and enable the "Sign In with LinkedIn" product. The LinkedIn team will review and approve your request before you can test it out.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **LinkedIn Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [LinkedIn Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/linkedin.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import LinkedInProvider from "next-auth/providers/linkedin";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
LinkedInProvider({
|
||||||
|
clientId: process.env.LINKEDIN_CLIENT_ID,
|
||||||
|
clientSecret: process.env.LINKEDIN_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: mailchimp
|
||||||
|
title: Mailchimp
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://mailchimp.com/developer/marketing/guides/access-user-data-oauth-2/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://admin.mailchimp.com/account/oauth2/client/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Mailchimp Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Mailchimp Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/mailchimp.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import MailchimpProvider from "next-auth/providers/mailchimp";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
MailchimpProvider({
|
||||||
|
clientId: process.env.MAILCHIMP_CLIENT_ID,
|
||||||
|
clientSecret: process.env.MAILCHIMP_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: mailru
|
||||||
|
title: Mail.ru
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://o2.mail.ru/docs
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://o2.mail.ru/app/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Mail.ru Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Mail.ru Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/mailru.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import MailRuProvider from "next-auth/providers/mailru";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
MailRuProvider({
|
||||||
|
clientId: process.env.MAILRU_CLIENT_ID,
|
||||||
|
clientSecret: process.env.MAILRU_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: medium
|
||||||
|
title: Medium
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://github.com/Medium/medium-api-docs
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://medium.com/me/applications
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Medium Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Medium Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/medium.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import MediumProvider from "next-auth/providers/medium";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
MediumProvider({
|
||||||
|
clientId: process.env.MEDIUM_CLIENT_ID,
|
||||||
|
clientSecret: process.env.MEDIUM_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Email address is not returned by the Medium API.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: naver
|
||||||
|
title: Naver
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.naver.com/docs/login/overview/overview.md
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.naver.com/docs/login/api/api.md
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Naver Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Naver Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/naver.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import NaverProvider from "next-auth/providers/naver";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
NaverProvider({
|
||||||
|
clientId: process.env.NAVER_CLIENT_ID,
|
||||||
|
clientSecret: process.env.NAVER_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: netlify
|
||||||
|
title: Netlify
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://www.netlify.com/blog/2016/10/10/integrating-with-netlify-oauth2/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://github.com/netlify/netlify-oauth-example
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Netlify Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Netlify Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/netlify.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import NetlifyProvider from "next-auth/providers/netlify";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
NetlifyProvider({
|
||||||
|
clientId: process.env.NETLIFY_CLIENT_ID,
|
||||||
|
clientSecret: process.env.NETLIFY_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
id: okta
|
||||||
|
title: Okta
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.okta.com/docs/reference/api/oidc
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Okta Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Okta Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/okta.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import OktaProvider from "next-auth/providers/okta";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
OktaProvider({
|
||||||
|
clientId: process.env.OKTA_CLIENT_ID,
|
||||||
|
clientSecret: process.env.OKTA_CLIENT_SECRET,
|
||||||
|
issuer: process.env.OKTA_ISSUER
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
id: onelogin
|
||||||
|
title: OneLogin
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.onelogin.com/openid-connect
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.onelogin.com/openid-connect/connect-to-onelogin
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **OneLogin Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [OneLogin Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/onelogin.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import OneLoginProvider from "next-auth/providers/onelogin";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
OneLoginProvider({
|
||||||
|
clientId: process.env.ONELOGIN_CLIENT_ID,
|
||||||
|
clientSecret: process.env.ONELOGIN_CLIENT_SECRET,
|
||||||
|
issuer: process.env.ONELOGIN_ISSUER
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
id: osso
|
||||||
|
title: Osso
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Osso is an open source service that handles SAML authentication against Identity Providers, normalizes profiles, and makes those profiles available to you in an OAuth 2.0 code grant flow.
|
||||||
|
|
||||||
|
If you don't yet have an Osso instance, you can use [Osso's Demo App](https://demo.ossoapp.com) for your testing purposes. For documentation on deploying an Osso instance, see https://ossoapp.com/docs/deploy/overview/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
You can configure your OAuth Clients on your Osso Admin UI, i.e. https://demo.ossoapp.com/admin/config - you'll need to get a Client ID and Secret and allow-list your redirect URIs.
|
||||||
|
|
||||||
|
[SAML SSO differs a bit from OAuth](https://ossoapp.com/blog/saml-vs-oauth) - for every tenant who wants to sign in to your application using SAML, you and your customer need to perform a multi-step configuration in Osso's Admin UI and the admin dashboard of the tenant's Identity Provider. Osso provides documentation for providers like Okta and OneLogin, cloud-based IDPs who also offer a developer account that's useful for testing. Osso also provides a [Mock IDP](https://idp.ossoapp.com) that you can use for testing without needing to sign up for an Identity Provider service.
|
||||||
|
|
||||||
|
See Osso's complete configuration and testing documentation at https://ossoapp.com/docs/configure/overview
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Osso Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Osso Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/osso.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
A full example application is available at https://github.com/enterprise-oss/osso-next-auth-example and https://nextjs-demo.ossoapp.com
|
||||||
|
|
||||||
|
```js
|
||||||
|
import OssoProvider from "next-auth/providers/osso";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
OssoProvider({
|
||||||
|
clientId: process.env.OSSO_CLIENT_ID,
|
||||||
|
clientSecret: process.env.OSSO_CLIENT_SECRET,
|
||||||
|
issuer: process.env.OSSO_ISSUER
|
||||||
|
})
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
`issuer` should be the fully qualified domain – e.g. `demo.ossoapp.com`
|
||||||
|
:::
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: osu
|
||||||
|
title: osu!
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://osu.ppy.sh/docs/index.html#authentication
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://osu.ppy.sh/home/account/edit#new-oauth-application
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **osu! Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [osu! Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/osu.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
osu! does **not** provide a user email!
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import OsuProvider from "next-auth/providers/osu";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
OsuProvider({
|
||||||
|
clientId: process.env.OSU_CLIENT_ID,
|
||||||
|
clientSecret: process.env.OSU_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
id: patreon
|
||||||
|
title: Patreon
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.patreon.com/#apiv2-oauth
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Create a API v2 client on [Patreon Platform](https://www.patreon.com/portal/registration/register-clients)
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Patreon Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Patreon Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/patreon.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import PatreonProvider from "next-auth/providers/patreon";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
PatreonProvider({
|
||||||
|
clientId: process.env.PATREON_ID,
|
||||||
|
clientSecret: process.env.PATREON_SECRET,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Make sure you use the scopes defined in [ApiV2](https://docs.patreon.com/#scopes)
|
||||||
|
:::
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: pinterest
|
||||||
|
title: Pinterest
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developers.pinterest.com/docs/getting-started/authentication/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developers.pinterest.com/apps/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Pinterest Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Pinterest Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/pinterest.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import PinterestProvider from "next-auth/providers/pinterest"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
PinterestProvider({
|
||||||
|
clientId: process.env.PINTEREST_ID,
|
||||||
|
clientSecret: process.env.PINTEREST_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
To use in production, make sure the app has standard API access and not trial access
|
||||||
|
:::
|
||||||
|
```
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
id: pipedrive
|
||||||
|
title: Pipedrive
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://pipedrive.readme.io/docs/marketplace-oauth-authorization
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Pipedrive Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Pipedrive Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/pipedrive.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import PipedriveProvider from "next-auth/providers/pipedrive";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
PipedriveProvider({
|
||||||
|
clientId: process.env.PIPEDRIVE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.PIPEDRIVE_CLIENT_SECRET,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
---
|
||||||
|
id: reddit
|
||||||
|
title: Reddit
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://www.reddit.com/dev/api/
|
||||||
|
|
||||||
|
## App Configuration
|
||||||
|
|
||||||
|
1. Visit https://www.reddit.com/prefs/apps/ and create a new web app
|
||||||
|
2. Provide a name for your web app
|
||||||
|
3. Provide a redirect uri ending with `/api/auth/callback/reddit`:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
4. All other fields are optional
|
||||||
|
5. Click the "create app" button
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Reddit Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Reddit Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/reddit.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import RedditProvider from "next-auth/providers/reddit";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
RedditProvider({
|
||||||
|
clientId: process.env.REDDIT_CLIENT_ID,
|
||||||
|
clientSecret: process.env.REDDIT_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Reddit requires authorization every time you go through their page.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Only allows one callback URL per Client ID / Client Secret.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
This Provider template only has a one hour access token to it and only has the "identity" scope. If you want to get a refresh token as well you must follow this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
providers: [
|
||||||
|
RedditProvider({
|
||||||
|
clientId: process.env.REDDIT_CLIENT_ID,
|
||||||
|
clientSecret: process.env.REDDIT_CLIENT_SECRET,
|
||||||
|
authorization: {
|
||||||
|
params: {
|
||||||
|
duration: "permanent",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
id: salesforce
|
||||||
|
title: Salesforce
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://help.salesforce.com/articleView?id=remoteaccess_authenticate.htm&type=5
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Salesforce Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Salesforce Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/salesforce.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import SalesforceProvider from "next-auth/providers/salesforce";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
SalesforceProvider({
|
||||||
|
clientId: process.env.SALESFORCE_CLIENT_ID,
|
||||||
|
clientSecret: process.env.SALESFORCE_CLIENT_SECRET,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
id: slack
|
||||||
|
title: Slack
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://api.slack.com/authentication
|
||||||
|
https://api.slack.com/docs/sign-in-with-slack
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://api.slack.com/apps
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Slack requires that the redirect URL of your app uses `https`, even for local development. An easy workaround for this is using a service like [`ngrok`](https://ngrok.com) that creates a secure tunnel to your app, using `https`. Remember to set the url as `NEXTAUTH_URL` as well.
|
||||||
|
:::
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Slack Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Slack Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/slack.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import SlackProvider from "next-auth/providers/slack";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
SlackProvider({
|
||||||
|
clientId: process.env.SLACK_CLIENT_ID,
|
||||||
|
clientSecret: process.env.SLACK_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: spotify
|
||||||
|
title: Spotify
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.spotify.com/documentation/general/guides/authorization-guide
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.spotify.com/dashboard/applications
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Spotify Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Spotify Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/spotify.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import SpotifyProvider from "next-auth/providers/spotify";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
SpotifyProvider({
|
||||||
|
clientId: process.env.SPOTIFY_CLIENT_ID,
|
||||||
|
clientSecret: process.env.SPOTIFY_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
id: strava
|
||||||
|
title: Strava
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
http://developers.strava.com/docs/reference/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Strava Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Strava Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/strava.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case. Ensure the redirect_uri configuration fits your needs accordingly.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import StravaProvider from "next-auth/providers/strava";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
StravaProvider({
|
||||||
|
clientId: process.env.STRAVA_CLIENT_ID,
|
||||||
|
clientSecret: process.env.STRAVA_CLIENT_SECRET,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
id: todoist
|
||||||
|
title: Todoist
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.todoist.com/guides/#oauth
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.todoist.com/appconsole.html
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Todoist Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Todoist Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/todoist.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import TodoistProvider from "next-auth/providers/todoist";
|
||||||
|
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
TodoistProvider({
|
||||||
|
clientId: process.env.TODOIST_ID,
|
||||||
|
clientSecret: process.env.TODOIST_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
id: trakt
|
||||||
|
title: Trakt
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://trakt.docs.apiary.io/#reference/authentication-oauth
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
If you're using the api in production by calling [api.trakt.tv](https://api.trakt.tv). Follow the example below. If you wish to develop on Trakt's sandbox environment by calling [api-staging.trakt.tv](https://api-staging.trakt.tv). Use the default options with the changed the URLs.
|
||||||
|
|
||||||
|
Start by creating an OAuth app on Trakt for [production](https://trakt.tv/oauth/applications/new) or [development](https://staging.trakt.tv/oauth/applications/new). Then set the Client ID and Client Secret as `TRAKT_ID` and `TRAKT_SECRET` in `.env`.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Trakt Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Trakt Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/trakt.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
providers: [
|
||||||
|
TraktProvider({
|
||||||
|
clientId: process.env.TRAKT_ID,
|
||||||
|
clientSecret: process.env.TRAKT_SECRET,
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Trakt does not allow hotlinking images. Even the authenticated user's profie picture.
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Trakt does not supply the authenticated user's email.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
id: twitch
|
||||||
|
title: Twitch
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://dev.twitch.tv/docs/authentication
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://dev.twitch.tv/console/apps
|
||||||
|
|
||||||
|
Add the following redirect URL into the console `http://<your-next-app-url>/api/auth/callback/twitch`
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Twitch Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Twitch Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/twitch.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import TwitchProvider from "next-auth/providers/twitch";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
TwitchProvider({
|
||||||
|
clientId: process.env.TWITCH_CLIENT_ID,
|
||||||
|
clientSecret: process.env.TWITCH_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
id: twitter
|
||||||
|
title: Twitter
|
||||||
|
---
|
||||||
|
|
||||||
|
Twitter is currently the only built-in provider using the OAuth 1.0 spec. This means that you won't receive an `access_token` or `refresh_token`, but an `oauth_token` and `oauth_token_secret` respectively. Remember to add these to your database schema, in case if you are using an [Adapter](https://authjs.dev/getting-started/database).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.twitter.com
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.twitter.com/en/apps
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Twitter Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Twitter Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/twitter.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import TwitterProvider from "next-auth/providers/twitter";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
TwitterProvider({
|
||||||
|
clientId: process.env.TWITTER_CLIENT_ID,
|
||||||
|
clientSecret: process.env.TWITTER_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
You must enable the _"Request email address from users"_ option in your app permissions if you want to obtain the users email address.
|
||||||
|
:::
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## OAuth 2.0
|
||||||
|
|
||||||
|
Twitter supports OAuth 2, which is currently opt-in. To enable it, simply add `version: "2.0"` to your Provider configuration:
|
||||||
|
|
||||||
|
```js
|
||||||
|
TwitterProvider({
|
||||||
|
clientId: process.env.TWITTER_ID,
|
||||||
|
clientSecret: process.env.TWITTER_SECRET,
|
||||||
|
version: "2.0", // opt-in to Twitter OAuth 2.0
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep in mind that although this change is easy, it changes how and with which of [Twitter APIs](https://developer.twitter.com/en/docs/api-reference-index) you can interact with. Read the official [Twitter OAuth 2 documentation](https://developer.twitter.com/en/docs/authentication/oauth-2-0) for more details.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Email is currently not supported by Twitter OAuth 2.0.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
id: united-effects
|
||||||
|
title: United Effects
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://docs.unitedeffects.com/integrations/nextauthjs
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://core.unitedeffects.com
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **United Effects Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [United Effects Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/united-effects.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import UnitedEffectsProvider from "next-auth/providers/united-effects";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
UnitedEffectsProvider({
|
||||||
|
clientId: process.env.UNITED_EFFECTS_CLIENT_ID,
|
||||||
|
clientSecret: process.env.UNITED_EFFECTS_CLIENT_SECRET,
|
||||||
|
issuer: process.env.UNITED_EFFECTS_ISSUER
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
`issuer` should be the fully qualified URL including your Auth Group ID – e.g. `https://auth.unitedeffects.com/YQpbQV5dbW-224dCovz-3`
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
The United Effects API does not return the user name or image by design, so this provider will return null for both. United Effects prioritizes user personal information security above all and has built a secured profile access request system separate from the provider API.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
---
|
||||||
|
id: vk
|
||||||
|
title: VK
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://vk.com/dev/first_guide
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://vk.com/apps?act=manage
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **VK Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [VK Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/vk.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import VkProvider from "next-auth/providers/vk";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
VkProvider({
|
||||||
|
clientId: process.env.VK_CLIENT_ID,
|
||||||
|
clientSecret: process.env.VK_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
By default the provider uses `5.131` version of the API. See https://vk.com/dev/versions for more info.
|
||||||
|
:::
|
||||||
|
|
||||||
|
If you want to use a different version, you can pass it to provider's options object:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// pages/api/auth/[...nextauth].js
|
||||||
|
|
||||||
|
const apiVersion = "5.131"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
VkProvider({
|
||||||
|
accessTokenUrl: `https://oauth.vk.com/access_token?v=${apiVersion}`,
|
||||||
|
requestTokenUrl: `https://oauth.vk.com/access_token?v=${apiVersion}`,
|
||||||
|
authorizationUrl:
|
||||||
|
`https://oauth.vk.com/authorize?response_type=code&v=${apiVersion}`,
|
||||||
|
profileUrl: `https://api.vk.com/method/users.get?fields=photo_100&v=${apiVersion}`,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
id: wikimedia
|
||||||
|
title: Wikimedia
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://www.mediawiki.org/wiki/Extension:OAuth
|
||||||
|
|
||||||
|
This provider also supports all Wikimedia projects:
|
||||||
|
|
||||||
|
- Wikipedia
|
||||||
|
- Wikidata
|
||||||
|
- Wikibooks
|
||||||
|
- Wiktionary
|
||||||
|
- etc..
|
||||||
|
|
||||||
|
Please be aware that Wikimedia accounts do not have to have an associated email address. So you may want to add check if the user has an email address before allowing them to login.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
1. Go to and accept the Consumer Registration doc: https://meta.wikimedia.org/wiki/Special:OAuthConsumerRegistration
|
||||||
|
2. Request a new OAuth 2.0 consumer to get the `clientId` and `clientSecret`: https://meta.wikimedia.org/wiki/Special:OAuthConsumerRegistration/propose/oauth2
|
||||||
|
2a. Add the following redirect URL into the console `http://<your-next-app-url>/api/auth/callback/wikimedia`
|
||||||
|
2b. Do not check the box next to `This consumer is only for [your username]`
|
||||||
|
2c. Unless you explicitly need a larger scope, feel free to select the radio button labelled `User identity verification only - no ability to read pages or act on the users behalf.`
|
||||||
|
|
||||||
|
After registration, you can initally test your application only with your own Wikimedia account. You may have to wait several days for the application to be approved for it to be used by everyone.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Wikimedia Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Wikimedia Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/wikimedia.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import WikimediaProvider from "next-auth/providers/wikimedia";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
WikimediaProvider({
|
||||||
|
clientId: process.env.WIKIMEDIA_CLIENT_ID,
|
||||||
|
clientSecret: process.env.WIKIMEDIA_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: wordpress
|
||||||
|
title: WordPress.com
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://developer.wordpress.com/docs/oauth2/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://developer.wordpress.com/apps/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Wordpress Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Wordpress Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/wordpress.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import WordpressProvider from "next-auth/providers/wordpress";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
WordpressProvider({
|
||||||
|
clientId: process.env.WORDPRESS_CLIENT_ID,
|
||||||
|
clientSecret: process.env.WORDPRESS_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Register your application to obtain Client ID and Client Secret at https://developer.wordpress.com/apps/ Select Type as Web and set Redirect URL to `http://example.com/api/auth/callback/wordpress` where example.com is your site domain.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
id: workos
|
||||||
|
title: WorkOS
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://workos.com/docs/sso/guide
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://dashboard.workos.com
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **WorkOS Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [WorkOS Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/workos.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import WorkOSProvider from "next-auth/providers/workos";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
WorkOSProvider({
|
||||||
|
clientId: process.env.WORKOS_CLIENT_ID,
|
||||||
|
clientSecret: process.env.WORKOS_API_KEY,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
WorkOS is not an identity provider itself, but, rather, a bridge to multiple single sign-on (SSO) providers. As a result, we need to make some additional changes to authenticate users using WorkOS.
|
||||||
|
|
||||||
|
In order to sign a user in using WorkOS, we need to specify which WorkOS Connection to use. You should use the `organization` or `connection` `authorizationParams` to specify which connection to use:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { signIn } from "next-auth/react"
|
||||||
|
|
||||||
|
|
||||||
|
const organization = 'ORGANIZATION_ID';
|
||||||
|
signIn(provider.id, undefined, {
|
||||||
|
organization,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
This can be done using a custom login page. See [Create a Next.js application with WorkOS SSO and NextAuth.js](https://workos.com/docs/integrations/next-auth/6-creating-a-custom-login-page).
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: yandex
|
||||||
|
title: Yandex
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://tech.yandex.com/oauth/doc/dg/concepts/about-docpage/
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://oauth.yandex.com/client/new
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Yandex Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Yandex Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/yandex.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import YandexProvider from "next-auth/providers/yandex";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
YandexProvider({
|
||||||
|
clientId: process.env.YANDEX_CLIENT_ID,
|
||||||
|
clientSecret: process.env.YANDEX_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
id: zitadel
|
||||||
|
title: Zitadel
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://zitadel.com/docs/apis/openidoauth/endpoints
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://zitadel.com/docs/guides/integrate/oauth-recommended-flows
|
||||||
|
|
||||||
|
The Redirect URIs used when creating the credentials must include your full domain and end in the callback path. For example:
|
||||||
|
|
||||||
|
- For production: `https://{YOUR_DOMAIN}/api/auth/callback/zitadel`
|
||||||
|
- For development: `http://localhost:3000/api/auth/callback/zitadel`
|
||||||
|
|
||||||
|
Make sure to enable **dev mode** in ZITADEL console to allow redirects for local development.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **ZITADEL Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [ZITADEL Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/zitadel.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import ZitadelProvider from "next-auth/providers/zitadel";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
ZitadelProvider({
|
||||||
|
issuer: process.env.ZITADEL_ISSUER,
|
||||||
|
clientId: process.env.ZITADEL_CLIENT_ID,
|
||||||
|
clientSecret: process.env.ZITADEL_CLIENT_SECRET,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need access to ZITADEL APIs or need additional information, make sure to add the corresponding scopes.
|
||||||
|
|
||||||
|
To get the full list of supported claims take a look [here](https://zitadel.com/docs/apis/openidoauth/endpoints).
|
||||||
|
|
||||||
|
```js
|
||||||
|
const options = {
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
ZitadelProvider({
|
||||||
|
clientId: process.env.ZITADEL_CLIENT_ID,
|
||||||
|
authorization: {
|
||||||
|
params: {
|
||||||
|
scope: `openid email profile urn:zitadel:iam:org:project:id:${process.env.ZITADEL_PROJECT_ID}:aud`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
ZITADEL also returns a `email_verified` boolean property in the profile.
|
||||||
|
|
||||||
|
You can use this property to restrict access to people with verified accounts.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const options = {
|
||||||
|
...
|
||||||
|
callbacks: {
|
||||||
|
async signIn({ account, profile }) {
|
||||||
|
if (account.provider === "zitadel") {
|
||||||
|
return profile.email_verified;
|
||||||
|
}
|
||||||
|
return true; // Do different verification for other providers that don't have `email_verified`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
id: zoho
|
||||||
|
title: Zoho
|
||||||
|
---
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Zoho returns a field on `Account` called `api_domain` which is a string. See their [docs](https://www.zoho.com/accounts/protocol/oauth/web-apps/access-token.html). Remember to add this field to your database schema, in case if you are using an [Adapter](https://next-auth.js.org/adapters).
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://www.zoho.com/accounts/protocol/oauth/web-server-applications.html
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://api-console.zoho.com/
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Zoho Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Zoho Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/zoho.js)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import ZohoProvider from "next-auth/providers/zoho";
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
ZohoProvider({
|
||||||
|
clientId: process.env.ZOHO_CLIENT_ID,
|
||||||
|
clientSecret: process.env.ZOHO_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
]
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
id: zoom
|
||||||
|
title: Zoom
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
https://marketplace.zoom.us/docs/guides/auth/oauth
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
https://marketplace.zoom.us
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
The **Zoom Provider** comes with a set of default options:
|
||||||
|
|
||||||
|
- [Zoom Provider options](https://github.com/nextauthjs/next-auth/blob/v4/packages/next-auth/src/providers/zoom.ts)
|
||||||
|
|
||||||
|
You can override any of the options to suit your own use case.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
import ZoomProvider from "next-auth/providers/zoom"
|
||||||
|
...
|
||||||
|
providers: [
|
||||||
|
ZoomProvider({
|
||||||
|
clientId: process.env.ZOOM_CLIENT_ID,
|
||||||
|
clientSecret: process.env.ZOOM_CLIENT_SECRET
|
||||||
|
})
|
||||||
|
}
|
||||||
|
...
|
||||||
|
```
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
id: security
|
||||||
|
title: Security
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
NextAuth.js practices responsible disclosure.
|
||||||
|
|
||||||
|
We request that you contact us directly to report serious issues that might impact the security of sites using NextAuth.js.
|
||||||
|
|
||||||
|
If you contact us regarding a serious issue:
|
||||||
|
|
||||||
|
- We will endeavor to get back to you within 72 hours.
|
||||||
|
- We will aim to publish a fix within 30 days.
|
||||||
|
- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
|
||||||
|
- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
|
||||||
|
|
||||||
|
The best way to report an issue is by contacting us via email at info@balazsorban.com, hi@thvu.dev and yo@ndo.dev or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||||
|
|
||||||
|
:::note
|
||||||
|
For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these these publically as bug reports or feature requests or to raise a question to open a discussion around them.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Security updates are only released for the current version.
|
||||||
|
|
||||||
|
Old releases are not maintained and do not receive updates.
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
id: tutorials
|
||||||
|
title: Tutorials and Explainers
|
||||||
|
---
|
||||||
|
|
||||||
|
> These tutorials are contributed by the community. Unless otherwise indicated, tutorials are hosted on this site. External and video based tutorials are denoted with the appropriate icons.
|
||||||
|
>
|
||||||
|
> **New submissions and edits are welcome!**
|
||||||
|
|
||||||
|
## Basics
|
||||||
|
|
||||||
|
#### [Introduction to NextAuth.js](https://www.youtube.com/watch?v=npZsJxWntJM) <svg role="img" viewBox="0 0 24 24" height="24" width="24" style={{ marginLeft: '5px', marginBottom:'-6px'}} xmlns="http://www.w3.org/2000/svg"><title>YouTube</title><path fill="#ff0000" d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
|
||||||
|
|
||||||
|
- This is an introductory video to NextAuth.js for beginners. In this video, it is explained how to set up authentication in a few easy steps and add different configurations to make it more robust and secure.
|
||||||
|
|
||||||
|
#### [Authentication patterns for Next.js](https://nextjs.org/docs/app/building-your-application/authentication) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- Next.js supports multiple patterns for authentication, each designed for different use cases. This guide will allow you to choose your adventure based on your constraints. By Lee Robinson.
|
||||||
|
|
||||||
|
#### [Adding Authentication to an existing Next.js Application in no time!](https://dev.to/ndom91/adding-authentication-to-an-existing-serverless-next-js-app-in-no-time-with-nextauth-js-192h) <svg style={{ marginLeft: '5px', marginBottom:'-6px'}} width="30" height="25" viewBox="0 0 50 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="50" height="40" rx="3" style={{ fill: '#000' }}></rect><path d="M19.099 23.508c0 1.31-.423 2.388-1.27 3.234-.838.839-1.942 1.258-3.312 1.258h-4.403V12.277h4.492c1.31 0 2.385.423 3.224 1.27.846.838 1.269 1.912 1.269 3.223v6.738zm-2.808 0V16.77c0-.562-.187-.981-.562-1.258-.374-.285-.748-.427-1.122-.427h-1.685v10.107h1.684c.375 0 .75-.138 1.123-.415.375-.285.562-.708.562-1.27zM28.185 28h-5.896c-.562 0-1.03-.187-1.404-.561-.375-.375-.562-.843-.562-1.404V14.243c0-.562.187-1.03.562-1.404.374-.375.842-.562 1.404-.562h5.896v2.808H23.13v3.65h3.088v2.808h-3.088v3.65h5.054V28zm7.12 0c-.936 0-1.684-.655-2.246-1.965l-3.65-13.758h3.089l2.807 10.804 2.808-10.804H41.2l-3.65 13.758C36.99 27.345 36.241 28 35.305 28z" style={{ fill: '#fff' }}></path></svg>
|
||||||
|
|
||||||
|
- This tutorial walks one through adding NextAuth.js to an existing project. Including setting up the OAuth client id and secret, adding the API routes for authentication, protecting pages and API routes behind that authentication, etc.
|
||||||
|
|
||||||
|
#### [How to Authenticate Next.js Apps with Twitter & NextAuth.js](https://spacejelly.dev/posts/how-to-authenticate-next-js-apps-with-twitter-nextauth-js/) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- Learn how to add Twitter authentication and login to a Next.js app both clientside and serverside with NextAuth.js.
|
||||||
|
|
||||||
|
#### [NextJS Authentication Crash Course with NextAuth.js](https://youtu.be/o_wZIVmWteQ) <svg role="img" viewBox="0 0 24 24" height="24" width="24" style={{ marginLeft: '5px', marginBottom:'-6px'}} xmlns="http://www.w3.org/2000/svg"><title>YouTube</title><path fill="#ff0000" d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
|
||||||
|
|
||||||
|
- This tutorial dives into the ins and outs of NextAuth, including using the Email, Github, Twitter and Auth0 providers in under an hour.
|
||||||
|
|
||||||
|
#### [Create your own NextAuth.js Login Pages](https://youtu.be/kB6YNYZ63fw) <svg role="img" viewBox="0 0 24 24" height="24" width="24" style={{ marginLeft: '5px', marginBottom:'-6px'}} xmlns="http://www.w3.org/2000/svg"><title>YouTube</title><path fill="#ff0000" d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
|
||||||
|
|
||||||
|
- This tutorial shows you how to jump in and create your own custom login pages versus using the ones provided by NextAuth.js
|
||||||
|
|
||||||
|
#### [Passwordless Authentication with next-auth](https://www.youtube.com/watch?v=GPBD3acOx_M) <svg role="img" viewBox="0 0 24 24" height="24" width="24" style={{ marginLeft: '5px', marginBottom:'-6px'}} xmlns="http://www.w3.org/2000/svg"><title>YouTube</title><path fill="#ff0000" d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
|
||||||
|
|
||||||
|
- A video tutorial by Xiaoru Li from Prisma.
|
||||||
|
|
||||||
|
#### [How to authenticate Next.js Apps with Sign-In With Ethereum (SIWE) & NextAuth.js](https://docs.login.xyz/integrations/nextauth.js) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- Learn how to use Sign-In With Ethereum to authenticate your users with their existing Ethereum wallets - identifiers they personally control.
|
||||||
|
- Example application: [spruceid/siwe-next-auth-example](https://github.com/spruceid/siwe-next-auth-example)
|
||||||
|
|
||||||
|
#### [Next.js Authentication with Okta and NextAuth.js 4.0](https://thetombomb.com/posts/nextjs-nextauth-okta) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- Learn how to perform authentication with an OIDC Application in Okta and NextAuth.js.
|
||||||
|
|
||||||
|
## Fullstack
|
||||||
|
|
||||||
|
#### [Magic Link Authentication in Next.js with NextAuth and Fauna](https://alterclass.io/tutorials/magic-link-authentication-in-nextjs-with-nextauth-and-fauna) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
Learn how to implement passwordless/magic link authentication with database storage in your Next.js projects using NextAuth and Fauna DB.
|
||||||
|
|
||||||
|
> The final version of the project's code can be found on [Github](https://github.com/AlterClassIO/magic-next-auth). You can use it as a starting point for any Next.js app that requires passwordless authentication.
|
||||||
|
|
||||||
|
This tutorial covers:
|
||||||
|
|
||||||
|
- Configuring Next.js, NextAuth.js, and Fauna to work together seamlessly
|
||||||
|
- Using Next.js dynamic API routes to handle authentication requests
|
||||||
|
- Using Fauna and the Fauna Adapter for `next-auth` to persist users, email sign in tokens, and sessions
|
||||||
|
- Creating custom login and confirmation pages with React + Tailwind CSS
|
||||||
|
- Customizing the sign-in email and sending a welcome email to new users
|
||||||
|
|
||||||
|
#### [Passwordless Authentication with Next.js, Prisma, and next-auth](https://dev.to/prisma/passwordless-authentication-with-next-js-prisma-and-next-auth-5g8g) <svg style={{ marginLeft: '5px', marginBottom:'-6px'}} width="30" height="25" viewBox="0 0 50 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="50" height="40" rx="3" style={{ fill: '#000' }}></rect><path d="M19.099 23.508c0 1.31-.423 2.388-1.27 3.234-.838.839-1.942 1.258-3.312 1.258h-4.403V12.277h4.492c1.31 0 2.385.423 3.224 1.27.846.838 1.269 1.912 1.269 3.223v6.738zm-2.808 0V16.77c0-.562-.187-.981-.562-1.258-.374-.285-.748-.427-1.122-.427h-1.685v10.107h1.684c.375 0 .75-.138 1.123-.415.375-.285.562-.708.562-1.27zM28.185 28h-5.896c-.562 0-1.03-.187-1.404-.561-.375-.375-.562-.843-.562-1.404V14.243c0-.562.187-1.03.562-1.404.374-.375.842-.562 1.404-.562h5.896v2.808H23.13v3.65h3.088v2.808h-3.088v3.65h5.054V28zm7.12 0c-.936 0-1.684-.655-2.246-1.965l-3.65-13.758h3.089l2.807 10.804 2.808-10.804H41.2l-3.65 13.758C36.99 27.345 36.241 28 35.305 28z" style={{ fill: '#fff' }}></path></svg>
|
||||||
|
|
||||||
|
- In this post, you'll learn how to add passwordless authentication to your Next.js app using Prisma and next-auth. By the end of this tutorial, your users will be able to log in to your app with either their GitHub account or a Slack-styled magic link sent right to their Email inbox. By Xiaoru Li.
|
||||||
|
|
||||||
|
## Advanced
|
||||||
|
|
||||||
|
#### [Add auth support to a Next.js app with a custom backend](https://arunoda.me/blog/add-auth-support-to-a-next-js-app-with-a-custom-backend) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- A tutorial by Arunoda Susirpiala.
|
||||||
|
|
||||||
|
#### [How to Configure Azure AD B2C Authentication with Next.js](https://benjaminwfox.com/blog/tech/how-to-configure-azure-b2c-with-nextjs) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- Configuring authentication with Azure B2C in Next.js is not a particularly straight forward process. We'll look at how to facilitate this using the NextAuth.js library. By Ben Fox.
|
||||||
|
|
||||||
|
#### [Sign in with Apple in NextJS](https://thesiddd.com/blog/apple-auth) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- This tutorial walks step by step on how to get sign in with Apple working (both locally and on a deployed website) using NextAuth.js.
|
||||||
|
|
||||||
|
#### [Using NextAuth.js with Magic links](https://dev.to/narciero/using-nextauth-js-with-magic-links-df4) <svg style={{ marginLeft: '5px', marginBottom:'-6px'}} width="30" height="25" viewBox="0 0 50 40" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="50" height="40" rx="3" style={{ fill: '#000' }}></rect><path d="M19.099 23.508c0 1.31-.423 2.388-1.27 3.234-.838.839-1.942 1.258-3.312 1.258h-4.403V12.277h4.492c1.31 0 2.385.423 3.224 1.27.846.838 1.269 1.912 1.269 3.223v6.738zm-2.808 0V16.77c0-.562-.187-.981-.562-1.258-.374-.285-.748-.427-1.122-.427h-1.685v10.107h1.684c.375 0 .75-.138 1.123-.415.375-.285.562-.708.562-1.27zM28.185 28h-5.896c-.562 0-1.03-.187-1.404-.561-.375-.375-.562-.843-.562-1.404V14.243c0-.562.187-1.03.562-1.404.374-.375.842-.562 1.404-.562h5.896v2.808H23.13v3.65h3.088v2.808h-3.088v3.65h5.054V28zm7.12 0c-.936 0-1.684-.655-2.246-1.965l-3.65-13.758h3.089l2.807 10.804 2.808-10.804H41.2l-3.65 13.758C36.99 27.345 36.241 28 35.305 28z" style={{ fill: '#fff' }}></path></svg>
|
||||||
|
|
||||||
|
- Learn how to use [Magic.Link](https://magic.link) authentication with [NextAuth.js](https://next-auth.js.org) to enable passwordless authentication without a database.
|
||||||
|
|
||||||
|
## Database
|
||||||
|
|
||||||
|
#### [Create a NextAuth.js Custom Adapter with HarperDB & Next.js](https://spacejelly.dev/posts/how-to-create-a-nextauth-js-custom-adapter-with-harperdb-next-js/) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- Use a custom database in a Custom Adapter for persisted NextAuth.js sessions using HarperDB as an example.
|
||||||
|
- Video tutorial also available: <https://www.youtube.com/watch?v=pu7xBv7sZ8s>
|
||||||
|
|
||||||
|
#### [Using NextAuth.js with Prisma and PlanetScale serverless databases](https://github.com/planetscale/nextjs-planetscale-starter) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||||
|
|
||||||
|
- How to set up a PlanetScale database to fetch and store user / account data with the Prisma adapter.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
id: avoid-corporate-link-checking-email-provider
|
||||||
|
title: Allow Email Signups Behind Corporate Link Checker
|
||||||
|
---
|
||||||
|
|
||||||
|
If you use Office 365 or Outlook, or potentially other Email systems, you may notice your Email invitation Links not working.
|
||||||
|
|
||||||
|
This is because the invitation Email your User is receiving is being scanned by the Email provider. In the specific case of Outlook and their "SafeLink" feature, they send a HEAD request to each link in the Email. This request will trigger the NextAuth.js catch-all API Route with the users invitation token, in effect using it up.
|
||||||
|
|
||||||
|
Therefore, when the user wants to use it themselves, and clicks on the invitation link they will be greeted with an error message that the invitation is invalid.
|
||||||
|
|
||||||
|
## Workarounds
|
||||||
|
|
||||||
|
### Disable "SafeLink"
|
||||||
|
|
||||||
|
The first potential workaround is to simply disable this "SafeLink" feature for your organisation. Microsoft has more details on this [here](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-links?view=o365-worldwide#do-not-rewrite-the-following-urls-lists-in-safe-links-policies). Obviously this won't be an option for everyone as this is usually a part of corporate IT policy.
|
||||||
|
|
||||||
|
### Update NextAuth.js for 'HEAD' requests
|
||||||
|
|
||||||
|
The second option is to modify your `[...nextauth].js` catch-all API route a bit to gracefully handle these initial `HEAD` requests from the email service, without accidentally using up the invitation link.
|
||||||
|
|
||||||
|
This can be done by simply returning a `200` response on `HEAD` requests at the very top of the API route, before any other logic is executed.
|
||||||
|
|
||||||
|
For example
|
||||||
|
|
||||||
|
```jsx title="/pages/api/auth/[...nextauth].js"
|
||||||
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
|
||||||
|
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
|
||||||
|
if(req.method === "HEAD") {
|
||||||
|
return res.status(200).end()
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This should allow you to successfully use NextAuth.js's Email provider behind strict corporate IT settings.
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
--
|
||||||
|
id: corporate-proxy
|
||||||
|
title: Add support for HTTP Proxy
|
||||||
|
--
|
||||||
|
|
||||||
|
Using NextAuth.js behind a corporate proxy is not supported out of the box. This is due to the fact that the underlying library we use, [`openid-client`](https://npm.im/openid-client), uses the built-in Node.js `http` / `https` libraries, which do not support proxys by default. (See: [`http` docs](https://nodejs.org/dist/latest-v18.x/docs/api/http.html), [`https` docs](https://nodejs.org/dist/latest-v18.x/docs/api/https.html)).
|
||||||
|
|
||||||
|
Therefore, we'll need to an additional proxy agent to the http client, such as `https-proxy-agent`. `openid-client` allows the user to set an `agent` for requests ([Source](https://github.com/panva/node-openid-client/blob/main/docs/README.md#customizing-individual-http-requests).
|
||||||
|
|
||||||
|
Thanks to [raphaelpc](https://github.com/raphaelpc) for the below diff, which when applied to `v4.2.1`, adds this agent support to the `client.js` file.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git a/node_modules/next-auth/core/lib/oauth/client.js b/node_modules/next-auth/core/lib/oauth/client.js
|
||||||
|
index 77161bd..1082fba 100644
|
||||||
|
--- a/node_modules/next-auth/core/lib/oauth/client.js
|
||||||
|
+++ b/node_modules/next-auth/core/lib/oauth/client.js
|
||||||
|
@@ -7,11 +7,19 @@ exports.openidClient = openidClient;
|
||||||
|
|
||||||
|
var _openidClient = require("openid-client");
|
||||||
|
|
||||||
|
+var HttpsProxyAgent = require("https-proxy-agent");
|
||||||
|
+
|
||||||
|
async function openidClient(options) {
|
||||||
|
const provider = options.provider;
|
||||||
|
- if (provider.httpOptions) _openidClient.custom.setHttpOptionsDefaults(provider.httpOptions);
|
||||||
|
- let issuer;
|
||||||
|
+ let httpOptions = {};
|
||||||
|
+ if (provider.httpOptions) httpOptions = { ...provider.httpOptions };
|
||||||
|
+ if (process.env.http_proxy) {
|
||||||
|
+ let agent = new HttpsProxyAgent(process.env.http_proxy);
|
||||||
|
+ httpOptions.agent = agent;
|
||||||
|
+ }
|
||||||
|
+ _openidClient.custom.setHttpOptionsDefaults(httpOptions);
|
||||||
|
|
||||||
|
+ let issuer;
|
||||||
|
if (provider.wellKnown) {
|
||||||
|
issuer = await _openidClient.Issuer.discover(provider.wellKnown);
|
||||||
|
} else {
|
||||||
|
```
|
||||||
|
|
||||||
|
> For more details, see [this issue](https://github.com/nextauthjs/next-auth/issues/2509#issuecomment-1035410802)
|
||||||
|
|
||||||
|
After applying this patch, we can add the the proxy connecting string via the `http_proxy` environment variable.
|
||||||
|
|
||||||
|
### Provider
|
||||||
|
|
||||||
|
If you're having trouble with your provider when using the `https-proxy-agent`, you may be using a provider which requires an extra request to, for example, fetch the users profile picture. In cases like these, you'll have to add the proxy workaround to your provider config as well. Below is an example of how to do that with the `AzureAD` provider.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
diff --git a/node_modules/next-auth/providers/azure-ad.js b/node_modules/next-auth/providers/azure-ad.js
|
||||||
|
index 73d96d3..536cd81 100644
|
||||||
|
--- a/node_modules/next-auth/providers/azure-ad.js
|
||||||
|
+++ b/node_modules/next-auth/providers/azure-ad.js
|
||||||
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
||||||
|
});
|
||||||
|
exports.default = AzureAD;
|
||||||
|
|
||||||
|
+const HttpsProxyAgent = require('https-proxy-agent');
|
||||||
|
+
|
||||||
|
function AzureAD(options) {
|
||||||
|
var _options$tenantId, _options$profilePhoto;
|
||||||
|
|
||||||
|
@@ -22,11 +24,15 @@ function AzureAD(options) {
|
||||||
|
},
|
||||||
|
|
||||||
|
async profile(profile, tokens) {
|
||||||
|
- const profilePicture = await fetch(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, {
|
||||||
|
+ let fetchOptions = {
|
||||||
|
headers: {
|
||||||
|
- Authorization: `Bearer ${tokens.access_token}`
|
||||||
|
- }
|
||||||
|
- });
|
||||||
|
+ Authorization: `Bearer ${tokens.access_token}`,
|
||||||
|
+ },
|
||||||
|
+ };
|
||||||
|
+ if (process.env.http_proxy) {
|
||||||
|
+ fetchOptions.agent = new HttpsProxyAgent(process.env.http_proxy);
|
||||||
|
+ }
|
||||||
|
+ const profilePicture = await fetch(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, fetchOptions);
|
||||||
|
|
||||||
|
if (profilePicture.ok) {
|
||||||
|
const pictureBuffer = await profilePicture.arrayBuffer();
|
||||||
|
```
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
id: creating-a-database-adapter
|
||||||
|
title: Create an adapter
|
||||||
|
---
|
||||||
|
|
||||||
|
Using a custom adapter you can connect to any database back-end or even several different databases. Official adapters created and maintained by our community can be found in the [adapters](https://github.com/nextauthjs/next-auth/tree/main/packages) packages. Feel free to add a custom adapter from your project to the repository, or even become a maintainer of a certain adapter. Custom adapters can still be created and used in a project without being added to the repository.
|
||||||
|
|
||||||
|
## How to create an adapter
|
||||||
|
|
||||||
|
For more information about creating an adapter, see [this guide](https://authjs.dev/guides/creating-a-database-adapter).
|
||||||
|
|
||||||
|
_See the code below for practical example._
|
||||||
|
|
||||||
|
### Example code
|
||||||
|
|
||||||
|
```ts
|
||||||
|
/** @return { import("next-auth/adapters").Adapter } */
|
||||||
|
export default function MyAdapter(client, options = {}) {
|
||||||
|
return {
|
||||||
|
async createUser(user) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async getUser(id) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async getUserByEmail(email) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async getUserByAccount({ providerAccountId, provider }) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async updateUser(user) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async deleteUser(userId) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async linkAccount(account) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async unlinkAccount({ providerAccountId, provider }) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async createSession({ sessionToken, userId, expires }) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async getSessionAndUser(sessionToken) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async updateSession({ sessionToken }) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async deleteSession(sessionToken) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async createVerificationToken({ identifier, expires, token }) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
async useVerificationToken({ identifier, token }) {
|
||||||
|
return
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required methods
|
||||||
|
|
||||||
|
These methods are required for all sign in flows:
|
||||||
|
|
||||||
|
- `createUser`
|
||||||
|
- `getUser`
|
||||||
|
- `getUserByEmail`
|
||||||
|
- `getUserByAccount`
|
||||||
|
- `linkAccount`
|
||||||
|
- `createSession`
|
||||||
|
- `getSessionAndUser`
|
||||||
|
- `updateSession`
|
||||||
|
- `deleteSession`
|
||||||
|
- `updateUser`
|
||||||
|
|
||||||
|
These methods are required to support email / passwordless sign in:
|
||||||
|
|
||||||
|
- `createVerificationToken`
|
||||||
|
- `useVerificationToken`
|
||||||
|
|
||||||
|
### Unimplemented methods
|
||||||
|
|
||||||
|
These methods will be required in a future release, but are not yet invoked:
|
||||||
|
|
||||||
|
- `deleteUser`
|
||||||
|
- `unlinkAccount`
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
---
|
||||||
|
id: ldap-auth-example
|
||||||
|
title: LDAP Authentication
|
||||||
|
---
|
||||||
|
|
||||||
|
NextAuth.js provides the ability to setup a [custom Credential provider](/configuration/providers/credentials) which we can take advantage of to authenticate users against an existing LDAP server.
|
||||||
|
|
||||||
|
You will need an additional dependency, `ldapjs`, which you can install by running
|
||||||
|
|
||||||
|
```bash npm2yarn2pnpm
|
||||||
|
npm install ldapjs
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you must setup the `CredentialsProvider()` provider key like so:
|
||||||
|
|
||||||
|
```js title="[...nextauth].js"
|
||||||
|
const ldap = require("ldapjs")
|
||||||
|
import NextAuth from "next-auth"
|
||||||
|
import CredentialsProvider from "next-auth/providers/credentials"
|
||||||
|
|
||||||
|
export default NextAuth({
|
||||||
|
providers: [
|
||||||
|
CredentialsProvider({
|
||||||
|
name: "LDAP",
|
||||||
|
credentials: {
|
||||||
|
username: { label: "DN", type: "text", placeholder: "" },
|
||||||
|
password: { label: "Password", type: "password" },
|
||||||
|
},
|
||||||
|
async authorize(credentials, req) {
|
||||||
|
// You might want to pull this call out so we're not making a new LDAP client on every login attemp
|
||||||
|
const client = ldap.createClient({
|
||||||
|
url: process.env.LDAP_URI,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Essentially promisify the LDAPJS client.bind function
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
client.bind(credentials.username, credentials.password, (error) => {
|
||||||
|
if (error) {
|
||||||
|
console.error("Failed")
|
||||||
|
reject()
|
||||||
|
} else {
|
||||||
|
console.log("Logged in")
|
||||||
|
resolve({
|
||||||
|
username: credentials.username,
|
||||||
|
password: credentials.password,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
callbacks: {
|
||||||
|
async jwt({ token, user }) {
|
||||||
|
const isSignIn = user ? true : false
|
||||||
|
if (isSignIn) {
|
||||||
|
token.username = user.username
|
||||||
|
token.password = user.password
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
},
|
||||||
|
async session({ session, token }) {
|
||||||
|
return { ...session, user: { username: token.username } }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The idea is that once one is authenticated with the LDAP server, one can pass through both the username/DN and password to the JWT stored in the browser.
|
||||||
|
|
||||||
|
This is then passed back to any API routes and retrieved as such:
|
||||||
|
|
||||||
|
```js title="/pages/api/doLDAPWork.js"
|
||||||
|
token = await jwt.getToken({
|
||||||
|
req,
|
||||||
|
})
|
||||||
|
const { username, password } = token
|
||||||
|
```
|
||||||
|
|
||||||
|
> Thanks to [Winwardo](https://github.com/Winwardo) for the code example
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
---
|
||||||
|
id: securing-pages-and-api-routes
|
||||||
|
title: Securing pages and API routes
|
||||||
|
---
|
||||||
|
|
||||||
|
You can easily protect client and server side rendered pages and API routes with NextAuth.js.
|
||||||
|
|
||||||
|
_You can find working examples of the approaches shown below in the [example project](https://github.com/nextauthjs/next-auth-example/)._
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
The methods `getSession()` and `getToken()` both return an `object` if a session is valid and `null` if a session is invalid or has expired.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Securing Pages
|
||||||
|
|
||||||
|
### Client Side
|
||||||
|
|
||||||
|
If data on a page is fetched using calls to secure API routes - i.e. routes which use `getSession()` or `getToken()` to access the session - you can use the `useSession` React Hook to secure pages.
|
||||||
|
|
||||||
|
```js title="pages/client-side-example.js"
|
||||||
|
import { useSession, getSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const { data: session, status } = useSession()
|
||||||
|
|
||||||
|
if (status === "loading") {
|
||||||
|
return <p>Loading...</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status === "unauthenticated") {
|
||||||
|
return <p>Access Denied</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Protected Page</h1>
|
||||||
|
<p>You can view this page because you are signed in.</p>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Next.js (Middleware)
|
||||||
|
|
||||||
|
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `middleware.js` file at the root or in the src directory (same level as your `pages`) which looks like this:
|
||||||
|
|
||||||
|
```js title="/middleware.js"
|
||||||
|
export { default } from "next-auth/middleware"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you only want to secure certain pages, export a `config` object with a `matcher`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export { default } from "next-auth/middleware"
|
||||||
|
|
||||||
|
export const config = { matcher: ["/dashboard(.*)"] }
|
||||||
|
```
|
||||||
|
|
||||||
|
For the time being, the `withAuth` middleware only supports `"jwt"` as [session strategy](https://next-auth.js.org/configuration/options#session).
|
||||||
|
|
||||||
|
More details can be found [here](https://next-auth.js.org/configuration/nextjs#middleware).
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
To include all `dashboard` nested routes (sub pages like `/dashboard/settings`, `/dashboard/profile`) you can pass `matcher: "/dashboard/:path*"` to `config`.
|
||||||
|
|
||||||
|
For other patterns check out the [Next.js Middleware documentation](https://nextjs.org/docs/advanced-features/middleware#matcher).
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Server Side
|
||||||
|
|
||||||
|
You can protect server side rendered pages using the `getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly.
|
||||||
|
|
||||||
|
You need to add this to every server rendered page you want to protect. Be aware, `getServerSession` takes slightly different arguments than the method it is replacing, `getSession`.
|
||||||
|
|
||||||
|
```js title="pages/server-side-example.js"
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
import { authOptions } from "./api/auth/[...nextauth]"
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
const { data: session } = useSession()
|
||||||
|
|
||||||
|
if (typeof window === "undefined") return null
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Protected Page</h1>
|
||||||
|
<p>You can view this page because you are signed in.</p>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return <p>Access Denied</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
session: await getServerSession(
|
||||||
|
context.req,
|
||||||
|
context.res,
|
||||||
|
authOptions
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
When you supply a `session` prop in `_app.js`, `useSession` won't show a loading state, as it'll already have the session available. In this way, you can provide a more seamless user experience.
|
||||||
|
|
||||||
|
```js title="pages/_app.js"
|
||||||
|
import { SessionProvider } from "next-auth/react"
|
||||||
|
|
||||||
|
export default function App({
|
||||||
|
Component,
|
||||||
|
pageProps: { session, ...pageProps },
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SessionProvider session={session}>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</SessionProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Securing API Routes
|
||||||
|
|
||||||
|
### Using getServerSession()
|
||||||
|
|
||||||
|
You can protect API routes using the `getServerSession()` method.
|
||||||
|
|
||||||
|
```js title="pages/api/get-session-example.js"
|
||||||
|
import { getServerSession } from "next-auth/next"
|
||||||
|
import { authOptions } from "./auth/[...nextauth]"
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
const session = await getServerSession(req, res, authOptions)
|
||||||
|
if (session) {
|
||||||
|
// Signed in
|
||||||
|
console.log("Session", JSON.stringify(session, null, 2))
|
||||||
|
} else {
|
||||||
|
// Not Signed in
|
||||||
|
res.status(401)
|
||||||
|
}
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using getToken()
|
||||||
|
|
||||||
|
If you are using JSON Web Tokens you can use the `getToken()` helper to access the contents of the JWT without having to handle JWT decryption / verification yourself. This method can only be used server side.
|
||||||
|
|
||||||
|
```js title="pages/api/get-token-example.js"
|
||||||
|
// This is an example of how to read a JSON Web Token from an API route
|
||||||
|
import { getToken } from "next-auth/jwt"
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
// If you don't have NEXTAUTH_SECRET set, you will have to pass your secret as `secret` to `getToken`
|
||||||
|
const token = await getToken({ req })
|
||||||
|
if (token) {
|
||||||
|
// Signed in
|
||||||
|
console.log("JSON Web Token", JSON.stringify(token, null, 2))
|
||||||
|
} else {
|
||||||
|
// Not Signed in
|
||||||
|
res.status(401)
|
||||||
|
}
|
||||||
|
res.end()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
You can use the `getToken()` helper function in any application as long as you set the `NEXTAUTH_URL` environment variable and the application is able to read the JWT cookie (e.g. is on the same domain).
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Pass `getToken` the same value for `secret` as specified in `pages/api/auth/[...nextauth].js`.
|
||||||
|
|
||||||
|
See [the documentation for the JWT option](/configuration/options#jwt) for more information.
|
||||||
|
:::
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
---
|
||||||
|
id: testing-with-cypress
|
||||||
|
title: Testing with Cypress
|
||||||
|
---
|
||||||
|
|
||||||
|
To test an implementation of NextAuth.js, we encourage you to use [Cypress](https://cypress.io).
|
||||||
|
|
||||||
|
## Setting up Cypress
|
||||||
|
|
||||||
|
To get started, install the dependencies:
|
||||||
|
|
||||||
|
```bash npm2yarn2pnpm
|
||||||
|
npm install --save-dev cypress cypress-social-logins @testing-library/cypress
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you are using username/password based login, you will not need the `cypress-social-login` dependency.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Cypress will install and initialize the folder structure with example integration tests, a folder for plugins, etc.
|
||||||
|
|
||||||
|
Next you will have to create some configuration files for Cypress.
|
||||||
|
|
||||||
|
First, the primary cypress config:
|
||||||
|
|
||||||
|
```js title="cypress.json"
|
||||||
|
{
|
||||||
|
"baseUrl": "http://localhost:3000",
|
||||||
|
"chromeWebSecurity": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This initial Cypress config will tell Cypress where to find your site on initial launch as well as allow it to open up URLs at domains that aren't your page, for example to be able to login to a social provider.
|
||||||
|
|
||||||
|
Second, a cypress file for environment variables. These can be defined in `cypress.json` under the key `env` as well, however since we're storing username / passwords in here we should keep those in a separate file and only commit `cypress.json` to version control, not `cypress.env.json`.
|
||||||
|
|
||||||
|
```js title="cypress.env.json"
|
||||||
|
{
|
||||||
|
"GOOGLE_USER": "username@company.com",
|
||||||
|
"GOOGLE_PW": "password",
|
||||||
|
"COOKIE_NAME": "next-auth.session-token",
|
||||||
|
"SITE_NAME": "http://localhost:3000"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You must change the login credentials you want to use, but you can also redefine the name of the `GOOGLE_*` variables if you're using a different provider. `COOKIE_NAME`, however, must be set to that value for NextAuth.js.
|
||||||
|
|
||||||
|
Third, if you're using the `cypress-social-login` plugin, you must add this to your `/cypress/plugins/index.js` file like so:
|
||||||
|
|
||||||
|
```js title="cypress/plugins/index.js"
|
||||||
|
const { GoogleSocialLogin } = require("cypress-social-logins").plugins
|
||||||
|
|
||||||
|
module.exports = (on, config) => {
|
||||||
|
on("task", {
|
||||||
|
GoogleSocialLogin: GoogleSocialLogin,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, you can also add the following npm scripts to your `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"test:e2e:open": "cypress open",
|
||||||
|
"test:e2e:run": "cypress run"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Writing a test
|
||||||
|
|
||||||
|
Once we've got all that configuration out of the way, we can begin writing tests to login using NextAuth.js.
|
||||||
|
|
||||||
|
The basic login test looks like this:
|
||||||
|
|
||||||
|
```js title="cypress/integration/login.js"
|
||||||
|
describe("Login page", () => {
|
||||||
|
before(() => {
|
||||||
|
cy.log(`Visiting https://company.tld`)
|
||||||
|
cy.visit("/")
|
||||||
|
})
|
||||||
|
it("Login with Google", () => {
|
||||||
|
const username = Cypress.env("GOOGLE_USER")
|
||||||
|
const password = Cypress.env("GOOGLE_PW")
|
||||||
|
const loginUrl = Cypress.env("SITE_NAME")
|
||||||
|
const cookieName = Cypress.env("COOKIE_NAME")
|
||||||
|
const socialLoginOptions = {
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
loginUrl,
|
||||||
|
headless: true,
|
||||||
|
logs: false,
|
||||||
|
isPopup: true,
|
||||||
|
loginSelector: `a[href="${Cypress.env(
|
||||||
|
"SITE_NAME"
|
||||||
|
)}/api/auth/signin/google"]`,
|
||||||
|
postLoginSelector: ".unread-count",
|
||||||
|
}
|
||||||
|
|
||||||
|
return cy
|
||||||
|
.task("GoogleSocialLogin", socialLoginOptions)
|
||||||
|
.then(({ cookies }) => {
|
||||||
|
cy.clearCookies()
|
||||||
|
|
||||||
|
const cookie = cookies
|
||||||
|
.filter((cookie) => cookie.name === cookieName)
|
||||||
|
.pop()
|
||||||
|
if (cookie) {
|
||||||
|
cy.setCookie(cookie.name, cookie.value, {
|
||||||
|
domain: cookie.domain,
|
||||||
|
expiry: cookie.expires,
|
||||||
|
httpOnly: cookie.httpOnly,
|
||||||
|
path: cookie.path,
|
||||||
|
secure: cookie.secure,
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Cookies.defaults({
|
||||||
|
preserve: cookieName,
|
||||||
|
})
|
||||||
|
|
||||||
|
// remove the two lines below if you need to stay logged in
|
||||||
|
// for your remaining tests
|
||||||
|
cy.visit("/api/auth/signout")
|
||||||
|
cy.get("form").submit()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Things to note here include, that you must adjust the CSS selector defined under `postLoginSelector` to match a selector found on your page after the user is logged in. This is how Cypress knows whether it succeeded or not. Also, if you're using another provider, you will have to adjust the `loginSelector` URL.
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
---
|
||||||
|
id: usage-with-class-components
|
||||||
|
title: Usage with class components
|
||||||
|
---
|
||||||
|
|
||||||
|
If you want to use the `useSession()` hook in your class components you can do so with the help of a higher order component or with a render prop.
|
||||||
|
|
||||||
|
## Higher Order Component
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
const withSession = (Component) => (props) => {
|
||||||
|
const session = useSession()
|
||||||
|
|
||||||
|
// if the component has a render property, we are good
|
||||||
|
if (Component.prototype.render) {
|
||||||
|
return <Component session={session} {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the passed component is a function component, there is no need for this wrapper
|
||||||
|
throw new Error(
|
||||||
|
[
|
||||||
|
"You passed a function component, `withSession` is not needed.",
|
||||||
|
"You can `useSession` directly in your component.",
|
||||||
|
].join("\n")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
class ClassComponent extends React.Component {
|
||||||
|
render() {
|
||||||
|
const { data: session, status } = this.props.session
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClassComponentWithSession = withSession(ClassComponent)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Render Prop
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
|
||||||
|
const UseSession = ({ children }) => {
|
||||||
|
const session = useSession()
|
||||||
|
return children(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
class ClassComponent extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<UseSession>
|
||||||
|
{(session) => <pre>{JSON.stringify(session, null, 2)}</pre>}
|
||||||
|
</UseSession>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
id: warnings
|
||||||
|
title: Warnings
|
||||||
|
---
|
||||||
|
|
||||||
|
This is a list of warning output from NextAuth.js.
|
||||||
|
|
||||||
|
All warnings indicate things which you should take a look at, but do not inhibit normal operation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Client
|
||||||
|
|
||||||
|
#### NEXTAUTH_URL
|
||||||
|
|
||||||
|
Environment variable `NEXTAUTH_URL` missing. Please set it in your `.env` file.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
On [Vercel](https://vercel.com) deployments, we will read the `VERCEL_URL` environment variable, so you won't need to define `NEXTAUTH_URL`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Server
|
||||||
|
|
||||||
|
These warnings are displayed on the terminal.
|
||||||
|
|
||||||
|
#### NO_SECRET
|
||||||
|
|
||||||
|
In development, we generate a `secret` based on your configuration for convenience. This is volatile and will throw an error in production. [Read more](https://next-auth.js.org/configuration/options#secret)
|
||||||
|
|
||||||
|
#### TWITTER_OAUTH_2_BETA
|
||||||
|
|
||||||
|
Twitter OAuth 2.0 is currently in beta as certain changes might still be necessary. This is not covered by semver. See the docs https://next-auth.js.org/providers/twitter#oauth-2
|
||||||
|
|
||||||
|
#### EXPERIMENTAL_API
|
||||||
|
|
||||||
|
Some APIs are still experimental; they may be changed or removed in the future. Use at your own risk.
|
||||||
|
|
||||||
|
#### DEBUG_ENABLED
|
||||||
|
|
||||||
|
You have enabled the `debug` option. It is meant for development only, to help you catch issues in your authentication flow and you should consider removing this option when deploying to production. One way of only allowing debugging while not in production is to set `debug: process.env.NODE_ENV !== "production"`, so you can commit this without needing to change the value.
|
||||||
|
|
||||||
|
If you want to log debug messages during production anyway, we recommend setting the [`logger` option](/configuration/options#logger) with proper sanitization of potentially sensitive user information.
|
||||||
|
|
||||||
|
## Adapter
|
||||||
|
|
||||||
|
### ADAPTER_TYPEORM_UPDATING_ENTITIES
|
||||||
|
|
||||||
|
This warning occurs when typeorm finds that the provided entities differ from the database entities. By default while not in `production` the typeorm adapter will always synchronize changes made to the entities codefiles.
|
||||||
|
|
||||||
|
Disable this warning by setting `synchronize: false` in your typeorm config
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js title="/pages/api/auth/[...nextauth].js"
|
||||||
|
adapter: TypeORMLegacyAdapter({
|
||||||
|
type: 'mysql',
|
||||||
|
username: process.env.DATABASE_USERNAME,
|
||||||
|
password: process.env.DATABASE_PASSWORD,
|
||||||
|
host: process.env.DATABASE_HOST,
|
||||||
|
database: process.env.DATABASE_DB,
|
||||||
|
synchronize: false
|
||||||
|
}),
|
||||||
|
```
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user