Compare commits

...

16 Commits

Author SHA1 Message Date
Balázs Orbán
362e981e6d chore(release): bump package version(s) [skip ci] 2022-11-06 06:07:47 +01:00
Balázs Orbán
5198eb19f7 fix(next): build RSC+unstable_getServerSession 2022-11-06 05:53:38 +01:00
Balázs Orbán
0210cfccf3 chore(release): bump package version(s) [skip ci] 2022-11-06 05:12:31 +01:00
Balázs Orbán
e90925bea0 feat(next): allow unstable_getServerSession in Server Components (#5741)
* feat(next): support Server Components with `unstable_getServerSession`

* chore: remove `.entries`

* docs(next): add documentation for RSC

* update beta docs

* chore(dev): add app dir

* fix text

* only show second warning if using with RSC

* only delete expires for RSC case
2022-11-06 04:03:26 +00:00
Leif Arriens
27a0b70d87 docs: fix import path at providers/oauth (#5725) (#5736) 2022-11-06 00:54:01 +01:00
Balázs Orbán
c676e93d8a chore(release): bump package version(s) [skip ci] 2022-11-05 23:43:00 +01:00
Matthew Francis Brunetti
f498e9cd0a fix(react): allow imports from "next-auth/react" in RSC (#5718) 2022-11-05 23:09:51 +01:00
Balázs Orbán
2f3396d376 chore(release): bump package version(s) [skip ci] 2022-11-04 03:48:42 +01:00
Balázs Orbán
e62f879ebd chore(adapters): run Xata tests 2022-11-04 03:38:24 +01:00
Balázs Orbán
f67959eb04 chore: update example to Next.js 13 2022-11-04 03:33:42 +01:00
Henrik Wenz
060953dacf fix: support Next.js 13 (#5710)
* Migrate dev app to Next.js Version 13

* Update core types

* Fix middleware

https://github.com/nextauthjs/next-auth/issues/5649

* Use new ResponseCookie API

https://github.com/vercel/next.js/pull/41526
2022-11-04 03:32:48 +01:00
Nico Miebach
30ad639d16 fix: Add support for Node 18 (#5656)
* add support for Node 18

* update node engines in packages/next-auth

Co-authored-by: Thang Vu <hi@thvu.dev>
2022-10-30 23:54:16 -07:00
Thang Vu
777da4302d fix: add next 13 as peer dependencies (#5657)
fix: add next 13 as peer dependencies
2022-10-30 23:46:24 -07:00
Tejas Kumar
733fd5f234 feat(adapters): add Xata adapter (#4911)
* Add Xata adapter

* Adjust slogan

* Namespace tables for better DX

* Fix types

* Adjust docs

* Import type only

* Add scripts

* Fix types

* Update packages/adapter-xata/package.json

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Update packages/adapter-xata/package.json

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Update packages/adapter-xata/src/index.ts

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Update packages/adapter-xata/src/index.ts

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Update packages/adapter-xata/src/index.ts

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Update docs/docs/adapters/xata.md

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Update docs/docs/adapters/xata.md

Co-authored-by: Balázs Orbán <info@balazsorban.com>

* Address more comments

* Clarify codegen

* Fix by adding src

* Fix types

* More cleanup

* Fix import

* Clean up model

* Adjust docs

* Update docs

* Housekeeping

* Add tests

* Update lockfile

* Update packages/adapter-xata/tsconfig.json

Co-authored-by: Thang Vu <hi@thvu.dev>

* Update packages/adapter-xata/src/index.ts

Co-authored-by: Balázs Orbán <info@balazsorban.com>
Co-authored-by: Thang Vu <hi@thvu.dev>
2022-10-27 21:39:49 +07:00
Thang Vu
a787efc6be docs: improve documentation for adding new provider (#5633) 2022-10-25 10:05:52 +07:00
Bruno Crosier
261968b9bb docs: improve credentials docs (#5627) 2022-10-24 23:33:46 +07:00
43 changed files with 1313 additions and 315 deletions

View File

@@ -33,6 +33,7 @@ body:
- "@next-auth/sequelize-adapter"
- "@next-auth/typeorm-legacy-adapter"
- "@next-auth/upstash-redis-adapter"
- "@next-auth/xata-adapter"
validations:
required: true
- type: textarea

View File

@@ -35,3 +35,6 @@ typeorm-legacy:
upstash-redis:
- "@next-auth/upstash-redis-adapter"
xata:
- "@next-auth/xata-adapter"

View File

@@ -48,6 +48,9 @@ typeorm-legacy:
upstash-redis:
- packages/adapter-upstash-redis/**
xata:
- packages/adapter-xata/**
core:
- packages/next-auth/src/**/*

View File

@@ -4,5 +4,5 @@ outputs:
version:
description: "npm package version"
runs:
using: "node16"
using: "node18"
main: "index.js"

View File

@@ -25,7 +25,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: "pnpm"
- name: Install dependencies
run: pnpm install
@@ -59,7 +59,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: "pnpm"
- name: Install dependencies
run: pnpm install
@@ -89,7 +89,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
cache: "pnpm"
- name: Install dependencies
run: pnpm install

2
.nvmrc
View File

@@ -1 +1 @@
16
18

View File

@@ -41,7 +41,7 @@ corepack enable pnpm
(Now, if you run `pnpm --version`, it should print the same verion as the `packageManager` property in the [`package.json` file](https://github.com/nextauthjs/next-auth/blob/main/package.json))
3. Install packages. Developing requires Node.js v16:
3. Install packages. Developing requires Node.js v18:
```sh
pnpm install

12
apps/dev/app/layout.tsx Normal file
View File

@@ -0,0 +1,12 @@
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<head></head>
<body>{children}</body>
</html>
)
}

View File

@@ -0,0 +1,7 @@
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "pages/api/auth/[...nextauth]"
export default async function Page() {
const session = await unstable_getServerSession(authOptions)
return <pre>{JSON.stringify(session, null, 2)}</pre>
}

View File

@@ -17,9 +17,7 @@ export default function Footer() {
<a href="https://github.com/nextauthjs/next-auth-example">GitHub</a>
</li>
<li className={styles.navItem}>
<Link href="/policy">
<a>Policy</a>
</Link>
<Link href="/policy">Policy</Link>
</li>
<li className={styles.navItem}>
<em>{packageJSON.version}</em>

View File

@@ -64,49 +64,31 @@ export default function Header() {
<nav>
<ul className={styles.navItems}>
<li className={styles.navItem}>
<Link href="/">
<a>Home</a>
</Link>
<Link href="/">Home</Link>
</li>
<li className={styles.navItem}>
<Link href="/client">
<a>Client</a>
</Link>
<Link href="/client">Client</Link>
</li>
<li className={styles.navItem}>
<Link href="/server">
<a>Server</a>
</Link>
<Link href="/server">Server</Link>
</li>
<li className={styles.navItem}>
<Link href="/protected">
<a>Protected</a>
</Link>
<Link href="/protected">Protected</Link>
</li>
<li className={styles.navItem}>
<Link href="/protected-ssr">
<a>Protected(SSR)</a>
</Link>
<Link href="/protected-ssr">Protected(SSR)</Link>
</li>
<li className={styles.navItem}>
<Link href="/api-example">
<a>API</a>
</Link>
<Link href="/api-example">API</Link>
</li>
<li className={styles.navItem}>
<Link href="/credentials">
<a>Credentials</a>
</Link>
<Link href="/credentials">Credentials</Link>
</li>
<li className={styles.navItem}>
<Link href="/email">
<a>Email</a>
</Link>
<Link href="/email">Email</Link>
</li>
<li className={styles.navItem}>
<Link href="/middleware-protected">
<a>Middleware protected</a>
</Link>
<Link href="/middleware-protected">Middleware protected</Link>
</li>
</ul>
</nav>

View File

@@ -4,5 +4,6 @@ module.exports = {
config.experiments = { ...config.experiments, topLevelAwait: true }
return config
},
experimental: { appDir: true },
typescript: { ignoreBuildErrors: true },
}

View File

@@ -19,7 +19,7 @@
"@next-auth/typeorm-legacy-adapter": "workspace:*",
"@prisma/client": "^3",
"faunadb": "^4",
"next": "12.3.1",
"next": "13.0.2",
"next-auth": "workspace:*",
"nodemailer": "^6",
"react": "^18",

View File

@@ -1,8 +1,8 @@
// This is an example of how to access a session from an API route
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from '../auth/[...nextauth]';
import { authOptions } from "../auth/[...nextauth]"
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
res.send(JSON.stringify(session, null, 2))
const session = await unstable_getServerSession(authOptions)
res.json(session)
}

View File

@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
@@ -15,7 +19,20 @@
"incremental": true,
"jsx": "preserve",
"baseUrl": ".",
"plugins": [
{
"name": "next"
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules", "jest.config.js"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules",
"jest.config.js"
]
}

View File

@@ -17,9 +17,7 @@ export default function Footer() {
<a href="https://github.com/nextauthjs/next-auth-example">GitHub</a>
</li>
<li className={styles.navItem}>
<Link href="/policy">
<a>Policy</a>
</Link>
<Link href="/policy">Policy</Link>
</li>
<li className={styles.navItem}>
<em>next-auth@{packageJSON.dependencies["next-auth"]}</em>

View File

@@ -67,39 +67,25 @@ export default function Header() {
<nav>
<ul className={styles.navItems}>
<li className={styles.navItem}>
<Link href="/">
<a>Home</a>
</Link>
<Link href="/">Home</Link>
</li>
<li className={styles.navItem}>
<Link href="/client">
<a>Client</a>
</Link>
<Link href="/client">Client</Link>
</li>
<li className={styles.navItem}>
<Link href="/server">
<a>Server</a>
</Link>
<Link href="/server">Server</Link>
</li>
<li className={styles.navItem}>
<Link href="/protected">
<a>Protected</a>
</Link>
<Link href="/protected">Protected</Link>
</li>
<li className={styles.navItem}>
<Link href="/api-example">
<a>API</a>
</Link>
<Link href="/api-example">API</Link>
</li>
<li className={styles.navItem}>
<Link href="/admin">
<a>Admin</a>
</Link>
<Link href="/admin">Admin</Link>
</li>
<li className={styles.navItem}>
<Link href="/me">
<a>Me</a>
</Link>
<Link href="/me">Me</Link>
</li>
</ul>
</nav>

View File

@@ -1,12 +1,8 @@
import Header from "./header"
import Footer from "./footer"
import type { ReactChildren } from "react"
import type { ReactNode } from "react"
interface Props {
children: React.ReactNode
}
export default function Layout({ children }: Props) {
export default function Layout({ children }: { children: ReactNode }) {
return (
<>
<Header />

View File

@@ -13,13 +13,12 @@ export default function ServerSidePage({ session }: { session: Session }) {
<h1>Server Side Rendering</h1>
<p>
This page uses the <strong>unstable_getServerSession()</strong> method
in <strong>unstable_getServerSideProps()</strong>.
in <strong>getServerSideProps()</strong>.
</p>
<p>
Using <strong>unstable_getServerSession()</strong> in{" "}
<strong>unstable_getServerSideProps()</strong> is the recommended
approach if you need to support Server Side Rendering with
authentication.
<strong>getServerSideProps()</strong> is the recommended approach if you
need to support Server Side Rendering with authentication.
</p>
<p>
The advantage of Server Side Rendering is this page does not require

View File

@@ -11,6 +11,7 @@ When using a database, you can still use JWT for session handling for fast acces
We have a list of official adapters that are distributed as their own packages under the `@next-auth/{name}-adapter` namespace. Their source code is available in their various adapters package directories at [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth/tree/main/packages).
- [`xata`](./xata)
- [`prisma`](./prisma)
- [`fauna`](./fauna)
- [`dynamodb`](./dynamodb)

242
docs/docs/adapters/xata.md Normal file
View File

@@ -0,0 +1,242 @@
---
id: xata
title: Xata
---
# Xata
This adapter allows using next-auth with Xata as a database to store users, sessions, and more. The preferred way to create a Xata project and use Xata databases is using the [Xata Command Line Interface (CLI)](https://docs.xata.io/cli/getting-started). The CLI allows generating a `XataClient` that will help you work with Xata in a safe way, and that this adapter depends on.
<!-- @todo add GIFs -->
## Getting Started
Let's first make sure we have everything installed and configured. We're going to need:
- next-auth + adapter
- the Xata CLI
- to configure the CLI
We can do this like so:
```bash npm2yarn2pnpm
# Install next-auth + adapter
npm install next-auth @next-auth/xata-adapter
# Install the Xata CLI globally if you don't already have it
npm install --location=global @xata.io/cli
# Login
xata auth login
```
Now that we're ready, let's create a new Xata project using our next-auth schema that the Xata adapter can work with. To do that, copy and paste this schema file into your project's directory:
```json title="schema.json"
{
"formatVersion": "",
"tables": [
{
"name": "nextauth_users",
"columns": [
{
"name": "email",
"type": "email"
},
{
"name": "emailVerified",
"type": "datetime"
},
{
"name": "name",
"type": "string"
},
{
"name": "image",
"type": "string"
}
]
},
{
"name": "nextauth_accounts",
"columns": [
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
},
{
"name": "type",
"type": "string"
},
{
"name": "provider",
"type": "string"
},
{
"name": "providerAccountId",
"type": "string"
},
{
"name": "refresh_token",
"type": "string"
},
{
"name": "access_token",
"type": "string"
},
{
"name": "expires_at",
"type": "int"
},
{
"name": "token_type",
"type": "string"
},
{
"name": "scope",
"type": "string"
},
{
"name": "id_token",
"type": "text"
},
{
"name": "session_state",
"type": "string"
}
]
},
{
"name": "nextauth_verificationTokens",
"columns": [
{
"name": "identifier",
"type": "string"
},
{
"name": "token",
"type": "string"
},
{
"name": "expires",
"type": "datetime"
}
]
},
{
"name": "nextauth_users_accounts",
"columns": [
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
},
{
"name": "account",
"type": "link",
"link": {
"table": "nextauth_accounts"
}
}
]
},
{
"name": "nextauth_users_sessions",
"columns": [
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
},
{
"name": "session",
"type": "link",
"link": {
"table": "nextauth_sessions"
}
}
]
},
{
"name": "nextauth_sessions",
"columns": [
{
"name": "sessionToken",
"type": "string"
},
{
"name": "expires",
"type": "datetime"
},
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
}
]
}
]
}
```
Now, run the following command:
```bash
xata init --schema=./path/to/your/schema.json
```
The CLI will walk you through a setup process where you choose a [workspace](https://docs.xata.io/concepts/workspaces) (kind of like a GitHub org or a Vercel team) and an appropriate database. We recommend using a fresh database for this, as we'll augment it with tables that next-auth needs.
Once you're done, you can continue using next-auth in your project as expected, like creating a `./pages/api/auth/[...nextauth]` route.
```typescript title="pages/api/auth/[...nextauth].ts"
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
const client = new XataClient()
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
})
```
Now to Xata-fy this route, let's add the Xata client and adapter:
```diff
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
+import { XataAdapter } from "@next-auth/xata-adapter"
+import { XataClient } from "../../../xata" // or wherever you've chosen to create the client
+const client = new XataClient()
export default NextAuth({
+ adapter: XataAdapter(client),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
})
```
This fully sets up your next-auth site to work with Xata.
## Contributing
This is an open-source project created by humans, and as such, might have a few issues. If you experience any of these, we recommend [opening issues](https://github.com/nextauthjs/next-auth/issues/new?assignees=&labels=triage&template=1_bug_framework.yml&title=Issue%20on%20Xata%20adapter&description=I%20experienced%20this%20issue:\n##%20Reproduction%20Steps:\n\n-) that can help us solve problems and build reliable software.

View File

@@ -24,7 +24,7 @@ export const authOptions: NextAuthOptions = {
export default NextAuth(authOptions);
```
In `getServerSideProps`:
### In `getServerSideProps`:
```js
import { authOptions } from 'pages/api/auth/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
@@ -48,7 +48,8 @@ export async function getServerSideProps(context) {
}
}
```
In API routes:
### In API Routes:
```js
import { authOptions } from 'pages/api/auth/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
@@ -68,6 +69,24 @@ export async function handler(req, res) {
}
```
### In `app/` directory:
You can also use `unstable_getServerSession` in Next.js' server components:
```tsx
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "pages/api/auth/[...nextauth]"
export default async function Page() {
const session = await unstable_getServerSession(authOptions)
return <pre>{JSON.stringify(session, null, 2)}</pre>
}
```
:::warning
Currently, the underlying Next.js `cookies()` method does [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).
:::
## Middleware
You can use a Next.js Middleware with NextAuth.js to protect your site.

View File

@@ -83,7 +83,7 @@ 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/"
import TwitterProvider from "next-auth/providers/twitter"
...
providers: [
TwitterProvider({
@@ -281,7 +281,7 @@ An advanced option, hopefully you won't need it in most cases. `next-auth` uses
### `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.
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.
## Using a custom provider
@@ -425,10 +425,11 @@ GoogleProvider({
If you think your custom provider might be useful to others, we encourage you to open a PR and add it to the built-in list so others can discover it much more easily!
You only need to add two changes:
You only need to add three changes:
1. Add your config: [`src/providers/{provider}.ts`](https://github.com/nextauthjs/next-auth/tree/main/packages/next-auth/src/providers)<br />
• make sure you use a named default export, like this: `export default function YourProvider`
2. Add provider documentation: [`/docs/providers/{provider}.md`](https://github.com/nextauthjs/next-auth/tree/main/docs/docs/providers)
3. Add the new provider name to the `Provider type` dropdown options in [`the provider issue template`](<[http](https://github.com/nextauthjs/next-auth/edit/main/.github/ISSUE_TEMPLATE/2_bug_provider.yml)>)
That's it! 🎉 Others will be able to discover and use this provider much more easily now!

View File

@@ -44,8 +44,8 @@ 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.
// `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: {
@@ -54,7 +54,7 @@ providers: [
},
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" }
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

View File

@@ -3,7 +3,7 @@ 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-v16.x/docs/api/http.html), [`https` docs](https://nodejs.org/dist/latest-v16.x/docs/api/https.html)).
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).

View File

@@ -1,8 +1,8 @@
# Corporate 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) which uses the built-in Node.js `http` / `https` libraries, and those do not support proxys by default:
- [`http` docs](https://nodejs.org/dist/latest-v16.x/docs/api/http.html)
- [`https` docs](https://nodejs.org/dist/latest-v16.x/docs/api/https.html)
- [`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 add an additional proxy agent to the http client, such as `https-proxy-agent`.

View File

@@ -24,7 +24,7 @@ export const authOptions: NextAuthOptions = {
export default NextAuth(authOptions);
```
In `getServerSideProps`:
### In `getServerSideProps`:
```js
import { authOptions } from 'pages/api/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
@@ -48,7 +48,8 @@ export async function getServerSideProps(context) {
}
}
```
In API routes:
### In API routes:
```js
import { authOptions } from 'pages/api/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
@@ -68,6 +69,24 @@ export async function handler(req, res) {
}
```
### In `app/` directory:
You can also use `unstable_getServerSession` in Next.js' server components:
```tsx
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "pages/api/auth/[...nextauth]"
export default async function Page() {
const session = await unstable_getServerSession(authOptions)
return <pre>{JSON.stringify(session, null, 2)}</pre>
}
```
:::warning
Currently, the underlying Next.js `cookies()` method does [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).
:::
## Middleware
You can use a Next.js Middleware with NextAuth.js to protect your site.

View File

@@ -40,7 +40,7 @@
"typescript": "4.8.4"
},
"engines": {
"node": "^12.19.0 || ^14.15.0 || ^16.13.0"
"node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0"
},
"prettier": {
"semi": false,

View File

@@ -0,0 +1,249 @@
<p align="center">
<br/>
<a href="https://next-auth.js.org" target="_blank"><img height="64px" src="https://next-auth.js.org/img/logo/logo-sm.png" /></a>&nbsp;&nbsp;&nbsp;&nbsp;<img height="64px" src="logo.svg" />
<h3 align="center"><b>Xata Adapter</b> - NextAuth.js</h3>
<p align="center">
Think data, not databases.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/xata-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/xata-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/xata-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/xata-adapter/next" alt="@next-auth/xata-adapter Version" /></a>
</p>
</p>
This adapter allows using next-auth with Xata as a database to store users, sessions, and more. The preferred way to create a Xata project and use Xata databases is using the [Xata Command Line Interface (CLI)](https://docs.xata.io/cli/getting-started). The CLI allows generating a `XataClient` that will help you work with Xata in a safe way, and that this adapter depends on.
<!-- @todo add GIFs -->
## Getting Started
Let's first make sure we have everything installed and configured. We're going to need:
- next-auth + adapter
- the Xata CLI
- to configure the CLI
We can do this like so:
```bash npm2yarn2pnpm
# Install next-auth + adapter
npm install next-auth @next-auth/xata-adapter
# Install the Xata CLI globally if you don't already have it
npm install --location=global @xata.io/cli
# Login
xata auth login
```
Now that we're ready, let's create a new Xata project using our next-auth schema that the Xata adapter can work with. To do that, copy and paste this schema file into your project's directory:
```json title="schema.json"
{
"formatVersion": "",
"tables": [
{
"name": "nextauth_users",
"columns": [
{
"name": "email",
"type": "email"
},
{
"name": "emailVerified",
"type": "datetime"
},
{
"name": "name",
"type": "string"
},
{
"name": "image",
"type": "string"
}
]
},
{
"name": "nextauth_accounts",
"columns": [
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
},
{
"name": "type",
"type": "string"
},
{
"name": "provider",
"type": "string"
},
{
"name": "providerAccountId",
"type": "string"
},
{
"name": "refresh_token",
"type": "string"
},
{
"name": "access_token",
"type": "string"
},
{
"name": "expires_at",
"type": "int"
},
{
"name": "token_type",
"type": "string"
},
{
"name": "scope",
"type": "string"
},
{
"name": "id_token",
"type": "text"
},
{
"name": "session_state",
"type": "string"
}
]
},
{
"name": "nextauth_verificationTokens",
"columns": [
{
"name": "identifier",
"type": "string"
},
{
"name": "token",
"type": "string"
},
{
"name": "expires",
"type": "datetime"
}
]
},
{
"name": "nextauth_users_accounts",
"columns": [
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
},
{
"name": "account",
"type": "link",
"link": {
"table": "nextauth_accounts"
}
}
]
},
{
"name": "nextauth_users_sessions",
"columns": [
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
},
{
"name": "session",
"type": "link",
"link": {
"table": "nextauth_sessions"
}
}
]
},
{
"name": "nextauth_sessions",
"columns": [
{
"name": "sessionToken",
"type": "string"
},
{
"name": "expires",
"type": "datetime"
},
{
"name": "user",
"type": "link",
"link": {
"table": "nextauth_users"
}
}
]
}
]
}
```
Now, run the following command:
```bash
xata init --schema=./path/to/your/schema.json
```
The CLI will walk you through a setup process where you choose a [workspace](https://docs.xata.io/concepts/workspaces) (kind of like a GitHub org or a Vercel team) and an appropriate database. We recommend using a fresh database for this, as we'll augment it with tables that next-auth needs.
Once you're done, you can continue using next-auth in your project as expected, like creating a `./pages/api/auth/[...nextauth]` route.
```typescript title="pages/api/auth/[...nextauth].ts"
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
const client = new XataClient()
export default NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
})
```
Now to Xata-fy this route, let's add the Xata client and adapter:
```diff
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
+import { XataAdapter } from "@next-auth/xata-adapter"
+import { XataClient } from "../../../xata" // or wherever you've chosen to create the client
+const client = new XataClient()
export default NextAuth({
+ adapter: XataAdapter(client),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
})
```
This fully sets up your next-auth site to work with Xata.
## Contributing
This is an open-source project created by humans, and as such, might have a few issues. If you experience any of these, we recommend [opening issues](https://github.com/nextauthjs/next-auth/issues/new?assignees=&labels=triage&template=1_bug_framework.yml&title=Issue%20on%20Xata%20adapter&description=I%20experienced%20this%20issue:\n##%20Reproduction%20Steps:\n\n-) that can help us solve problems and build reliable software.

View File

@@ -0,0 +1,6 @@
<svg width="461" height="467" viewBox="0 0 461 467" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M389.431 465.611C421.673 433.443 443.246 393.222 449.403 353.796C455.56 314.369 445.797 278.966 422.262 255.376L300.691 376.663L389.431 465.611Z" fill="#06D6A0"/>
<path d="M71.5738 466.306C39.331 434.138 17.7582 393.917 11.6011 354.49C5.44395 315.064 15.2069 279.661 38.7422 256.07L160.314 377.358L71.5738 466.306Z" fill="#FFBB00"/>
<path d="M0.673946 122.184C0.727229 167.729 18.8709 211.387 51.1137 243.554L51.1168 243.551L172.673 364.823C204.84 332.58 222.882 288.88 222.829 243.335C222.775 197.79 204.632 154.132 172.389 121.964L172.386 121.967L50.8296 0.695312C18.6622 32.9381 0.620662 76.6388 0.673946 122.184Z" fill="#FF0075"/>
<path d="M460.329 121.488C460.276 167.033 442.132 210.692 409.89 242.859L409.886 242.855L288.33 364.127C256.163 331.884 238.121 288.183 238.175 242.638C238.228 197.094 256.372 153.435 288.614 121.268L288.618 121.271L410.174 0C442.341 32.2428 460.383 75.9435 460.329 121.488Z" fill="#0076FF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,46 @@
{
"name": "@next-auth/xata-adapter",
"version": "0.2.0",
"description": "Xata adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},
"author": "Tejas Kumar",
"main": "dist/index.js",
"license": "ISC",
"keywords": [
"next-auth",
"next.js",
"oauth",
"xata"
],
"private": false,
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "tsc",
"test": "jest"
},
"files": [
"README.md",
"dist"
],
"peerDependencies": {
"@xata.io/client": ">=0.13.0",
"next-auth": "^4"
},
"devDependencies": {
"@next-auth/adapter-test": "workspace:^0.0.0",
"@next-auth/tsconfig": "workspace:^0.0.0",
"jest": "^27.4.3",
"next-auth": "workspace:*",
"@xata.io/client": "^0.13.0",
"typescript": "^4.7.4"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
}
}

View File

@@ -0,0 +1,162 @@
import type { Adapter } from "next-auth/adapters"
import type { XataClient } from "./xata"
export function XataAdapter(client: XataClient): Adapter {
return {
async createUser(user) {
const newUser = await client.db.nextauth_users.create(user)
return newUser
},
async getUser(id) {
const user = await client.db.nextauth_users.filter({ id }).getFirst()
return user ?? null
},
async getUserByEmail(email) {
const user = await client.db.nextauth_users.filter({ email }).getFirst()
return user ?? null
},
async getUserByAccount({ providerAccountId, provider }) {
const result = await client.db.nextauth_users_accounts
.select(["user.*"])
.filter({
"account.providerAccountId": providerAccountId,
"account.provider": provider,
})
.getFirst()
const user = result?.user
return user ?? null
},
async updateUser(user) {
const result = await client.db.nextauth_users.update(user.id!, user)
return (
result ?? {
...user,
id: user.id!,
emailVerified: user.emailVerified ?? null,
}
)
},
async deleteUser(id) {
return await client.db.nextauth_users.delete(id)
},
async linkAccount(initialAccount) {
const { userId, ...account } = initialAccount
const newXataAccount = await client.db.nextauth_accounts.create({
...account,
user: { id: userId },
})
await client.db.nextauth_users_accounts.create({
user: { id: userId },
account: { id: newXataAccount.id },
})
},
async unlinkAccount({ providerAccountId, provider }) {
/**
* @todo refactor this when we support DELETE WHERE.
*/
const connectedAccount = await client.db.nextauth_users_accounts
.filter({
"account.providerAccountId": providerAccountId,
"account.provider": provider,
})
.getFirst()
if (!connectedAccount) {
return
}
return await client.db.nextauth_users_accounts.delete(connectedAccount.id)
},
async createSession(initialSession) {
const { userId, ...session } = initialSession
const newXataSession = await client.db.nextauth_sessions.create({
...session,
user: { id: userId },
})
await client.db.nextauth_users_sessions.create({
user: { id: userId },
session: { id: newXataSession.id },
})
return { ...session, ...newXataSession, userId }
},
async getSessionAndUser(sessionToken) {
const result = await client.db.nextauth_users_sessions
.select(["user.*", "session.*"])
.filter({ "session.sessionToken": sessionToken })
.getFirst()
if (!result?.session || !result?.user) {
return null
}
return {
session: {
...result.session,
sessionToken: result.session.sessionToken!,
expires: result.session.expires!,
userId: result.user.id,
},
user: {
...result.user,
emailVerified: result.user.emailVerified ?? null,
},
}
},
async updateSession({ sessionToken, ...data }) {
const session = await client.db.nextauth_sessions
.filter({ sessionToken })
.getFirst()
if (!session) {
return null
}
await client.db.nextauth_sessions.update({ ...session, ...data })
return {
...session,
sessionToken,
userId: data.userId!,
expires: data.expires!,
}
},
async deleteSession(sessionToken) {
/**
* @todo refactor this when we support DELETE WHERE.
*/
const session = await client.db.nextauth_sessions
.filter({ sessionToken })
.getFirst()
if (!session) {
return
}
const connectedSession = await client.db.nextauth_users_sessions
.filter({ "session.sessionToken": sessionToken })
.getFirst()
if (!connectedSession) {
return
}
await client.db.nextauth_sessions.delete(session.id)
await client.db.nextauth_users_sessions.delete(connectedSession.id)
},
async createVerificationToken(token) {
await client.db.nextauth_verificationTokens.create({
expires: token.expires,
identifier: token.identifier,
token: token.token,
})
return token
},
async useVerificationToken(token) {
/**
* @todo refactor this when we support DELETE WHERE.
*/
const xataToken = await client.db.nextauth_verificationTokens
.filter({ identifier: token.identifier, token: token.token })
.getFirst()
if (!xataToken) {
return null
}
await client.db.nextauth_verificationTokens.delete(xataToken.id)
return { ...token, expires: new Date() }
},
}
}

View File

@@ -0,0 +1,93 @@
/**
* This file is auto-generated from Xata and corresponds
* to the database types in the Xata database. Please do not
* augment by hand.
*/
import {
buildClient,
BaseClientOptions,
XataRecord,
ClientConstructor,
} from "@xata.io/client"
export interface NextauthUser {
email?: string | null
emailVerified?: Date | null
name?: string | null
image?: string | null
}
export type NextauthUserRecord = NextauthUser & XataRecord
export interface NextauthAccount {
user?: NextauthUserRecord | null
type?: string | null
provider?: string | null
providerAccountId?: string | null
refresh_token?: string | null
access_token?: string | null
expires_at?: number | null
token_type?: string | null
scope?: string | null
id_token?: string | null
session_state?: string | null
}
export type NextauthAccountRecord = NextauthAccount & XataRecord
export interface NextauthVerificationToken {
identifier?: string | null
token?: string | null
expires?: Date | null
}
export type NextauthVerificationTokenRecord = NextauthVerificationToken &
XataRecord
export interface NextauthUsersAccount {
user?: NextauthUserRecord | null
account?: NextauthAccountRecord | null
}
export type NextauthUsersAccountRecord = NextauthUsersAccount & XataRecord
export interface NextauthUsersSession {
user?: NextauthUserRecord | null
session?: NextauthSessionRecord | null
}
export type NextauthUsersSessionRecord = NextauthUsersSession & XataRecord
export interface NextauthSession {
sessionToken?: string | null
expires?: Date | null
user?: NextauthUserRecord | null
}
export type NextauthSessionRecord = NextauthSession & XataRecord
export type DatabaseSchema = {
nextauth_users: NextauthUser
nextauth_accounts: NextauthAccount
nextauth_verificationTokens: NextauthVerificationToken
nextauth_users_accounts: NextauthUsersAccount
nextauth_users_sessions: NextauthUsersSession
nextauth_sessions: NextauthSession
}
const tables = [
"nextauth_users",
"nextauth_accounts",
"nextauth_verificationTokens",
"nextauth_users_accounts",
"nextauth_users_sessions",
"nextauth_sessions",
]
const DatabaseClient = buildClient() as ClientConstructor<any>
export class XataClient extends DatabaseClient<DatabaseSchema> {
constructor(options?: BaseClientOptions) {
super({ databaseURL: "", ...options }, tables)
}
}

View File

@@ -0,0 +1,56 @@
import "isomorphic-fetch"
import { runBasicTests } from "@next-auth/adapter-test"
import "dotenv/config"
import { XataClient } from "../src/xata"
import { XataAdapter } from "../src"
if (!process.env.XATA_API_KEY) {
test("Skipping XataAdapter tests, since required environment variables aren't available", () => {
expect(true).toBe(true)
})
process.exit(0)
}
if (process.env.CI) {
// TODO: Fix this
test('Skipping XataAdapter tests in CI because of "Request failed" errors. Should revisit', () => {
expect(true).toBe(true)
})
process.exit(0)
}
const client = new XataClient({
apiKey: process.env.XATA_API_KEY,
})
runBasicTests({
adapter: XataAdapter(client),
db: {
async user(id: string) {
const data = await client.db.nextauth_users.filter({ id }).getFirst()
if (!data) return null
return data
},
async account({ provider, providerAccountId }) {
const data = await client.db.nextauth_accounts
.filter({ provider, providerAccountId })
.getFirst()
if (!data) return null
return data
},
async session(sessionToken) {
const data = await client.db.nextauth_sessions
.filter({ sessionToken })
.getFirst()
if (!data) return null
return data
},
async verificationToken(where) {
const data = await client.db.nextauth_verificationTokens
.filter(where)
.getFirst()
if (!data) return null
return data
},
},
})

View File

@@ -0,0 +1,9 @@
{
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["."],
"exclude": ["tests", "dist", "jest.config.js"]
}

View File

@@ -1,6 +1,6 @@
{
"name": "next-auth",
"version": "4.15.0",
"version": "4.16.1",
"description": "Authentication for Next.js",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth.git",
@@ -78,7 +78,7 @@
"uuid": "^8.3.2"
},
"peerDependencies": {
"next": "^12.2.5",
"next": "^12.2.5 || ^13",
"nodemailer": "^6.6.5",
"react": "^17.0.2 || ^18",
"react-dom": "^17.0.2 || ^18"
@@ -120,7 +120,7 @@
"jest-environment-jsdom": "^28.1.1",
"jest-watch-typeahead": "^1.1.0",
"msw": "^0.42.3",
"next": "12.3.1",
"next": "13.0.2",
"postcss": "^8.4.14",
"postcss-cli": "^9.1.0",
"postcss-nested": "^5.0.6",
@@ -129,6 +129,6 @@
"whatwg-fetch": "^3.6.2"
},
"engines": {
"node": "^12.19.0 || ^14.15.0 || ^16.13.0"
"node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0"
}
}
}

View File

@@ -58,10 +58,8 @@ async function toInternalRequest(
const url = new URL(req.url)
// TODO: handle custom paths?
const nextauth = url.pathname.split("/").slice(3)
const headers = Object.fromEntries(req.headers.entries())
const query: Record<string, any> = Object.fromEntries(
url.searchParams.entries()
)
const headers = Object.fromEntries(req.headers)
const query: Record<string, any> = Object.fromEntries(url.searchParams)
query.nextauth = nextauth
return {

View File

@@ -1,6 +1,7 @@
import type { IncomingHttpHeaders } from "http"
import type { CookiesOptions } from "../.."
import type { CookieOption, LoggerInstance, SessionStrategy } from "../types"
import type { NextRequest } from "next/server"
import type { NextApiRequest } from "next"
// Uncomment to recalculate the estimated size
// of an empty session cookie
@@ -128,10 +129,10 @@ export class SessionStore {
constructor(
option: CookieOption,
req: {
cookies?: Partial<Record<string, string> | Map<string, string>>
headers?: Headers | IncomingHttpHeaders | Record<string, string>
},
req: Partial<{
cookies: NextRequest["cookies"] | NextApiRequest["cookies"]
headers: NextRequest["headers"] | NextApiRequest["headers"]
}>,
logger: LoggerInstance | Console
) {
this.#logger = logger
@@ -140,7 +141,14 @@ export class SessionStore {
const { cookies } = req
const { name: cookieName } = option
if (cookies instanceof Map) {
if (typeof cookies?.getAll === "function") {
// Next.js ^v13.0.1 (Edge Env)
for (const { name, value } of cookies.getAll()) {
if (name.startsWith(cookieName)) {
this.#chunks[name] = value
}
}
} else if (cookies instanceof Map) {
for (const name of cookies.keys()) {
if (name.startsWith(cookieName)) this.#chunks[name] = cookies.get(name)
}

View File

@@ -27,7 +27,7 @@ export default async function getAuthorizationUrl({
if (typeof provider.authorization === "string") {
const parsedUrl = new URL(provider.authorization)
const parsedParams = Object.fromEntries(parsedUrl.searchParams.entries())
const parsedParams = Object.fromEntries(parsedUrl.searchParams)
params = { ...params, ...parsedParams }
} else {
params = { ...params, ...provider.authorization?.params }

View File

@@ -1,6 +1,7 @@
import { NextAuthHandler } from "../core"
import { detectHost } from "../utils/detect-host"
import { setCookie } from "./utils"
import { cookies as nextCookies, headers } from "next/headers"
import type {
GetServerSidePropsContext,
@@ -84,6 +85,7 @@ function NextAuth(
export default NextAuth
let experimentalWarningShown = false
let experimentalRSCWarningShown = false
export async function unstable_getServerSession(
...args:
| [
@@ -92,6 +94,7 @@ export async function unstable_getServerSession(
NextAuthOptions
]
| [NextApiRequest, NextApiResponse, NextAuthOptions]
| [NextAuthOptions]
): Promise<Session | null> {
if (!experimentalWarningShown && process.env.NODE_ENV !== "production") {
console.warn(
@@ -103,7 +106,33 @@ export async function unstable_getServerSession(
experimentalWarningShown = true
}
const [req, res, options] = args
const isRSC = args.length === 1
if (
!experimentalRSCWarningShown &&
isRSC &&
process.env.NODE_ENV !== "production"
) {
console.warn(
"[next-auth][warn][EXPERIMENTAL_API]",
"\n`unstable_getServerSession` is used in a React Server Component.",
`\nhttps://next-auth.js.org/configuration/nextjs#unstable_getServerSession}`,
`\nhttps://next-auth.js.org/warnings#EXPERIMENTAL_API`
)
experimentalRSCWarningShown = true
}
const [req, res, options] = isRSC
? [
{
headers: ensureAvailable(headers),
cookies: ensureAvailable(nextCookies)
.getAll()
.reduce((acc, c) => ({ ...acc, [c.name]: c.value }), {}),
} as any,
{ getHeader() {}, setCookie() {}, setHeader() {} } as any,
args[0],
]
: args
options.secret = options.secret ?? process.env.NEXTAUTH_SECRET
@@ -123,7 +152,11 @@ export async function unstable_getServerSession(
cookies?.forEach((cookie) => setCookie(res, cookie))
if (body && typeof body !== "string" && Object.keys(body).length) {
if (status === 200) return body as Session
if (status === 200) {
// @ts-expect-error
if (isRSC) delete body.expires
return body as Session
}
throw new Error((body as any).message)
}
@@ -139,3 +172,15 @@ declare global {
}
}
}
function ensureAvailable(fn: () => any) {
try {
return fn()
} catch (error) {
console.error(error)
console.error(
`Could not access ${fn.name}(). If you are not in a React Server Cmponent, pass the request and response.`
)
// Cannot throw since Next.js expects DynamicServerError
}
}

View File

@@ -184,7 +184,7 @@ export type WithAuthArgs =
* [Documentation](https://next-auth.js.org/configuration/nextjs#middleware)
*/
export function withAuth(...args: WithAuthArgs) {
if (!args.length || args[0] instanceof NextRequest) {
if (!args.length || args[0] instanceof Request) {
// @ts-expect-error
return handleMiddleware(...args)
}

View File

@@ -95,7 +95,7 @@ export type SessionContextValue<R extends boolean = false> = R extends true
| { data: Session; status: "authenticated" }
| { data: null; status: "unauthenticated" | "loading" }
export const SessionContext = React.createContext<
export const SessionContext = React.createContext?.<
SessionContextValue | undefined
>(undefined)
@@ -106,6 +106,10 @@ export const SessionContext = React.createContext<
* [Documentation](https://next-auth.js.org/getting-started/client#usesession)
*/
export function useSession<R extends boolean>(options?: UseSessionOptions<R>) {
if (!SessionContext) {
throw new Error("React Context is unavailable in Server Components")
}
// @ts-expect-error Satisfy TS if branch on line below
const value: SessionContextValue<R> = React.useContext(SessionContext)
if (!value && process.env.NODE_ENV !== "production") {
@@ -322,6 +326,10 @@ export async function signOut<R extends boolean = true>(
* [Documentation](https://next-auth.js.org/getting-started/client#sessionprovider)
*/
export function SessionProvider(props: SessionProviderProps) {
if (!SessionContext) {
throw new Error("React Context is unavailable in Server Components")
}
const { children, basePath, refetchInterval, refetchWhenOffline } = props
if (basePath) __NEXTAUTH.basePath = basePath

441
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff