mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
71 Commits
next-auth@
...
next-auth@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2510f74809 | ||
|
|
27b2519b84 | ||
|
|
5f15b0704a | ||
|
|
e4573ffff5 | ||
|
|
4ce1951a2b | ||
|
|
c95531d651 | ||
|
|
654d52bb56 | ||
|
|
b72d7be9be | ||
|
|
76fcc4e70c | ||
|
|
4cacf504dd | ||
|
|
50eb23f626 | ||
|
|
d813c00b3e | ||
|
|
fc4448a85a | ||
|
|
16f781c091 | ||
|
|
ebfdaece0e | ||
|
|
64a190e549 | ||
|
|
e11f898c10 | ||
|
|
dcb11da2e2 | ||
|
|
9f900befe6 | ||
|
|
09c2a89df8 | ||
|
|
20c3fe3331 | ||
|
|
e26f500d18 | ||
|
|
494d16e54d | ||
|
|
5a8aa2e5e5 | ||
|
|
05ff6ae221 | ||
|
|
1fbc684f53 | ||
|
|
124be4fb1f | ||
|
|
3b0128c3ca | ||
|
|
36b97aafb8 | ||
|
|
175d37499b | ||
|
|
08a6835a70 | ||
|
|
448a11ff0a | ||
|
|
f39f9708bd | ||
|
|
6d98b8b33c | ||
|
|
ef7ec044c5 | ||
|
|
e89e3143d7 | ||
|
|
12f0795a0a | ||
|
|
9e0036bc73 | ||
|
|
27aa5ef09b | ||
|
|
903bd6fac9 | ||
|
|
998b7a0db4 | ||
|
|
465644f9e4 | ||
|
|
d12bd5a799 | ||
|
|
3897d47db2 | ||
|
|
e44dccc42d | ||
|
|
733a81bd3a | ||
|
|
f06f3bbc96 | ||
|
|
aea27a1fa8 | ||
|
|
bd37c55241 | ||
|
|
169a5230db | ||
|
|
f48eb0478e | ||
|
|
b25a090c17 | ||
|
|
0167e9368b | ||
|
|
dcb576f01b | ||
|
|
9417822a41 | ||
|
|
14f8f0cb58 | ||
|
|
212272a839 | ||
|
|
a8e8b7542c | ||
|
|
14cecb9b73 | ||
|
|
28bec0fbcc | ||
|
|
bc683a5b72 | ||
|
|
e7b8597f73 | ||
|
|
5c89a21bfa | ||
|
|
6e9c8b5b3c | ||
|
|
91a9e5f601 | ||
|
|
cb916f4848 | ||
|
|
8259cd4fc6 | ||
|
|
7a8c0068c4 | ||
|
|
6edb6ddaaf | ||
|
|
0711d32a00 | ||
|
|
c261af4695 |
2
.github/pr-labeler.yml
vendored
2
.github/pr-labeler.yml
vendored
@@ -54,7 +54,7 @@ upstash-redis:
|
||||
xata:
|
||||
- packages/adapter-xata/**
|
||||
|
||||
core:
|
||||
legacy:
|
||||
- packages/next-auth/src/**/*
|
||||
|
||||
style:
|
||||
|
||||
7
.github/sync.yml
vendored
7
.github/sync.yml
vendored
@@ -1,7 +0,0 @@
|
||||
# This is a legacy example pushed from the v4 branch
|
||||
nextauthjs/next-auth-example:
|
||||
- source: apps/example-nextjs
|
||||
dest: .
|
||||
deleteOrphaned: true
|
||||
- .github/FUNDING.yml
|
||||
- LICENSE
|
||||
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -32,11 +32,16 @@ jobs:
|
||||
run: pnpm install
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
- name: Run tests
|
||||
run: pnpm test
|
||||
env:
|
||||
UPSTASH_REDIS_URL: ${{ secrets.UPSTASH_REDIS_URL }}
|
||||
UPSTASH_REDIS_KEY: ${{ secrets.UPSTASH_REDIS_KEY }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
# - name: Coverage
|
||||
# uses: codecov/codecov-action@v1
|
||||
# with:
|
||||
|
||||
18
.github/workflows/sync-examples.yml
vendored
18
.github/workflows/sync-examples.yml
vendored
@@ -1,18 +0,0 @@
|
||||
name: Sync Example Repositories
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v4
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Run GitHub File Sync
|
||||
# Can update to v1 when https://github.com/BetaHuhn/repo-file-sync-action/issues/168 is resolved
|
||||
uses: BetaHuhn/repo-file-sync-action@v1.16.5
|
||||
with:
|
||||
GH_PAT: ${{ secrets.GH_PAT_CLASSIC }}
|
||||
SKIP_PR: true
|
||||
25
apps/dev/app/api/auth/[...nextauth]/route.ts
Normal file
25
apps/dev/app/api/auth/[...nextauth]/route.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import NextAuth, { type NextAuthOptions } from "next-auth"
|
||||
import GitHub from "next-auth/providers/github"
|
||||
// import { NextRequest } from "next/server"
|
||||
|
||||
export const authOptions: NextAuthOptions = {
|
||||
providers: [
|
||||
GitHub({
|
||||
clientId: process.env.GITHUB_ID as string,
|
||||
clientSecret: process.env.GITHUB_SECRET as string,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced Initialization - route handler
|
||||
*/
|
||||
// const handler = async (
|
||||
// req: NextRequest,
|
||||
// routeContext: { params: { nextauth: string[] } }
|
||||
// ): Promise<any> => {
|
||||
// return NextAuth(req, routeContext, authOptions)
|
||||
// }
|
||||
|
||||
const handler = NextAuth(authOptions)
|
||||
export { handler as GET, handler as POST }
|
||||
1
apps/dev/next-env.d.ts
vendored
1
apps/dev/next-env.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"@prisma/client": "^3",
|
||||
"@supabase/supabase-js": "^2.0.5",
|
||||
"faunadb": "^4",
|
||||
"next": "13.0.6",
|
||||
"next": "13.4.12",
|
||||
"next-auth": "workspace:*",
|
||||
"nodemailer": "^6",
|
||||
"react": "^18",
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"fake-smtp-server": "^0.8.0",
|
||||
"pg": "^8.7.3",
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
],
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react": "^18.0.37",
|
||||
"typescript": "^4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@ title: Adapters
|
||||
Visit the [authjs.dev](https://authjs.dev/reference/adapters) page for the up-to-date documentation.
|
||||
|
||||
- [Dgraph](https://authjs.dev/reference/adapter/dgraph)
|
||||
- [Drizzle](https://authjs.dev/reference/adapter/drizzle)
|
||||
- [DynamoDB](https://authjs.dev/reference/adapter/dynamodb)
|
||||
- [Fauna](https://authjs.dev/reference/adapter/fauna)
|
||||
- [Firebase](https://authjs.dev/reference/adapter/firebase)
|
||||
- [MongoDB](https://authjs.dev/reference/adapter/mongodb)
|
||||
- [Prisma](https://authjs.dev/reference/adapter/prisma)
|
||||
- [TypeORM](https://authjs.dev/reference/adapter/typeorm)
|
||||
- [kysely](https://authjs.dev/reference/adapter/kysely)
|
||||
- [MikroORM](https://authjs.dev/reference/adapter/mikro-orm)
|
||||
- [MongoDB](https://authjs.dev/reference/adapter/mongodb)
|
||||
- [neo4j](https://authjs.dev/reference/adapter/neo4j)
|
||||
- [Prisma](https://authjs.dev/reference/adapter/prisma)
|
||||
- [PouchDB](https://authjs.dev/reference/adapter/pouchdb)
|
||||
- [Sequelize](https://authjs.dev/reference/adapter/sequelize)
|
||||
- [Supabase](https://authjs.dev/reference/adapter/supabase)
|
||||
- [TypeORM](https://authjs.dev/reference/adapter/typeorm)
|
||||
- [Upstash Redis](https://authjs.dev/reference/adapter/upstash-redis)
|
||||
- [Xata](https://authjs.dev/reference/adapter/xata)
|
||||
|
||||
@@ -3,17 +3,23 @@ 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/nextjs) (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.
|
||||
|
||||
Depending on your use case, you can initialize NextAuth.js in two different ways:
|
||||
|
||||
## Simple initialization
|
||||
|
||||
In most cases, you won't need to worry about what `NextAuth.js` does, and you will get by just fine with the following initialization:
|
||||
|
||||
```ts title="/pages/api/auth/[...nextauth].js"
|
||||
```ts title="/pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
export default NextAuth({
|
||||
@@ -25,9 +31,37 @@ Here, you only need to pass your [options](/configuration/options) to `NextAuth`
|
||||
|
||||
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
|
||||
|
||||
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].js` config file is still just **a regular [API Route](https://nextjs.org/docs/api-routes/introduction)** at the end of the day.
|
||||
:::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.md)
|
||||
:::
|
||||
|
||||
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:
|
||||
|
||||
@@ -91,7 +125,7 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
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].js"
|
||||
```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"
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
# Next.js
|
||||
|
||||
## `unstable_getServerSession`
|
||||
|
||||
This method was renamed to `getServerSession`. See the documentation below.
|
||||
|
||||
## `getServerSession`
|
||||
|
||||
When calling from server-side i.e. in 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.
|
||||
:::tip
|
||||
You can create a helper function so you don't need to pass `authOptions` around:
|
||||
|
||||
Otherwise, if you only want to get the session token, see [`getToken`](/tutorials/securing-pages-and-api-routes#using-gettoken).
|
||||
```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:
|
||||
|
||||
@@ -55,7 +70,7 @@ import { authOptions } from 'pages/api/auth/[...nextauth]'
|
||||
import { getServerSession } from "next-auth/next"
|
||||
|
||||
|
||||
export async function handler(req, res) {
|
||||
export default async function handler(req, res) {
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
|
||||
if (!session) {
|
||||
@@ -69,7 +84,7 @@ export async function handler(req, res) {
|
||||
}
|
||||
```
|
||||
|
||||
### In `app/` directory:
|
||||
### In App Router:
|
||||
|
||||
You can also use `getServerSession` in Next.js' server components:
|
||||
|
||||
@@ -87,6 +102,15 @@ export default async function Page() {
|
||||
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.
|
||||
@@ -154,22 +178,27 @@ Callbacks are asynchronous functions you can use to control what happens when an
|
||||
|
||||
#### Description
|
||||
|
||||
Specify URLs to be used if you want to create custom sign in, and error pages. Pages specified will override the corresponding built-in page.
|
||||
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.
|
||||
|
||||
:::note
|
||||
This should match the `pages` configuration that's found in `[...nextauth].ts`.
|
||||
:::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
|
||||
pages: {
|
||||
signIn: '/api/auth/signin',
|
||||
error: '/api/auth/error',
|
||||
}
|
||||
import { withAuth } from "next-auth/middleware"
|
||||
|
||||
export default withAuth({
|
||||
// Matches the pages config in `[...nextauth]`
|
||||
pages: {
|
||||
signIn: '/login',
|
||||
error: '/error',
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
See the documentation for the [pages option](/configuration/pages) for more information.
|
||||
For more information, see the documentation for the [pages option](/configuration/pages).
|
||||
|
||||
---
|
||||
|
||||
@@ -179,7 +208,7 @@ See the documentation for the [pages option](/configuration/pages) for more info
|
||||
|
||||
#### Description
|
||||
|
||||
The same `secret` used in the [NextAuth.js config](/configuration/options#options).
|
||||
The same `secret` is used in the [NextAuth.js config](/configuration/options#options).
|
||||
|
||||
#### Example (default value)
|
||||
|
||||
@@ -225,7 +254,6 @@ The `middleware` function will only be invoked if the `authorized` callback retu
|
||||
|
||||
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"
|
||||
@@ -253,7 +281,7 @@ import withAuth from "next-auth/middleware"
|
||||
import { authOptions } from "pages/api/auth/[...nextauth]";
|
||||
|
||||
export default withAuth({
|
||||
jwt: { decode: authOptions.jwt },
|
||||
jwt: { decode: authOptions.jwt?.decode },
|
||||
callbacks: {
|
||||
authorized: ({ token }) => !!token,
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@ 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.
|
||||
@@ -35,10 +41,10 @@ The email provider requires a database, it cannot be used without one.
|
||||
|
||||
| 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 `email` | `"email"` | Yes |
|
||||
| server | Path or object pointing to the email server | `string` or `Object` | Yes |
|
||||
| sendVerificationRequest | Callback to execute when a verification request is sent | `(params) => Promise<undefined>` | Yes |
|
||||
| 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 |
|
||||
|
||||
@@ -18,8 +18,8 @@ See below for more detailed provider settings.
|
||||
|
||||
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.
|
||||
a. You can use `openssl rand -base64 32` or https://generate-secret.vercel.app/32 to generate a random value.
|
||||
b. You **do not** need the `NEXTAUTH_URL` environment variable in Vercel.
|
||||
- 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!
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ This error occurs when the `SessionProvider` Context has a problem fetching sess
|
||||
|
||||
#### CLIENT_FETCH_ERROR
|
||||
|
||||
If you see `CLIENT_FETCH_ERROR` make sure you have configured the `NEXTAUTH_URL` environment variable.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ export default NextAuth({
|
||||
jwt({ token, trigger, session }) {
|
||||
if (trigger === "update" && session?.name) {
|
||||
// Note, that `session` can be any arbitrary object, remember to validate it!
|
||||
token.name = session
|
||||
token.name = session.name
|
||||
}
|
||||
return token
|
||||
}
|
||||
@@ -359,7 +359,7 @@ export default async (req, res) => {
|
||||
```
|
||||
|
||||
:::note
|
||||
Unlike and `getCsrfToken()`, when calling `getProviders()` server side, you don't need to pass anything, just as calling it client side.
|
||||
Unlike `getCsrfToken()`, when calling `getProviders()` server side, you don't need to pass anything, just as calling it client side.
|
||||
:::
|
||||
|
||||
---
|
||||
@@ -519,7 +519,11 @@ where `data.url` is the validated URL you can redirect the user to without any f
|
||||
|
||||
## SessionProvider
|
||||
|
||||
Using the supplied `<SessionProvider>` allows instances of `useSession()` to share the session object across components, by using [React Context](https://reactjs.org/docs/context.html) under the hood. It also takes care of keeping the session updated and synced between tabs/windows.
|
||||
:::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"
|
||||
|
||||
@@ -26,6 +26,8 @@ If you are using TypeScript, NextAuth.js comes with its types definitions within
|
||||
|
||||
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"
|
||||
@@ -74,6 +76,7 @@ Instances of `useSession` will then have access to the session data and status.
|
||||
|
||||
:::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/building-your-application/routing/pages-and-layouts).
|
||||
:::
|
||||
|
||||
### Frontend - Add React Hook
|
||||
|
||||
@@ -6,7 +6,7 @@ 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-typescript-example
|
||||
https://github.com/nextauthjs/next-auth-example
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -351,8 +351,8 @@ User {
|
||||
id
|
||||
name
|
||||
email
|
||||
- emailVerified
|
||||
+ email_verified
|
||||
+ emailVerified
|
||||
- email_verified
|
||||
image
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
@@ -3,6 +3,17 @@ 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/reference/adapters).
|
||||
:::
|
||||
|
||||
## Documentation
|
||||
|
||||
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
|
||||
@@ -20,7 +31,7 @@ https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-regis
|
||||
- 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, use `https://yourapplication.com/api/auth/callback/azure-ad` or for development `http://localhost:3000/api/auth/callback/azure-ad`.
|
||||
- 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
|
||||
@@ -37,6 +48,10 @@ 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.
|
||||
:::
|
||||
|
||||
@@ -125,7 +125,7 @@ providers: [
|
||||
return user
|
||||
},
|
||||
credentials: {
|
||||
email: { label: "Username", type: "text ", placeholder: "jsmith" },
|
||||
username: { label: "Username", type: "text ", placeholder: "jsmith" },
|
||||
"2fa-key": { label: "2FA Key" },
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -32,11 +32,19 @@ 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/providers/email-http) 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.
|
||||
You can either use a connection string or a `nodemailer` configuration object or transport.
|
||||
|
||||
2.1 **Using a connection string**
|
||||
|
||||
@@ -252,3 +260,27 @@ By default, NextAuth.js will normalize the email address. It treats values as ca
|
||||
:::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";
|
||||
}
|
||||
},
|
||||
...
|
||||
```
|
||||
|
||||
@@ -3,6 +3,10 @@ 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://authjs.dev/reference/adapters).
|
||||
:::
|
||||
|
||||
## Documentation
|
||||
|
||||
https://docs.gitlab.com/ee/api/oauth2.html
|
||||
|
||||
@@ -15,7 +15,7 @@ https://developers.kakao.com/docs/latest/en/kakaologin/common
|
||||
|
||||
The **Kakao Provider** comes with a set of default options:
|
||||
|
||||
- [Kakao Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/kakao.js)
|
||||
- [Kakao Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/kakao.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ https://help.salesforce.com/articleView?id=remoteaccess_authenticate.htm&type=5
|
||||
|
||||
The **Salesforce Provider** comes with a set of default options:
|
||||
|
||||
- [Salesforce Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/salesforce.js)
|
||||
- [Salesforce Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/salesforce.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ https://vk.com/apps?act=manage
|
||||
|
||||
The **VK Provider** comes with a set of default options:
|
||||
|
||||
- [VK Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/vk.js)
|
||||
- [VK Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/vk.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
@@ -34,7 +34,7 @@ providers: [
|
||||
```
|
||||
|
||||
:::note
|
||||
By default the provider uses `5.126` version of the API. See https://vk.com/dev/versions for more info.
|
||||
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:
|
||||
@@ -42,7 +42,7 @@ If you want to use a different version, you can pass it to provider's options ob
|
||||
```js
|
||||
// pages/api/auth/[...nextauth].js
|
||||
|
||||
const apiVersion = "5.126"
|
||||
const apiVersion = "5.131"
|
||||
...
|
||||
providers: [
|
||||
VkProvider({
|
||||
|
||||
@@ -3,6 +3,10 @@ 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://authjs.dev/reference/adapters).
|
||||
:::
|
||||
|
||||
## Documentation
|
||||
|
||||
https://www.zoho.com/accounts/protocol/oauth/web-server-applications.html
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"name": "next-auth-docs",
|
||||
"version": "0.2.0",
|
||||
"scripts": {
|
||||
"start": "npm run generate-providers && docusaurus start --no-open --port 8000",
|
||||
"start": "npm run generate-providers && docusaurus start --no-open",
|
||||
"dev": "npm run start",
|
||||
"build": "npm run generate-providers && docusaurus build",
|
||||
"docusaurus": "docusaurus",
|
||||
|
||||
@@ -118,7 +118,7 @@ Once you have saved your schema, use the Prisma CLI to generate the Prisma Clien
|
||||
npx prisma generate
|
||||
```
|
||||
|
||||
To configure you database to use the new schema (i.e. create tables and columns) use the `prisma migrate` command:
|
||||
To configure your database to use the new schema (i.e. create tables and columns) use the `prisma migrate` command:
|
||||
|
||||
```
|
||||
npx prisma migrate dev
|
||||
|
||||
@@ -121,7 +121,7 @@ The `RefreshAccessTokenError` error that is caught in the `refreshAccessToken()`
|
||||
|
||||
We can handle this functionality as a side effect:
|
||||
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
```js title="pages/index.js"
|
||||
import { signIn, useSession } from "next-auth/client";
|
||||
import { useEffect } from "react";
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ This is a monorepo containing the following packages / projects:
|
||||
## Getting Started
|
||||
|
||||
```
|
||||
npm install --save next-auth
|
||||
npm install next-auth
|
||||
```
|
||||
|
||||
The easiest way to continue getting started, is to follow the [getting started](https://next-auth.js.org/getting-started/example) section in our docs.
|
||||
@@ -168,7 +168,7 @@ export default function App({
|
||||
|
||||
## Security
|
||||
|
||||
If you think you have found a vulnerability (or not sure) in NextAuth.js or any of the related packages (i.e. Adapters), we ask you to have a read of our [Security Policy](https://github.com/nextauthjs/next-auth/blob/main/SECURITY.md) to reach out responsibly. Please do not open Pull Requests/Issues/Discussions before consulting with us.
|
||||
If you think you have found a vulnerability (or not sure) in NextAuth.js or any of the related packages (i.e. Adapters), we ask you to have a read of our [Security Policy](https://github.com/nextauthjs/next-auth/security/policy) to reach out responsibly. Please do not open Pull Requests/Issues/Discussions before consulting with us.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
@@ -204,8 +204,8 @@ We're happy to announce we've recently created an [OpenCollective](https://openc
|
||||
<sub>🥉 Bronze Financial Sponsor</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://clerk.dev" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/49538330?s=200&v=4" alt="Prisma Logo" />
|
||||
<a href="https://clerk.com" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/49538330?s=200&v=4" alt="Clerk Logo" />
|
||||
</a><br />
|
||||
<div>Clerk</div><br />
|
||||
<sub>🥉 Bronze Financial Sponsor</sub>
|
||||
@@ -247,7 +247,7 @@ We're happy to announce we've recently created an [OpenCollective](https://openc
|
||||
## Contributing
|
||||
|
||||
We're open to all community contributions! If you'd like to contribute in any way, please first read
|
||||
our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
|
||||
our [Contributing Guide](https://github.com/nextauthjs/.github/blob/main/CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-auth",
|
||||
"version": "4.21.1",
|
||||
"version": "4.23.2",
|
||||
"description": "Authentication for Next.js",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
@@ -9,7 +9,7 @@
|
||||
"Balázs Orbán <info@balazsorban.com>",
|
||||
"Nico Domino <yo@ndo.dev>",
|
||||
"Lluis Agusti <hi@llu.lu>",
|
||||
"Thang Huu Vu <thvu@hey.com>"
|
||||
"Thang Huu Vu <hi@thvu.dev>"
|
||||
],
|
||||
"main": "index.js",
|
||||
"module": "index.js",
|
||||
@@ -27,19 +27,42 @@
|
||||
"nextauth"
|
||||
],
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./jwt": "./jwt/index.js",
|
||||
"./react": "./react/index.js",
|
||||
"./core": "./core/index.js",
|
||||
"./next": "./next/index.js",
|
||||
"./middleware": "./middleware.js",
|
||||
"./client/_utils": "./client/_utils.js",
|
||||
"./providers/*": "./providers/*.js"
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./adapters": {
|
||||
"types": "./adapters.d.ts"
|
||||
},
|
||||
"./jwt": {
|
||||
"types": "./jwt/index.d.ts",
|
||||
"default": "./jwt/index.js"
|
||||
},
|
||||
"./react": {
|
||||
"types": "./react/index.d.ts",
|
||||
"default": "./react/index.js"
|
||||
},
|
||||
"./next": {
|
||||
"types": "./next/index.d.ts",
|
||||
"default": "./next/index.js"
|
||||
},
|
||||
"./middleware": {
|
||||
"types": "./middleware.d.ts",
|
||||
"default": "./middleware.js"
|
||||
},
|
||||
"./client/_utils": {
|
||||
"types": "./client/_utils.d.ts",
|
||||
"default": "./client/_utils.js"
|
||||
},
|
||||
"./providers/*": {
|
||||
"types": "./providers/*.d.ts",
|
||||
"default": "./providers/*.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm clean && pnpm build:js && pnpm build:css",
|
||||
"build:js": "pnpm clean && pnpm generate-providers && pnpm tsc --project tsconfig.json && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
|
||||
"clean": "rm -rf coverage client css utils providers core jwt react next index.d.ts index.js adapters.d.ts middleware.d.ts middleware.js",
|
||||
"clean": "rm -rf coverage client css utils providers core jwt react next lib ./*.js ./*.ts*",
|
||||
"build:css": "postcss --config config/postcss.config.js src/**/*.css --base src --dir . && node config/wrap-css.js",
|
||||
"dev": "pnpm clean && pnpm generate-providers && concurrently \"pnpm watch:css\" \"pnpm watch:ts\"",
|
||||
"watch:ts": "pnpm tsc --project tsconfig.dev.json",
|
||||
@@ -107,7 +130,7 @@
|
||||
"@types/node": "^17.0.42",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/oauth": "^0.9.1",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react": "18.0.37",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"babel-plugin-jsx-pragmatic": "^1.0.2",
|
||||
@@ -118,7 +141,7 @@
|
||||
"jest-environment-jsdom": "^28.1.1",
|
||||
"jest-watch-typeahead": "^1.1.0",
|
||||
"msw": "^0.42.3",
|
||||
"next": "13.0.6",
|
||||
"next": "13.3.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-cli": "^9.1.0",
|
||||
"postcss-nested": "^5.0.6",
|
||||
|
||||
@@ -59,37 +59,22 @@ export interface VerificationToken {
|
||||
* [Adapters Overview](https://next-auth.js.org/adapters/overview) |
|
||||
* [Create a custom adapter](https://next-auth.js.org/tutorials/creating-a-database-adapter)
|
||||
*/
|
||||
export type Adapter<WithVerificationToken = boolean> = DefaultAdapter &
|
||||
(WithVerificationToken extends true
|
||||
? {
|
||||
createVerificationToken: (
|
||||
verificationToken: VerificationToken
|
||||
) => Awaitable<VerificationToken | null | undefined>
|
||||
/**
|
||||
* Return verification token from the database
|
||||
* and delete it so it cannot be used again.
|
||||
*/
|
||||
useVerificationToken: (params: {
|
||||
identifier: string
|
||||
token: string
|
||||
}) => Awaitable<VerificationToken | null>
|
||||
}
|
||||
: {})
|
||||
|
||||
export interface DefaultAdapter {
|
||||
createUser: (user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>
|
||||
getUser: (id: string) => Awaitable<AdapterUser | null>
|
||||
getUserByEmail: (email: string) => Awaitable<AdapterUser | null>
|
||||
export interface Adapter {
|
||||
createUser?: (user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>
|
||||
getUser?: (id: string) => Awaitable<AdapterUser | null>
|
||||
getUserByEmail?: (email: string) => Awaitable<AdapterUser | null>
|
||||
/** Using the provider id and the id of the user for a specific account, get the user. */
|
||||
getUserByAccount: (
|
||||
getUserByAccount?: (
|
||||
providerAccountId: Pick<AdapterAccount, "provider" | "providerAccountId">
|
||||
) => Awaitable<AdapterUser | null>
|
||||
updateUser: (user: Partial<AdapterUser> & Pick<AdapterUser, 'id'>) => Awaitable<AdapterUser>
|
||||
updateUser?: (
|
||||
user: Partial<AdapterUser> & Pick<AdapterUser, "id">
|
||||
) => Awaitable<AdapterUser>
|
||||
/** @todo Implement */
|
||||
deleteUser?: (
|
||||
userId: string
|
||||
) => Promise<void> | Awaitable<AdapterUser | null | undefined>
|
||||
linkAccount: (
|
||||
linkAccount?: (
|
||||
account: AdapterAccount
|
||||
) => Promise<void> | Awaitable<AdapterAccount | null | undefined>
|
||||
/** @todo Implement */
|
||||
@@ -97,15 +82,15 @@ export interface DefaultAdapter {
|
||||
providerAccountId: Pick<AdapterAccount, "provider" | "providerAccountId">
|
||||
) => Promise<void> | Awaitable<AdapterAccount | undefined>
|
||||
/** Creates a session for the user and returns it. */
|
||||
createSession: (session: {
|
||||
createSession?: (session: {
|
||||
sessionToken: string
|
||||
userId: string
|
||||
expires: Date
|
||||
}) => Awaitable<AdapterSession>
|
||||
getSessionAndUser: (
|
||||
getSessionAndUser?: (
|
||||
sessionToken: string
|
||||
) => Awaitable<{ session: AdapterSession; user: AdapterUser } | null>
|
||||
updateSession: (
|
||||
updateSession?: (
|
||||
session: Partial<AdapterSession> & Pick<AdapterSession, "sessionToken">
|
||||
) => Awaitable<AdapterSession | null | undefined>
|
||||
/**
|
||||
@@ -113,7 +98,7 @@ export interface DefaultAdapter {
|
||||
* It is preferred that this method also returns the session
|
||||
* that is being deleted for logging purposes.
|
||||
*/
|
||||
deleteSession: (
|
||||
deleteSession?: (
|
||||
sessionToken: string
|
||||
) => Promise<void> | Awaitable<AdapterSession | null | undefined>
|
||||
createVerificationToken?: (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { EventCallbacks, LoggerInstance } from ".."
|
||||
import type { EventCallbacks, InternalOptions, LoggerInstance } from ".."
|
||||
|
||||
/**
|
||||
* Same as the default `Error`, but it is JSON serializable.
|
||||
@@ -106,7 +106,7 @@ export function eventsErrorHandler(
|
||||
export function adapterErrorHandler<TAdapter>(
|
||||
adapter: TAdapter | undefined,
|
||||
logger: LoggerInstance
|
||||
): TAdapter | undefined {
|
||||
): InternalOptions["adapter"] | undefined {
|
||||
if (!adapter) return
|
||||
|
||||
return Object.keys(adapter).reduce<any>((acc, name) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import logger, { setLogger } from "../utils/logger"
|
||||
import { detectHost } from "../utils/detect-host"
|
||||
import { detectOrigin } from "../utils/detect-origin"
|
||||
import * as routes from "./routes"
|
||||
import renderPage from "./pages"
|
||||
import { init } from "./init"
|
||||
@@ -13,7 +13,7 @@ import { parse as parseCookie } from "cookie"
|
||||
|
||||
export interface RequestInternal {
|
||||
/** @default "http://localhost:3000" */
|
||||
host?: string
|
||||
origin?: string
|
||||
method?: string
|
||||
cookies?: Partial<Record<string, string>>
|
||||
headers?: Record<string, any>
|
||||
@@ -70,10 +70,18 @@ async function toInternalRequest(
|
||||
cookies: parseCookie(req.headers.get("cookie") ?? ""),
|
||||
providerId: nextauth[1],
|
||||
error: url.searchParams.get("error") ?? nextauth[1],
|
||||
host: detectHost(headers["x-forwarded-host"] ?? headers.host),
|
||||
origin: detectOrigin(
|
||||
headers["x-forwarded-host"] ?? headers.host,
|
||||
headers["x-forwarded-proto"]
|
||||
),
|
||||
query,
|
||||
}
|
||||
}
|
||||
|
||||
const { headers } = req
|
||||
const host = headers?.["x-forwarded-host"] ?? headers?.host
|
||||
req.origin = detectOrigin(host, headers?.["x-forwarded-proto"])
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
@@ -132,7 +140,7 @@ export async function AuthHandler<
|
||||
authOptions,
|
||||
action,
|
||||
providerId,
|
||||
host: req.host,
|
||||
origin: req.origin,
|
||||
callbackUrl: req.body?.callbackUrl ?? req.query?.callbackUrl,
|
||||
csrfToken: req.body?.csrfToken,
|
||||
cookies: req.cookies,
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { InternalOptions } from "./types"
|
||||
import parseUrl from "../utils/parse-url"
|
||||
|
||||
interface InitParams {
|
||||
host?: string
|
||||
origin?: string
|
||||
authOptions: AuthOptions
|
||||
providerId?: string
|
||||
action: InternalOptions["action"]
|
||||
@@ -33,7 +33,7 @@ export async function init({
|
||||
authOptions,
|
||||
providerId,
|
||||
action,
|
||||
host,
|
||||
origin,
|
||||
cookies: reqCookies,
|
||||
callbackUrl: reqCallbackUrl,
|
||||
csrfToken: reqCsrfToken,
|
||||
@@ -42,7 +42,7 @@ export async function init({
|
||||
options: InternalOptions
|
||||
cookies: cookie.Cookie[]
|
||||
}> {
|
||||
const url = parseUrl(host)
|
||||
const url = parseUrl(origin)
|
||||
|
||||
const secret = createSecret({ authOptions, url })
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ export function assertConfig(params: {
|
||||
const warnings: WarningCode[] = []
|
||||
|
||||
if (!warned) {
|
||||
if (!req.host) warnings.push("NEXTAUTH_URL")
|
||||
if (!req.origin) warnings.push("NEXTAUTH_URL")
|
||||
|
||||
// TODO: Make this throw an error in next major. This will also get rid of `NODE_ENV`
|
||||
if (!options.secret && process.env.NODE_ENV !== "production")
|
||||
@@ -70,7 +70,7 @@ export function assertConfig(params: {
|
||||
|
||||
const callbackUrlParam = req.query?.callbackUrl as string | undefined
|
||||
|
||||
const url = parseUrl(req.host)
|
||||
const url = parseUrl(req.origin)
|
||||
|
||||
if (callbackUrlParam && !isValidHttpUrl(callbackUrlParam, url.base)) {
|
||||
return new InvalidCallbackUrl(
|
||||
|
||||
@@ -114,7 +114,7 @@ export function defaultCookies(useSecureCookies: boolean): CookiesOptions {
|
||||
path: "/",
|
||||
secure: useSecureCookies,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,8 +161,21 @@ export class SessionStore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The JWT Session or database Session ID
|
||||
* constructed from the cookie chunks.
|
||||
*/
|
||||
get value() {
|
||||
return Object.values(this.#chunks)?.join("")
|
||||
// Sort the chunks by their keys before joining
|
||||
const sortedKeys = Object.keys(this.#chunks).sort((a, b) => {
|
||||
const aSuffix = parseInt(a.split(".").pop() ?? "0")
|
||||
const bSuffix = parseInt(b.split(".").pop() ?? "0")
|
||||
|
||||
return aSuffix - bSuffix
|
||||
})
|
||||
|
||||
// Use the sorted keys to join the chunks in the correct order
|
||||
return sortedKeys.map((key) => this.#chunks[key]).join("")
|
||||
}
|
||||
|
||||
/** Given a cookie, return a list of cookies, chunked to fit the allowed cookie size. */
|
||||
|
||||
@@ -12,6 +12,7 @@ export default async function getAdapterUserFromEmail({
|
||||
email: string
|
||||
adapter: InternalOptions<"email">["adapter"]
|
||||
}): Promise<AdapterUser> {
|
||||
// @ts-expect-error -- adapter is checked to be defined in `init`
|
||||
const { getUserByEmail } = adapter
|
||||
const adapterUser = email ? await getUserByEmail(email) : null
|
||||
if (adapterUser) return adapterUser
|
||||
|
||||
@@ -36,7 +36,8 @@ export default async function email(
|
||||
theme,
|
||||
}),
|
||||
// Save in database
|
||||
adapter.createVerificationToken({
|
||||
// @ts-expect-error -- adapter is checked to be defined in `init`
|
||||
adapter.createVerificationToken?.({
|
||||
identifier,
|
||||
token: hashToken(token, options),
|
||||
expires,
|
||||
|
||||
@@ -220,7 +220,6 @@ export default async function callback(params: {
|
||||
|
||||
const profile = await getAdapterUserFromEmail({
|
||||
email: identifier,
|
||||
// @ts-expect-error -- Verified in `assertConfig`. adapter: Adapter<true>
|
||||
adapter,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { fromDate } from "../lib/utils"
|
||||
|
||||
import type { Adapter } from "../../adapters"
|
||||
import type { InternalOptions } from "../types"
|
||||
import type { ResponseInternal } from ".."
|
||||
import type { Session } from "../.."
|
||||
@@ -98,8 +97,9 @@ export default async function session(
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// @ts-expect-error -- adapter is checked to be defined in `init`
|
||||
const { getSessionAndUser, deleteSession, updateSession } =
|
||||
adapter as Adapter
|
||||
adapter
|
||||
let userAndSession = await getSessionAndUser(sessionToken)
|
||||
|
||||
// If session has expired, clean up the database
|
||||
|
||||
@@ -57,7 +57,6 @@ export default async function signin(params: {
|
||||
|
||||
const user = await getAdapterUserFromEmail({
|
||||
email,
|
||||
// @ts-expect-error -- Verified in `assertConfig`. adapter: Adapter<true>
|
||||
adapter: options.adapter,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Adapter } from "../../adapters"
|
||||
import type { InternalOptions } from "../types"
|
||||
import type { ResponseInternal } from ".."
|
||||
import type { SessionStore } from "../lib/cookie"
|
||||
@@ -28,7 +27,8 @@ export default async function signout(params: {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const session = await (adapter as Adapter).deleteSession(sessionToken)
|
||||
// @ts-expect-error -- adapter is checked to be defined in `init`
|
||||
const session = await adapter.deleteSession(sessionToken)
|
||||
// Dispatch signout event
|
||||
// @ts-expect-error
|
||||
await events.signOut?.({ session })
|
||||
|
||||
@@ -52,8 +52,8 @@ export interface AuthOptions {
|
||||
*/
|
||||
secret?: string
|
||||
/**
|
||||
* Configure your session like if you want to use JWT or a database,
|
||||
* how long until an idle session expires, or to throttle write operations in case you are using a database.
|
||||
* Configure your session settings, such as determining whether to use JWT or a database,
|
||||
* setting the idle session expiration duration, or implementing write operation throttling for database usage.
|
||||
* * **Default value**: See the documentation page
|
||||
* * **Required**: No
|
||||
*
|
||||
@@ -580,14 +580,15 @@ export type AuthAction =
|
||||
| "error"
|
||||
| "_log"
|
||||
|
||||
type NonNullableFields<T> = {
|
||||
[P in keyof T]-?: NonNullable<T[P]>
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface InternalOptions<
|
||||
TProviderType = ProviderType,
|
||||
WithVerificationToken = TProviderType extends "email" ? true : false
|
||||
> {
|
||||
export interface InternalOptions<TProviderType = ProviderType> {
|
||||
providers: InternalProvider[]
|
||||
/**
|
||||
* Parsed from `NEXTAUTH_URL` or `x-forwarded-host` on Vercel.
|
||||
* Parsed from `NEXTAUTH_URL` or `x-forwarded-host` and `x-forwarded-proto` if the host is trusted.
|
||||
* @default "http://localhost:3000/api/auth"
|
||||
*/
|
||||
url: InternalUrl
|
||||
@@ -603,9 +604,7 @@ export interface InternalOptions<
|
||||
pages: Partial<PagesOptions>
|
||||
jwt: JWTOptions
|
||||
events: Partial<EventCallbacks>
|
||||
adapter: WithVerificationToken extends true
|
||||
? Adapter<WithVerificationToken>
|
||||
: Adapter<WithVerificationToken> | undefined
|
||||
adapter?: NonNullableFields<Adapter>
|
||||
callbacks: CallbacksOptions
|
||||
cookies: CookiesOptions
|
||||
callbackUrl: string
|
||||
|
||||
@@ -21,7 +21,7 @@ export interface JWTEncodeParams {
|
||||
secret: string | Buffer
|
||||
/**
|
||||
* The maximum age of the NextAuth.js issued JWT in seconds.
|
||||
* @default 30 * 24 * 30 * 60 // 30 days
|
||||
* @default 30 * 24 * 60 * 60 // 30 days
|
||||
*/
|
||||
maxAge?: number
|
||||
}
|
||||
@@ -36,13 +36,13 @@ export interface JWTDecodeParams {
|
||||
export interface JWTOptions {
|
||||
/**
|
||||
* The secret used to encode/decode the NextAuth.js issued JWT.
|
||||
* @deprecated Set the `NEXTAUTH_SECRET` environment vairable or
|
||||
* @deprecated Set the `NEXTAUTH_SECRET` environment variable or
|
||||
* use the top-level `secret` option instead
|
||||
*/
|
||||
secret: string
|
||||
/**
|
||||
* The maximum age of the NextAuth.js issued JWT in seconds.
|
||||
* @default 30 * 24 * 30 * 60 // 30 days
|
||||
* @default 30 * 24 * 60 * 60 // 30 days
|
||||
*/
|
||||
maxAge: number
|
||||
/** Override this method to control the NextAuth.js issued JWT encoding. */
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { AuthHandler } from "../core"
|
||||
import { detectHost } from "../utils/detect-host"
|
||||
import { setCookie } from "./utils"
|
||||
import { setCookie, getBody, toResponse } from "./utils"
|
||||
|
||||
import type {
|
||||
GetServerSidePropsContext,
|
||||
NextApiRequest,
|
||||
NextApiResponse,
|
||||
} from "next"
|
||||
import { type NextRequest } from "next/server"
|
||||
import type { AuthOptions, Session } from ".."
|
||||
import type {
|
||||
CallbacksOptions,
|
||||
@@ -15,19 +15,21 @@ import type {
|
||||
NextAuthResponse,
|
||||
} from "../core/types"
|
||||
|
||||
async function NextAuthHandler(
|
||||
interface RouteHandlerContext {
|
||||
params: { nextauth: string[] }
|
||||
}
|
||||
|
||||
async function NextAuthApiHandler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse,
|
||||
options: AuthOptions
|
||||
) {
|
||||
const { nextauth, ...query } = req.query
|
||||
|
||||
options.secret =
|
||||
options.secret ?? options.jwt?.secret ?? process.env.NEXTAUTH_SECRET
|
||||
options.secret ??= options.jwt?.secret ?? process.env.NEXTAUTH_SECRET
|
||||
|
||||
const handler = await AuthHandler({
|
||||
req: {
|
||||
host: detectHost(req.headers["x-forwarded-host"]),
|
||||
body: req.body,
|
||||
query,
|
||||
cookies: req.cookies,
|
||||
@@ -53,7 +55,8 @@ async function NextAuthHandler(
|
||||
// Could chain. .end() when lowest target is Node 14
|
||||
// https://github.com/nodejs/node/issues/33148
|
||||
res.status(302).setHeader("Location", handler.redirect)
|
||||
return res.end()
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
return res.json({ url: handler.redirect })
|
||||
}
|
||||
@@ -61,6 +64,51 @@ async function NextAuthHandler(
|
||||
return res.send(handler.body)
|
||||
}
|
||||
|
||||
// @see https://beta.nextjs.org/docs/routing/route-handlers
|
||||
async function NextAuthRouteHandler(
|
||||
req: NextRequest,
|
||||
context: RouteHandlerContext,
|
||||
options: AuthOptions
|
||||
) {
|
||||
options.secret ??= process.env.NEXTAUTH_SECRET
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { headers, cookies } = require("next/headers")
|
||||
const nextauth = context.params?.nextauth
|
||||
const query = Object.fromEntries(req.nextUrl.searchParams)
|
||||
const body = await getBody(req)
|
||||
const internalResponse = await AuthHandler({
|
||||
req: {
|
||||
body,
|
||||
query,
|
||||
cookies: Object.fromEntries(
|
||||
cookies()
|
||||
.getAll()
|
||||
.map((c) => [c.name, c.value])
|
||||
),
|
||||
headers: Object.fromEntries(headers() as Headers),
|
||||
method: req.method,
|
||||
action: nextauth?.[0] as AuthAction,
|
||||
providerId: nextauth?.[1],
|
||||
error: query.error ?? nextauth?.[1],
|
||||
},
|
||||
options,
|
||||
})
|
||||
|
||||
const response = toResponse(internalResponse)
|
||||
const redirect = response.headers.get("Location")
|
||||
if (body?.json === "true" && redirect) {
|
||||
response.headers.delete("Location")
|
||||
response.headers.set("Content-Type", "application/json")
|
||||
return new Response(JSON.stringify({ url: redirect }), {
|
||||
status: internalResponse.status,
|
||||
headers: response.headers,
|
||||
})
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
function NextAuth(options: AuthOptions): any
|
||||
function NextAuth(
|
||||
req: NextApiRequest,
|
||||
@@ -68,22 +116,50 @@ function NextAuth(
|
||||
options: AuthOptions
|
||||
): any
|
||||
|
||||
function NextAuth(
|
||||
req: NextRequest,
|
||||
res: RouteHandlerContext,
|
||||
options: AuthOptions
|
||||
): any
|
||||
|
||||
/** The main entry point to next-auth */
|
||||
function NextAuth(
|
||||
...args: [AuthOptions] | [NextApiRequest, NextApiResponse, AuthOptions]
|
||||
...args:
|
||||
| [AuthOptions]
|
||||
| Parameters<typeof NextAuthRouteHandler>
|
||||
| Parameters<typeof NextAuthApiHandler>
|
||||
) {
|
||||
if (args.length === 1) {
|
||||
return async (req: NextAuthRequest, res: NextAuthResponse) =>
|
||||
await NextAuthHandler(req, res, args[0])
|
||||
return async (
|
||||
req: NextAuthRequest | NextRequest,
|
||||
res: NextAuthResponse | RouteHandlerContext
|
||||
) => {
|
||||
if ((res as any)?.params) {
|
||||
return await NextAuthRouteHandler(
|
||||
req as NextRequest,
|
||||
res as RouteHandlerContext,
|
||||
args[0]
|
||||
)
|
||||
}
|
||||
return await NextAuthApiHandler(
|
||||
req as NextApiRequest,
|
||||
res as NextApiResponse,
|
||||
args[0]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return NextAuthHandler(args[0], args[1], args[2])
|
||||
if ((args[1] as any)?.params) {
|
||||
return NextAuthRouteHandler(
|
||||
...(args as Parameters<typeof NextAuthRouteHandler>)
|
||||
)
|
||||
}
|
||||
|
||||
return NextAuthApiHandler(...(args as Parameters<typeof NextAuthApiHandler>))
|
||||
}
|
||||
|
||||
export default NextAuth
|
||||
|
||||
let experimentalRSCWarningShown = false
|
||||
|
||||
type GetServerSessionOptions = Partial<Omit<AuthOptions, "callbacks">> & {
|
||||
callbacks?: Omit<AuthOptions["callbacks"], "session"> & {
|
||||
session?: (...args: Parameters<CallbacksOptions["session"]>) => any
|
||||
@@ -103,19 +179,6 @@ export async function getServerSession<
|
||||
: Session
|
||||
>(...args: GetServerSessionParams<O>): Promise<R | null> {
|
||||
const isRSC = args.length === 0 || args.length === 1
|
||||
if (
|
||||
!experimentalRSCWarningShown &&
|
||||
isRSC &&
|
||||
process.env.NODE_ENV !== "production"
|
||||
) {
|
||||
console.warn(
|
||||
"[next-auth][warn][EXPERIMENTAL_API]",
|
||||
"\n`getServerSession` is used in a React Server Component.",
|
||||
`\nhttps://next-auth.js.org/configuration/nextjs#getServerSession}`,
|
||||
`\nhttps://next-auth.js.org/warnings#EXPERIMENTAL_API`
|
||||
)
|
||||
experimentalRSCWarningShown = true
|
||||
}
|
||||
|
||||
let req, res, options: AuthOptions
|
||||
if (isRSC) {
|
||||
@@ -138,12 +201,11 @@ export async function getServerSession<
|
||||
options = Object.assign({}, args[2], { providers: [] })
|
||||
}
|
||||
|
||||
options.secret = options.secret ?? process.env.NEXTAUTH_SECRET
|
||||
options.secret ??= process.env.NEXTAUTH_SECRET
|
||||
|
||||
const session = await AuthHandler<Session | {} | string>({
|
||||
options,
|
||||
req: {
|
||||
host: detectHost(req.headers["x-forwarded-host"]),
|
||||
action: "session",
|
||||
method: "GET",
|
||||
cookies: req.cookies,
|
||||
|
||||
@@ -186,7 +186,39 @@ export type WithAuthArgs =
|
||||
* ---
|
||||
* [Documentation](https://next-auth.js.org/configuration/nextjs#middleware)
|
||||
*/
|
||||
export function withAuth(...args: WithAuthArgs) {
|
||||
|
||||
export function withAuth(): ReturnType<NextMiddlewareWithAuth>
|
||||
|
||||
export function withAuth(
|
||||
req: NextRequestWithAuth
|
||||
): ReturnType<NextMiddlewareWithAuth>
|
||||
|
||||
export function withAuth(
|
||||
req: NextRequestWithAuth,
|
||||
event: NextFetchEvent
|
||||
): ReturnType<NextMiddlewareWithAuth>
|
||||
|
||||
export function withAuth(
|
||||
req: NextRequestWithAuth,
|
||||
options: NextAuthMiddlewareOptions
|
||||
): ReturnType<NextMiddlewareWithAuth>
|
||||
|
||||
export function withAuth(
|
||||
middleware: NextMiddlewareWithAuth,
|
||||
options: NextAuthMiddlewareOptions
|
||||
): NextMiddlewareWithAuth
|
||||
|
||||
export function withAuth(
|
||||
middleware: NextMiddlewareWithAuth
|
||||
): NextMiddlewareWithAuth
|
||||
|
||||
export function withAuth(
|
||||
options: NextAuthMiddlewareOptions
|
||||
): NextMiddlewareWithAuth
|
||||
|
||||
export function withAuth(
|
||||
...args: WithAuthArgs
|
||||
): ReturnType<NextMiddlewareWithAuth> | NextMiddlewareWithAuth {
|
||||
if (!args.length || args[0] instanceof Request) {
|
||||
// @ts-expect-error
|
||||
return handleMiddleware(...args)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { serialize } from "cookie"
|
||||
import { Cookie } from "../core/lib/cookie"
|
||||
import { type ResponseInternal } from "../core"
|
||||
|
||||
export function setCookie(res, cookie: Cookie) {
|
||||
// Preserve any existing cookies that have already been set in the same session
|
||||
@@ -13,3 +14,47 @@ export function setCookie(res, cookie: Cookie) {
|
||||
setCookieHeader.push(cookieHeader)
|
||||
res.setHeader("Set-Cookie", setCookieHeader)
|
||||
}
|
||||
|
||||
export async function getBody(
|
||||
req: Request
|
||||
): Promise<Record<string, any> | undefined> {
|
||||
if (!("body" in req) || !req.body || req.method !== "POST") return
|
||||
|
||||
const contentType = req.headers.get("content-type")
|
||||
if (contentType?.includes("application/json")) {
|
||||
return await req.json()
|
||||
} else if (contentType?.includes("application/x-www-form-urlencoded")) {
|
||||
const params = new URLSearchParams(await req.text())
|
||||
return Object.fromEntries(params)
|
||||
}
|
||||
}
|
||||
|
||||
export function toResponse(res: ResponseInternal): Response {
|
||||
const headers = new Headers(
|
||||
res.headers?.reduce((acc, { key, value }) => {
|
||||
acc[key] = value
|
||||
return acc
|
||||
}, {})
|
||||
)
|
||||
|
||||
res.cookies?.forEach((cookie) => {
|
||||
const { name, value, options } = cookie
|
||||
const cookieHeader = serialize(name, value, options)
|
||||
if (headers.has("Set-Cookie")) headers.append("Set-Cookie", cookieHeader)
|
||||
else headers.set("Set-Cookie", cookieHeader)
|
||||
})
|
||||
|
||||
let body = res.body
|
||||
|
||||
if (headers.get("content-type") === "application/json")
|
||||
body = JSON.stringify(res.body)
|
||||
else if (headers.get("content-type") === "application/x-www-form-urlencoded")
|
||||
body = new URLSearchParams(res.body).toString()
|
||||
|
||||
const status = res.redirect ? 302 : res.status ?? 200
|
||||
const response = new Response(body, { headers, status })
|
||||
|
||||
if (res.redirect) response.headers.set("Location", res.redirect)
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import { createTransport } from "nodemailer"
|
||||
|
||||
import type { CommonProviderOptions } from "."
|
||||
import type { Options as SMTPTransportOptions } from "nodemailer/lib/smtp-transport"
|
||||
import { Transport, TransportOptions, createTransport } from "nodemailer"
|
||||
import * as JSONTransport from "nodemailer/lib/json-transport.js"
|
||||
import * as SendmailTransport from "nodemailer/lib/sendmail-transport/index.js"
|
||||
import * as SESTransport from "nodemailer/lib/ses-transport.js"
|
||||
import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js"
|
||||
import * as SMTPTransport from "nodemailer/lib/smtp-transport.js"
|
||||
import * as StreamTransport from "nodemailer/lib/stream-transport.js"
|
||||
import type { Awaitable } from ".."
|
||||
import type { CommonProviderOptions } from "."
|
||||
import type { Theme } from "../core/types"
|
||||
|
||||
// TODO: Make use of https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html for the string
|
||||
type AllTransportOptions = string | SMTPTransport | SMTPTransport.Options | SMTPPool | SMTPPool.Options | SendmailTransport | SendmailTransport.Options | StreamTransport | StreamTransport.Options | JSONTransport | JSONTransport.Options | SESTransport | SESTransport.Options | Transport<any> | TransportOptions
|
||||
|
||||
export interface SendVerificationRequestParams {
|
||||
identifier: string
|
||||
url: string
|
||||
@@ -14,10 +21,9 @@ export interface SendVerificationRequestParams {
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
export interface EmailConfig extends CommonProviderOptions {
|
||||
type: "email"
|
||||
// TODO: Make use of https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html
|
||||
server: string | SMTPTransportOptions
|
||||
export interface EmailUserConfig {
|
||||
server?: AllTransportOptions
|
||||
type?: "email"
|
||||
/** @default "NextAuth <no-reply@example.com>" */
|
||||
from?: string
|
||||
/**
|
||||
@@ -27,7 +33,7 @@ export interface EmailConfig extends CommonProviderOptions {
|
||||
*/
|
||||
maxAge?: number
|
||||
/** [Documentation](https://next-auth.js.org/providers/email#customizing-emails) */
|
||||
sendVerificationRequest: (
|
||||
sendVerificationRequest?: (
|
||||
params: SendVerificationRequestParams
|
||||
) => Awaitable<void>
|
||||
/**
|
||||
@@ -61,10 +67,31 @@ export interface EmailConfig extends CommonProviderOptions {
|
||||
* [Documentation](https://next-auth.js.org/providers/email#normalizing-the-e-mail-address) | [RFC 2821](https://tools.ietf.org/html/rfc2821) | [Email syntax](https://en.wikipedia.org/wiki/Email_address#Syntax)
|
||||
*/
|
||||
normalizeIdentifier?: (identifier: string) => string
|
||||
options: EmailUserConfig
|
||||
}
|
||||
|
||||
export type EmailUserConfig = Partial<Omit<EmailConfig, "options">>
|
||||
export interface EmailConfig extends CommonProviderOptions {
|
||||
// defaults
|
||||
id: "email"
|
||||
type: "email"
|
||||
name: "Email"
|
||||
server: AllTransportOptions
|
||||
from: string
|
||||
maxAge: number
|
||||
sendVerificationRequest: (
|
||||
params: SendVerificationRequestParams
|
||||
) => Awaitable<void>
|
||||
|
||||
/**
|
||||
* This is copied into EmailConfig in parseProviders() don't use elsewhere
|
||||
*/
|
||||
options: EmailUserConfig
|
||||
|
||||
// user options
|
||||
// TODO figure out a better way than copying from EmailUserConfig
|
||||
secret?: string
|
||||
generateVerificationToken?: () => Awaitable<string>
|
||||
normalizeIdentifier?: (identifier: string) => string
|
||||
}
|
||||
|
||||
export type EmailProvider = (options: EmailUserConfig) => EmailConfig
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export interface CommonProviderOptions {
|
||||
id: string
|
||||
name: string
|
||||
type: ProviderType
|
||||
options?: Record<string, unknown>
|
||||
options?: any
|
||||
}
|
||||
|
||||
export type Provider = OAuthConfig<any> | EmailConfig | CredentialsConfig
|
||||
|
||||
@@ -74,7 +74,7 @@ export type TokenEndpointHandler = EndpointHandler<
|
||||
params: CallbackParamsType
|
||||
/**
|
||||
* When using this custom flow, make sure to do all the necessary security checks.
|
||||
* Thist object contains parameters you have to match against the request to make sure it is valid.
|
||||
* This object contains parameters you have to match against the request to make sure it is valid.
|
||||
*/
|
||||
checks: OAuthChecks
|
||||
},
|
||||
|
||||
56
packages/next-auth/src/providers/passage.ts
Normal file
56
packages/next-auth/src/providers/passage.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { OAuthConfig, OAuthUserConfig } from "."
|
||||
|
||||
/** @see [Supported Scopes](https://docs.passage.id/hosted-login/oidc-client-configuration#supported-scopes) */
|
||||
export interface PassageProfile {
|
||||
iss: string
|
||||
/** Unique identifer in Passage for the user */
|
||||
sub: string
|
||||
aud: string[]
|
||||
exp: number
|
||||
iat: number
|
||||
auth_time: number
|
||||
azp: string
|
||||
client_id: string
|
||||
at_hash: string
|
||||
c_hash: string
|
||||
/** The user's email address */
|
||||
email: string
|
||||
/** Whether the user has verified their email address */
|
||||
email_verified: boolean
|
||||
/** The user's phone number */
|
||||
phone: string
|
||||
/** Whether the user has verified their phone number */
|
||||
phone_number_verified: boolean
|
||||
}
|
||||
|
||||
export default function Passage(
|
||||
config: OAuthUserConfig<PassageProfile>
|
||||
): OAuthConfig<PassageProfile> {
|
||||
config.issuer = config.issuer?.replace(/\/$/, "")
|
||||
return {
|
||||
id: "passage",
|
||||
name: "Passage",
|
||||
type: "oauth",
|
||||
wellKnown: `${config.issuer}/.well-known/openid-configuration`,
|
||||
authorization: { params: { scope: "openid email" } },
|
||||
client: { token_endpoint_auth_method: "client_secret_basic" },
|
||||
checks: ["pkce", "state"],
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.sub,
|
||||
name: null,
|
||||
email: profile.email,
|
||||
image: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/passage.svg",
|
||||
logoDark: "/passage.svg",
|
||||
bg: "#fff",
|
||||
bgDark: "#fff",
|
||||
text: "#000",
|
||||
textDark: "#000",
|
||||
},
|
||||
options: config,
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ export async function signIn<
|
||||
isCredentials ? "callback" : "signin"
|
||||
}/${provider}`
|
||||
|
||||
const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`
|
||||
const _signInUrl = `${signInUrl}${authorizationParams ? `?${new URLSearchParams(authorizationParams)}` : ""}`
|
||||
|
||||
const res = await fetch(_signInUrl, {
|
||||
method: "post",
|
||||
|
||||
@@ -35,7 +35,7 @@ export interface SignInOptions extends Record<string, unknown> {
|
||||
}
|
||||
|
||||
export interface SignInResponse {
|
||||
error: string | undefined
|
||||
error: string | null
|
||||
status: number
|
||||
ok: boolean
|
||||
url: string | null
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/** Extract the host from the environment */
|
||||
export function detectHost(forwardedHost: any) {
|
||||
/** Extract the origin from the environment */
|
||||
export function detectOrigin(forwardedHost: any, protocol: any) {
|
||||
// If we detect a Vercel environment, we can trust the host
|
||||
if (process.env.VERCEL ?? process.env.AUTH_TRUST_HOST)
|
||||
return forwardedHost
|
||||
return `${protocol === "http" ? "http" : "https"}://${forwardedHost}`
|
||||
|
||||
// If `NEXTAUTH_URL` is `undefined` we fall back to "http://localhost:3000"
|
||||
return process.env.NEXTAUTH_URL
|
||||
}
|
||||
321
pnpm-lock.yaml
generated
321
pnpm-lock.yaml
generated
@@ -60,11 +60,11 @@ importers:
|
||||
'@prisma/client': ^3
|
||||
'@supabase/supabase-js': ^2.0.5
|
||||
'@types/jsonwebtoken': ^8.5.5
|
||||
'@types/react': ^18.0.15
|
||||
'@types/react': ^18.0.37
|
||||
'@types/react-dom': ^18.0.6
|
||||
fake-smtp-server: ^0.8.0
|
||||
faunadb: ^4
|
||||
next: 13.0.6
|
||||
next: 13.4.12
|
||||
next-auth: workspace:*
|
||||
nodemailer: ^6
|
||||
pg: ^8.7.3
|
||||
@@ -81,14 +81,14 @@ importers:
|
||||
'@prisma/client': 3.15.2_prisma@3.15.2
|
||||
'@supabase/supabase-js': 2.0.5
|
||||
faunadb: 4.6.0
|
||||
next: 13.0.6_biqbaboplfbrettd7655fr4n2y
|
||||
next: 13.4.12_biqbaboplfbrettd7655fr4n2y
|
||||
next-auth: link:../../packages/next-auth
|
||||
nodemailer: 6.7.5
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
devDependencies:
|
||||
'@types/jsonwebtoken': 8.5.8
|
||||
'@types/react': 18.0.15
|
||||
'@types/react': 18.2.0
|
||||
'@types/react-dom': 18.0.6
|
||||
fake-smtp-server: 0.8.0
|
||||
pg: 8.7.3
|
||||
@@ -462,7 +462,7 @@ importers:
|
||||
'@types/node': ^17.0.42
|
||||
'@types/nodemailer': ^6.4.4
|
||||
'@types/oauth': ^0.9.1
|
||||
'@types/react': ^18.0.15
|
||||
'@types/react': 18.0.37
|
||||
'@types/react-dom': ^18.0.6
|
||||
autoprefixer: ^10.4.7
|
||||
babel-plugin-jsx-pragmatic: ^1.0.2
|
||||
@@ -475,7 +475,7 @@ importers:
|
||||
jest-watch-typeahead: ^1.1.0
|
||||
jose: ^4.11.4
|
||||
msw: ^0.42.3
|
||||
next: 13.0.6
|
||||
next: 13.3.0
|
||||
oauth: ^0.9.15
|
||||
openid-client: ^5.4.0
|
||||
postcss: ^8.4.14
|
||||
@@ -512,13 +512,13 @@ importers:
|
||||
'@testing-library/dom': 8.14.0
|
||||
'@testing-library/jest-dom': 5.16.4
|
||||
'@testing-library/react': 13.3.0_biqbaboplfbrettd7655fr4n2y
|
||||
'@testing-library/react-hooks': 8.0.1_bb2bxwco6ptpubzwpazr52qf6i
|
||||
'@testing-library/react-hooks': 8.0.1_jf7puk66b2eiqxne3oe3xlxkou
|
||||
'@testing-library/user-event': 14.2.1_ihvo3xlg2d6kwqju3os3zitn3y
|
||||
'@types/jest': 28.1.3
|
||||
'@types/node': 17.0.45
|
||||
'@types/nodemailer': 6.4.4
|
||||
'@types/oauth': 0.9.1
|
||||
'@types/react': 18.0.15
|
||||
'@types/react': 18.0.37
|
||||
'@types/react-dom': 18.0.6
|
||||
autoprefixer: 10.4.7_postcss@8.4.14
|
||||
babel-plugin-jsx-pragmatic: 1.0.2
|
||||
@@ -529,7 +529,7 @@ importers:
|
||||
jest-environment-jsdom: 28.1.1
|
||||
jest-watch-typeahead: 1.1.0_jest@28.1.1
|
||||
msw: 0.42.3
|
||||
next: 13.0.6_4cc5zw5azim2bix77d63le72su
|
||||
next: 13.3.0_4cc5zw5azim2bix77d63le72su
|
||||
postcss: 8.4.14
|
||||
postcss-cli: 9.1.0_postcss@8.4.14
|
||||
postcss-nested: 5.0.6_postcss@8.4.14
|
||||
@@ -5348,7 +5348,7 @@ packages:
|
||||
'@docusaurus/react-loadable': 5.5.2_react@18.2.0
|
||||
'@docusaurus/types': 2.1.0_biqbaboplfbrettd7655fr4n2y
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.0.15
|
||||
'@types/react': 18.2.0
|
||||
'@types/react-router-config': 5.0.6
|
||||
'@types/react-router-dom': 5.3.3
|
||||
react: 18.2.0
|
||||
@@ -5647,7 +5647,7 @@ packages:
|
||||
peerDependencies:
|
||||
react: '*'
|
||||
dependencies:
|
||||
'@types/react': 18.0.26
|
||||
'@types/react': 18.2.0
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
dev: true
|
||||
@@ -5677,7 +5677,7 @@ packages:
|
||||
infima: 0.2.0-alpha.42
|
||||
lodash: 4.17.21
|
||||
nprogress: 0.2.0
|
||||
postcss: 8.4.19
|
||||
postcss: 8.4.20
|
||||
prism-react-renderer: 1.3.5_react@18.2.0
|
||||
prismjs: 1.28.0
|
||||
react: 18.2.0
|
||||
@@ -5716,7 +5716,7 @@ packages:
|
||||
'@docusaurus/plugin-content-pages': 2.1.0_biqbaboplfbrettd7655fr4n2y
|
||||
'@docusaurus/utils': 2.1.0_@docusaurus+types@2.1.0
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.0.15
|
||||
'@types/react': 18.2.0
|
||||
'@types/react-router-config': 5.0.6
|
||||
clsx: 1.2.1
|
||||
parse-numeric-range: 1.3.0
|
||||
@@ -5801,7 +5801,7 @@ packages:
|
||||
react-dom: ^16.8.4 || ^17.0.0
|
||||
dependencies:
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.0.15
|
||||
'@types/react': 18.2.0
|
||||
commander: 5.1.0
|
||||
joi: 17.6.0
|
||||
react: 18.2.0
|
||||
@@ -7539,111 +7539,174 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@next/env/13.0.6:
|
||||
resolution: {integrity: sha512-yceT6DCHKqPRS1cAm8DHvDvK74DLIkDQdm5iV+GnIts8h0QbdHvkUIkdOvQoOODgpr6018skbmSQp12z5OWIQQ==}
|
||||
/@next/env/13.3.0:
|
||||
resolution: {integrity: sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==}
|
||||
dev: true
|
||||
|
||||
/@next/swc-android-arm-eabi/13.0.6:
|
||||
resolution: {integrity: sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
optional: true
|
||||
/@next/env/13.4.12:
|
||||
resolution: {integrity: sha512-RmHanbV21saP/6OEPBJ7yJMuys68cIf8OBBWd7+uj40LdpmswVAwe1uzeuFyUsd6SfeITWT3XnQfn6wULeKwDQ==}
|
||||
dev: false
|
||||
|
||||
/@next/swc-android-arm64/13.0.6:
|
||||
resolution: {integrity: sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-darwin-arm64/13.0.6:
|
||||
resolution: {integrity: sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg==}
|
||||
/@next/swc-darwin-arm64/13.3.0:
|
||||
resolution: {integrity: sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-darwin-x64/13.0.6:
|
||||
resolution: {integrity: sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ==}
|
||||
/@next/swc-darwin-arm64/13.4.12:
|
||||
resolution: {integrity: sha512-deUrbCXTMZ6ZhbOoloqecnUeNpUOupi8SE2tx4jPfNS9uyUR9zK4iXBvH65opVcA/9F5I/p8vDXSYbUlbmBjZg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-darwin-x64/13.3.0:
|
||||
resolution: {integrity: sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-freebsd-x64/13.0.6:
|
||||
resolution: {integrity: sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w==}
|
||||
/@next/swc-darwin-x64/13.4.12:
|
||||
resolution: {integrity: sha512-WRvH7RxgRHlC1yb5oG0ZLx8F7uci9AivM5/HGGv9ZyG2Als8Ij64GC3d+mQ5sJhWjusyU6T6V1WKTUoTmOB0zQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm-gnueabihf/13.0.6:
|
||||
resolution: {integrity: sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm64-gnu/13.0.6:
|
||||
resolution: {integrity: sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q==}
|
||||
/@next/swc-linux-arm64-gnu/13.3.0:
|
||||
resolution: {integrity: sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm64-musl/13.0.6:
|
||||
resolution: {integrity: sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A==}
|
||||
/@next/swc-linux-arm64-gnu/13.4.12:
|
||||
resolution: {integrity: sha512-YEKracAWuxp54tKiAvvq73PUs9lok57cc8meYRibTWe/VdPB2vLgkTVWFcw31YDuRXdEhdX0fWS6Q+ESBhnEig==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-x64-gnu/13.0.6:
|
||||
resolution: {integrity: sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw==}
|
||||
/@next/swc-linux-arm64-musl/13.3.0:
|
||||
resolution: {integrity: sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-arm64-musl/13.4.12:
|
||||
resolution: {integrity: sha512-LhJR7/RAjdHJ2Isl2pgc/JaoxNk0KtBgkVpiDJPVExVWA1c6gzY57+3zWuxuyWzTG+fhLZo2Y80pLXgIJv7g3g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-x64-gnu/13.3.0:
|
||||
resolution: {integrity: sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-x64-musl/13.0.6:
|
||||
resolution: {integrity: sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA==}
|
||||
/@next/swc-linux-x64-gnu/13.4.12:
|
||||
resolution: {integrity: sha512-1DWLL/B9nBNiQRng+1aqs3OaZcxC16Nf+mOnpcrZZSdyKHek3WQh6j/fkbukObgNGwmCoVevLUa/p3UFTTqgqg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-arm64-msvc/13.0.6:
|
||||
resolution: {integrity: sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw==}
|
||||
/@next/swc-linux-x64-musl/13.3.0:
|
||||
resolution: {integrity: sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-linux-x64-musl/13.4.12:
|
||||
resolution: {integrity: sha512-kEAJmgYFhp0VL+eRWmUkVxLVunn7oL9Mdue/FS8yzRBVj7Z0AnIrHpTIeIUl1bbdQq1VaoOztnKicAjfkLTRCQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-arm64-msvc/13.3.0:
|
||||
resolution: {integrity: sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-ia32-msvc/13.0.6:
|
||||
resolution: {integrity: sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg==}
|
||||
/@next/swc-win32-arm64-msvc/13.4.12:
|
||||
resolution: {integrity: sha512-GMLuL/loR6yIIRTnPRY6UGbLL9MBdw2anxkOnANxvLvsml4F0HNIgvnU3Ej4BjbqMTNjD4hcPFdlEow4XHPdZA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-ia32-msvc/13.3.0:
|
||||
resolution: {integrity: sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-x64-msvc/13.0.6:
|
||||
resolution: {integrity: sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ==}
|
||||
/@next/swc-win32-ia32-msvc/13.4.12:
|
||||
resolution: {integrity: sha512-PhgNqN2Vnkm7XaMdRmmX0ZSwZXQAtamBVSa9A/V1dfKQCV1rjIZeiy/dbBnVYGdj63ANfsOR/30XpxP71W0eww==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-x64-msvc/13.3.0:
|
||||
resolution: {integrity: sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@next/swc-win32-x64-msvc/13.4.12:
|
||||
resolution: {integrity: sha512-Z+56e/Ljt0bUs+T+jPjhFyxYBcdY2RIq9ELFU+qAMQMteHo7ymbV7CKmlcX59RI9C4YzN8PgMgLyAoi916b5HA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@nicolo-ribaudo/chokidar-2/2.1.8-no-fsevents.3:
|
||||
@@ -8218,6 +8281,13 @@ packages:
|
||||
resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==}
|
||||
dependencies:
|
||||
tslib: 2.4.1
|
||||
dev: true
|
||||
|
||||
/@swc/helpers/0.5.1:
|
||||
resolution: {integrity: sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==}
|
||||
dependencies:
|
||||
tslib: 2.4.1
|
||||
dev: false
|
||||
|
||||
/@swc/jest/0.2.21_@swc+core@1.2.204:
|
||||
resolution: {integrity: sha512-/+NcExiZbxXANNhNPnIdFuGq62CeumulLS1bngwqIXd8H7d96LFUfrYzdt8tlTwLMel8tFtQ5aRjzVkyOTyPDw==}
|
||||
@@ -8269,7 +8339,7 @@ packages:
|
||||
redent: 3.0.0
|
||||
dev: true
|
||||
|
||||
/@testing-library/react-hooks/8.0.1_bb2bxwco6ptpubzwpazr52qf6i:
|
||||
/@testing-library/react-hooks/8.0.1_jf7puk66b2eiqxne3oe3xlxkou:
|
||||
resolution: {integrity: sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
@@ -8286,7 +8356,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
'@types/react': 18.0.15
|
||||
'@types/react': 18.0.37
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-error-boundary: 3.1.4_react@18.2.0
|
||||
@@ -8814,14 +8884,14 @@ packages:
|
||||
/@types/react-dom/18.0.6:
|
||||
resolution: {integrity: sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==}
|
||||
dependencies:
|
||||
'@types/react': 18.0.26
|
||||
'@types/react': 18.2.0
|
||||
dev: true
|
||||
|
||||
/@types/react-router-config/5.0.6:
|
||||
resolution: {integrity: sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg==}
|
||||
dependencies:
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.0.26
|
||||
'@types/react': 18.2.0
|
||||
'@types/react-router': 5.1.18
|
||||
dev: true
|
||||
|
||||
@@ -8829,7 +8899,7 @@ packages:
|
||||
resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==}
|
||||
dependencies:
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.0.26
|
||||
'@types/react': 18.2.0
|
||||
'@types/react-router': 5.1.18
|
||||
dev: true
|
||||
|
||||
@@ -8837,19 +8907,19 @@ packages:
|
||||
resolution: {integrity: sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==}
|
||||
dependencies:
|
||||
'@types/history': 4.7.11
|
||||
'@types/react': 18.0.26
|
||||
'@types/react': 18.2.0
|
||||
dev: true
|
||||
|
||||
/@types/react/18.0.15:
|
||||
resolution: {integrity: sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==}
|
||||
/@types/react/18.0.37:
|
||||
resolution: {integrity: sha512-4yaZZtkRN3ZIQD3KSEwkfcik8s0SWV+82dlJot1AbGYHCzJkWP3ENBY6wYeDRmKZ6HkrgoGAmR2HqdwYGp6OEw==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.5
|
||||
'@types/scheduler': 0.16.2
|
||||
csstype: 3.1.0
|
||||
dev: true
|
||||
|
||||
/@types/react/18.0.26:
|
||||
resolution: {integrity: sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==}
|
||||
/@types/react/18.2.0:
|
||||
resolution: {integrity: sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.5
|
||||
'@types/scheduler': 0.16.2
|
||||
@@ -10606,6 +10676,12 @@ packages:
|
||||
dependencies:
|
||||
node-gyp-build: 4.5.0
|
||||
|
||||
/busboy/1.6.0:
|
||||
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
|
||||
engines: {node: '>=10.16.0'}
|
||||
dependencies:
|
||||
streamsearch: 1.1.0
|
||||
|
||||
/bytes/3.0.0:
|
||||
resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -14796,7 +14872,6 @@ packages:
|
||||
|
||||
/glob-to-regexp/0.4.1:
|
||||
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
|
||||
dev: true
|
||||
|
||||
/glob/7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
@@ -15023,7 +15098,6 @@ packages:
|
||||
|
||||
/graceful-fs/4.2.10:
|
||||
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
|
||||
dev: true
|
||||
|
||||
/graphlib/2.1.8:
|
||||
resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==}
|
||||
@@ -19224,17 +19298,20 @@ packages:
|
||||
/next-tick/1.1.0:
|
||||
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
|
||||
|
||||
/next/13.0.6_4cc5zw5azim2bix77d63le72su:
|
||||
resolution: {integrity: sha512-COvigvms2LRt1rrzfBQcMQ2GZd86Mvk1z+LOLY5pniFtL4VrTmhZ9salrbKfSiXbhsD01TrDdD68ec3ABDyscA==}
|
||||
/next/13.3.0_4cc5zw5azim2bix77d63le72su:
|
||||
resolution: {integrity: sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==}
|
||||
engines: {node: '>=14.6.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.1.0
|
||||
fibers: '>= 3.1.0'
|
||||
node-sass: ^6.0.0 || ^7.0.0
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
sass: ^1.3.0
|
||||
peerDependenciesMeta:
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
fibers:
|
||||
optional: true
|
||||
node-sass:
|
||||
@@ -19242,71 +19319,67 @@ packages:
|
||||
sass:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@next/env': 13.0.6
|
||||
'@next/env': 13.3.0
|
||||
'@swc/helpers': 0.4.14
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001431
|
||||
postcss: 8.4.14
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
styled-jsx: 5.1.0_5wvcx74lvxq2lfpc5x4ihgp2jm
|
||||
styled-jsx: 5.1.1_5wvcx74lvxq2lfpc5x4ihgp2jm
|
||||
optionalDependencies:
|
||||
'@next/swc-android-arm-eabi': 13.0.6
|
||||
'@next/swc-android-arm64': 13.0.6
|
||||
'@next/swc-darwin-arm64': 13.0.6
|
||||
'@next/swc-darwin-x64': 13.0.6
|
||||
'@next/swc-freebsd-x64': 13.0.6
|
||||
'@next/swc-linux-arm-gnueabihf': 13.0.6
|
||||
'@next/swc-linux-arm64-gnu': 13.0.6
|
||||
'@next/swc-linux-arm64-musl': 13.0.6
|
||||
'@next/swc-linux-x64-gnu': 13.0.6
|
||||
'@next/swc-linux-x64-musl': 13.0.6
|
||||
'@next/swc-win32-arm64-msvc': 13.0.6
|
||||
'@next/swc-win32-ia32-msvc': 13.0.6
|
||||
'@next/swc-win32-x64-msvc': 13.0.6
|
||||
'@next/swc-darwin-arm64': 13.3.0
|
||||
'@next/swc-darwin-x64': 13.3.0
|
||||
'@next/swc-linux-arm64-gnu': 13.3.0
|
||||
'@next/swc-linux-arm64-musl': 13.3.0
|
||||
'@next/swc-linux-x64-gnu': 13.3.0
|
||||
'@next/swc-linux-x64-musl': 13.3.0
|
||||
'@next/swc-win32-arm64-msvc': 13.3.0
|
||||
'@next/swc-win32-ia32-msvc': 13.3.0
|
||||
'@next/swc-win32-x64-msvc': 13.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
dev: true
|
||||
|
||||
/next/13.0.6_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-COvigvms2LRt1rrzfBQcMQ2GZd86Mvk1z+LOLY5pniFtL4VrTmhZ9salrbKfSiXbhsD01TrDdD68ec3ABDyscA==}
|
||||
engines: {node: '>=14.6.0'}
|
||||
/next/13.4.12_biqbaboplfbrettd7655fr4n2y:
|
||||
resolution: {integrity: sha512-eHfnru9x6NRmTMcjQp6Nz0J4XH9OubmzOa7CkWL+AUrUxpibub3vWwttjduu9No16dug1kq04hiUUpo7J3m3Xw==}
|
||||
engines: {node: '>=16.8.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.1.0
|
||||
fibers: '>= 3.1.0'
|
||||
node-sass: ^6.0.0 || ^7.0.0
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
sass: ^1.3.0
|
||||
peerDependenciesMeta:
|
||||
fibers:
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
node-sass:
|
||||
fibers:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@next/env': 13.0.6
|
||||
'@swc/helpers': 0.4.14
|
||||
'@next/env': 13.4.12
|
||||
'@swc/helpers': 0.5.1
|
||||
busboy: 1.6.0
|
||||
caniuse-lite: 1.0.30001431
|
||||
postcss: 8.4.14
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
styled-jsx: 5.1.0_react@18.2.0
|
||||
styled-jsx: 5.1.1_react@18.2.0
|
||||
watchpack: 2.4.0
|
||||
zod: 3.21.4
|
||||
optionalDependencies:
|
||||
'@next/swc-android-arm-eabi': 13.0.6
|
||||
'@next/swc-android-arm64': 13.0.6
|
||||
'@next/swc-darwin-arm64': 13.0.6
|
||||
'@next/swc-darwin-x64': 13.0.6
|
||||
'@next/swc-freebsd-x64': 13.0.6
|
||||
'@next/swc-linux-arm-gnueabihf': 13.0.6
|
||||
'@next/swc-linux-arm64-gnu': 13.0.6
|
||||
'@next/swc-linux-arm64-musl': 13.0.6
|
||||
'@next/swc-linux-x64-gnu': 13.0.6
|
||||
'@next/swc-linux-x64-musl': 13.0.6
|
||||
'@next/swc-win32-arm64-msvc': 13.0.6
|
||||
'@next/swc-win32-ia32-msvc': 13.0.6
|
||||
'@next/swc-win32-x64-msvc': 13.0.6
|
||||
'@next/swc-darwin-arm64': 13.4.12
|
||||
'@next/swc-darwin-x64': 13.4.12
|
||||
'@next/swc-linux-arm64-gnu': 13.4.12
|
||||
'@next/swc-linux-arm64-musl': 13.4.12
|
||||
'@next/swc-linux-x64-gnu': 13.4.12
|
||||
'@next/swc-linux-x64-musl': 13.4.12
|
||||
'@next/swc-win32-arm64-msvc': 13.4.12
|
||||
'@next/swc-win32-ia32-msvc': 13.4.12
|
||||
'@next/swc-win32-x64-msvc': 13.4.12
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
@@ -20862,15 +20935,6 @@ packages:
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
|
||||
/postcss/8.4.19:
|
||||
resolution: {integrity: sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
dependencies:
|
||||
nanoid: 3.3.4
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
/postcss/8.4.20:
|
||||
resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -23024,6 +23088,10 @@ packages:
|
||||
any-promise: 1.3.0
|
||||
dev: true
|
||||
|
||||
/streamsearch/1.1.0:
|
||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
/strict-event-emitter/0.2.4:
|
||||
resolution: {integrity: sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ==}
|
||||
dependencies:
|
||||
@@ -23196,8 +23264,8 @@ packages:
|
||||
supports-color: 5.5.0
|
||||
dev: false
|
||||
|
||||
/styled-jsx/5.1.0_5wvcx74lvxq2lfpc5x4ihgp2jm:
|
||||
resolution: {integrity: sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==}
|
||||
/styled-jsx/5.1.1_5wvcx74lvxq2lfpc5x4ihgp2jm:
|
||||
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': '*'
|
||||
@@ -23214,8 +23282,8 @@ packages:
|
||||
react: 18.2.0
|
||||
dev: true
|
||||
|
||||
/styled-jsx/5.1.0_react@18.2.0:
|
||||
resolution: {integrity: sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ==}
|
||||
/styled-jsx/5.1.1_react@18.2.0:
|
||||
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
peerDependencies:
|
||||
'@babel/core': '*'
|
||||
@@ -24774,7 +24842,6 @@ packages:
|
||||
dependencies:
|
||||
glob-to-regexp: 0.4.1
|
||||
graceful-fs: 4.2.10
|
||||
dev: true
|
||||
|
||||
/wbuf/1.7.3:
|
||||
resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==}
|
||||
@@ -25352,6 +25419,10 @@ packages:
|
||||
readable-stream: 3.6.0
|
||||
dev: true
|
||||
|
||||
/zod/3.21.4:
|
||||
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
|
||||
dev: false
|
||||
|
||||
/zwitch/1.0.5:
|
||||
resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==}
|
||||
dev: true
|
||||
|
||||
Reference in New Issue
Block a user