Compare commits

...

71 Commits

Author SHA1 Message Date
Thang Vu
2510f74809 chore(release): bump version [skip ci] 2023-10-02 18:57:37 +07:00
Thang Vu
27b2519b84 fix(next): returns correct status for signing in with redirect: false for route handler (#8775)
* fix: returns status for signing in with credentials provider `redirect: false`

* chore: format cookie.ts
2023-10-02 18:48:36 +07:00
Ahmed Abdelbaset
5f15b0704a docs: fix typo (#8767)
fix typo
2023-10-02 01:03:25 +01:00
Balázs Orbán
e4573ffff5 docs: typo 2023-10-02 01:37:14 +02:00
Balázs Orbán
4ce1951a2b docs: close admonition 2023-10-02 01:34:55 +02:00
Balázs Orbán
c95531d651 docs: mention auth() convention under getServerSession 2023-10-02 01:32:35 +02:00
Balázs Orbán
654d52bb56 docs: mention getServerSession under SessionProvider 2023-10-02 01:27:35 +02:00
Herbie Vine
b72d7be9be docs: set decode fn not jwt obj (#8742)
Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-09-29 15:36:32 +02:00
Balázs Orbán
76fcc4e70c chore: don't sync example from v4 branch 2023-09-27 12:49:25 +02:00
Balázs Orbán
4cacf504dd docs: clarify pages in middleware 2023-09-26 13:23:04 +02:00
Balázs Orbán
50eb23f626 fix: update security policy link 2023-09-25 11:30:27 +02:00
Balázs Orbán
d813c00b3e fix(ts): fix typo 2023-09-20 19:48:30 +01:00
Soheil Nazari
fc4448a85a docs: add extra tips for next app router (#8227)
* Update example.md

* Update example.md

* Update example.md

* Update docs/docs/getting-started/example.md

* Update docs/docs/getting-started/example.md

* Update docs/docs/getting-started/example.md

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
2023-09-20 13:46:47 +07:00
Thang Vu
16f781c091 chore: update email 2023-09-16 12:07:27 +07:00
Jared Wyce
ebfdaece0e fix: remove trailing ? from signIn URL (#8466)
* fix: 🎣 avoid phishing categorization by VPNs

* Update packages/next-auth/src/react/index.tsx

* Update packages/next-auth/src/react/index.tsx

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
2023-09-06 12:55:03 +07:00
Devdat Kumar
64a190e549 docs: Update adapters.md (#8397)
"Drizzle" and "Kysely" links have been added to the list, and the list has been sorted.

https://next-auth.js.org/adapters
2023-08-24 10:23:41 +01:00
Arif Shanji
e11f898c10 docs: typo (#8366) 2023-08-21 13:53:35 +02:00
Balázs Orbán
dcb11da2e2 docs: update error page
closes #8174
2023-08-18 09:22:25 +01:00
Thang Vu
9f900befe6 chore(release): bump version [skip ci] 2023-08-16 14:43:26 +07:00
Gabriel Villenave
09c2a89df8 fix: use default submodules export in package.json (#8330)
Use `default` submodules export in `package.json` to ensure compatibility, as specified in https://nodejs.org/api/packages.html#conditional-exports
2023-08-16 09:33:07 +02:00
Balázs Orbán
20c3fe3331 fix(ts): correctly expose next-auth/adapters
Fixes https://github.com/nextauthjs/next-auth/issues/8283#issuecomment-1675939280
2023-08-12 16:37:18 +02:00
Manuel Cattelan
e26f500d18 docs(providers): add warning for gitlab provider (#8292) 2023-08-11 13:56:56 +02:00
Balázs Orbán
494d16e54d chore(release): bump version [skip ci] 2023-08-11 13:43:03 +02:00
Balázs Orbán
5a8aa2e5e5 feat(providers): add Passage by 1Password 2023-08-11 13:39:52 +02:00
Balázs Orbán
05ff6ae221 fix(ts): correctly export submodule types 2023-08-11 11:31:35 +02:00
Jonathan Edenström
1fbc684f53 fix: sort cookie chunks correctly (#8284) 2023-08-10 12:17:41 +01:00
Balázs Orbán
124be4fb1f chore(release): bump version [skip ci] 2023-08-08 19:21:49 +02:00
Balázs Orbán
3b0128c3ca fix(ts): match next-auth/adapter & @auth/core/adapters 2023-08-08 19:20:30 +02:00
Balázs Orbán
36b97aafb8 docs: amplify note 2023-08-08 18:00:41 +02:00
Thang Vu
175d37499b chore(release): bump version [skip ci] 2023-08-06 22:52:13 +07:00
Thang Vu
08a6835a70 fix: don't return res.end() in api handler (#8244)
Move #8069 to v4 branch
co-authored by @maritz

Co-authored-by: maritz <159633+maritz@users.noreply.github.com>
2023-08-06 22:38:57 +07:00
Thang Vu
448a11ff0a chore: add turbo env vars 2023-08-06 21:47:08 +07:00
Thang Vu
f39f9708bd fix(ts) : add missing function overload for Route Handler (#8236)
Pick up https://github.com/nextauthjs/next-auth/pull/8211 & tweak some changes

Co-authored-by: Max Quinn <max.t.quinn@gmail.com>
2023-08-05 19:57:29 +07:00
Matt Azlin
6d98b8b33c docs: fixing broken link in documentation (#8208) 2023-08-03 16:11:11 +02:00
Balázs Orbán
ef7ec044c5 docs: clarify getServerSession 2023-08-03 16:05:32 +02:00
Balázs Orbán
e89e3143d7 docs: move unstable_getServerSession 2023-08-03 16:03:48 +02:00
Noam Al Rifaï
12f0795a0a docs: Typo fixed (#8206) 2023-08-03 16:01:58 +02:00
Trent
9e0036bc73 docs(providers): mention HTTP-based Email guide (#8214)
Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-08-03 15:57:57 +02:00
MohammadAli Saeidi
27aa5ef09b docs: Update object key "email" to "username" (#8113) 2023-07-25 14:45:38 +02:00
Thang Vu
903bd6fac9 fix: remove RSC warning in getServerSession (#8108) 2023-07-25 12:13:51 +02:00
Ricardo van Noort
998b7a0db4 docs: Update upgrade-to-v4.md (#8123) 2023-07-25 12:12:57 +02:00
Thang Vu
465644f9e4 fix(ts): SignInResponse.error type (#8109)
Co-authored-by: smcg468 <49883535+smcg468@users.noreply.github.com>
2023-07-22 12:39:23 +07:00
GhibliMagic
d12bd5a799 doc: Add a guide on sending magic links to existing users only (#7663) 2023-07-22 11:57:52 +07:00
Tony Worm
3897d47db2 docs: Update refresh-token-rotation.md - fix example client code filename (#8088) 2023-07-20 01:09:06 +02:00
Doug
e44dccc42d docs(providers): updated docs with missing account attribute (#8084) 2023-07-19 15:24:41 +02:00
Balázs Orbán
733a81bd3a chore(release): bump version [skip ci] 2023-07-18 22:53:27 +02:00
Balázs Orbán
f06f3bbc96 chore(release): bump version [skip ci] 2023-07-18 15:53:30 +02:00
Thang Vu
aea27a1fa8 fix: remove unused TS types 2023-07-16 22:32:55 +07:00
Thang Vu
bd37c55241 fix(ts): adapter interface (#8054) 2023-07-16 20:47:18 +07:00
Rexford Essilfie
169a5230db fix(ts): add overloads to withAuth middleware (#7999)
* fix(ts): add overloads to withAuth middleware

* fix: allow extends Request on returned middleware handler

* chore: simplify return type for withAuth returning middleware

* chore: remove withAuth overloads generics

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
2023-07-12 10:49:50 +07:00
Francis Gulotta
f48eb0478e fix(providers): fix nodemailer/required types (#7950)
Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-07-11 12:57:37 +02:00
Stephen Cronin
b25a090c17 docs: fix getServerSession API Routes example (#7978)
* Fix Next.js getServerSession API Routes example

Example API code threw an error in Next.js. Fixed the example to work.

* Update docs/docs/configuration/nextjs.md

---------

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-07-09 14:03:02 +02:00
Matt Jared
0167e9368b docs: Update example.md (#7879) 2023-06-27 14:29:17 +02:00
Mikalai S
dcb576f01b docs: Mention a possible cause of ResourceNotFound issue (#7758) 2023-06-09 14:56:55 +02:00
Balázs Orbán
9417822a41 Update oauth.ts
Closes #7608

Co-authored-by: aaazzz <akrm@hey.com>
2023-06-01 11:17:23 +01:00
Balázs Orbán
14f8f0cb58 docs: rephrase
Closes #7531

Co-authored-by: Trey Speakman
 <100887275+treyspeakman@users.noreply.github.com>
2023-05-19 00:58:27 +01:00
Nick Radford
212272a839 docs: Update sub-bullet about vercel deployment specifics (#7537) 2023-05-14 12:59:49 +02:00
Balázs Orbán
a8e8b7542c docs: Update initialization.md 2023-05-11 23:30:53 +01:00
browny
14cecb9b73 docs: update react docs link (#7521) 2023-05-11 14:45:39 +02:00
Ivan Medina
28bec0fbcc docs: Update client.md (#7458) 2023-05-06 12:09:10 +01:00
Thang Vu
bc683a5b72 chore: merge changes back to v4 (#7430)
* docs: Remove --save from install command (#7277)

Remove --save from install command

--save is no longer needed on npm install.

* chore: fix "Contributing guide" link (#7279)

* fix: detect origin when `instanceof Request` check fails (#7303)

* docs: Update Clerk sponsorship URL (#7305)

- Change Clerk URL from `https://clerk.dev` to `https://clerk.com`

- Fix alt from copy/paste

* chore: bump react types

* fix(docs): fix default `maxAge` formula (#7406)

* Update pnpm-lock.yaml

* sync package.json change

---------

Co-authored-by: Chris Hayes <6013871+Christopher-Hayes@users.noreply.github.com>
Co-authored-by: Raul <57044803+Leprekus@users.noreply.github.com>
Co-authored-by: Balázs Orbán <info@balazsorban.com>
Co-authored-by: Nick Parsons <nparsons08@gmail.com>
Co-authored-by: Victor <saptefrativictor@gmail.com>
2023-05-04 20:05:33 +01:00
Sebastián Iturra
e7b8597f73 docs: Update email.md (#7391) 2023-04-28 13:53:27 +01:00
Kjetil Hårtveit
5c89a21bfa docs: mention caching in App Router (#7206)
I spent at least a day figuring out why my tRPC caches were all [MISSing](https://vercel.com/docs/concepts/edge-network/caching#miss) even though I set the correct Cache-Control headers (my stack: NextAuth, NextJS, tRPC, Vercel). I wish information could be placed where appropriate so that others don't need to debug like I had too.

I realise it's a bit convoluted as tRPC suggested I could fetch the session in the context and then use it throughout my routers. It was not obvious to me that this caused all the public caches to fail, even on query procedures that were not using the session. The caches were MISSing because `getServerSession` refreshes the cookies via the `set-cookie` header and [Vercel won't allow this](https://vercel.com/docs/concepts/functions/serverless-functions/edge-caching). I'm not saying the refreshing of cookies is wrong, it's a nice feature, and it's kind of handy this implicitly means Vercel doesn't cache. 

So how I got here has many causes and it's futile to find anyone to "blame". The factors are:
- tRPC suggests `getSession()` in their [documentation for context](https://trpc.io/docs/server/context). 
- I see tRPC does not suggest `getSession()` in the page for [caching](https://trpc.io/docs/server/caching) which is correct but wasn't obvious to me what I had done wrong.
- my misunderstanding about the link between session and personalized data (it makes sense to me now but it wasn't that obvious to see the link: get session means no public cache)
2023-04-26 13:05:01 +01:00
Andreas Jagiella
6e9c8b5b3c docs(providers): mention non-standard properties (#7290)
~ needed database entries
~ type of redirect uri
2023-04-26 13:03:08 +01:00
Ilya
91a9e5f601 docs(providers): update default vk provider version and options link (#7354)
Update version by default and options link

Now by default VK provider uses `5.131` version.
And provider options link changed to .ts.
2023-04-26 12:58:09 +01:00
Balázs Orbán
cb916f4848 docs: Update typescript.md
closes #7288
2023-04-17 21:01:11 +01:00
muoi
8259cd4fc6 docs : fix typo (#7258)
Update link to Kakao Provider options
2023-04-17 10:35:15 +01:00
Dorijan Hašpl
7a8c0068c4 docs: mention Route Handler initialization in getting started (#7213)
Updated the Getting Started documentation file (section about adding NextAuth API routes) to refer to another documentation section where the NextAuth API routes are handled using the new App Router and Route Handlers
2023-04-12 11:39:09 +01:00
Balázs Orbán
6edb6ddaaf fix: respect protocol too, when host is trusted (#7214)
* fix: respect protocol too when host is trusted

* simplify
2023-04-12 11:30:20 +01:00
Balázs Orbán
0711d32a00 chore(release): bump version [skip ci] 2023-04-09 11:54:51 +02:00
Balázs Orbán
c261af4695 feat: support Route Handlers (#6777)
* feat: support Route Handlers

* update dev app

* init NextAuth via Route Handler in dev app

* import as type

* fix labeler

* default secret to `NEXTAUTH_SECRET`

* handle redirects

* support advanced init in Route Handlers

* use port 3000 for docs dev

* document initialization with Route Handlers

* upgrade to latest `next`

* upgrade to 13.3.0

* remove workaround

* cleanup
2023-04-09 10:51:49 +01:00
58 changed files with 798 additions and 337 deletions

View File

@@ -54,7 +54,7 @@ upstash-redis:
xata:
- packages/adapter-xata/**
core:
legacy:
- packages/next-auth/src/**/*
style:

7
.github/sync.yml vendored
View File

@@ -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

View File

@@ -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:

View File

@@ -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

View 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 }

View File

@@ -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.

View File

@@ -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",

View File

@@ -23,7 +23,8 @@
{
"name": "next"
}
]
],
"strictNullChecks": true
},
"include": [
"next-env.d.ts",

View File

@@ -26,7 +26,7 @@
},
"devDependencies": {
"@types/node": "^17",
"@types/react": "^18.0.15",
"@types/react": "^18.0.37",
"typescript": "^4"
}
}

View File

@@ -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)

View File

@@ -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"

View File

@@ -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,
},

View File

@@ -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 |

View File

@@ -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!

View File

@@ -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.
---

View File

@@ -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"

View File

@@ -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

View File

@@ -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
---

View File

@@ -351,8 +351,8 @@ User {
id
name
email
- emailVerified
+ email_verified
+ emailVerified
- email_verified
image
- created_at
- updated_at

View File

@@ -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.
:::

View File

@@ -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" },
},
}),

View File

@@ -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";
}
},
...
```

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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({

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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";

View File

@@ -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

View File

@@ -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",

View File

@@ -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?: (

View File

@@ -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) => {

View File

@@ -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,

View File

@@ -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 })

View File

@@ -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(

View File

@@ -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. */

View File

@@ -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

View File

@@ -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,

View File

@@ -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,
})

View File

@@ -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

View File

@@ -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,
})

View File

@@ -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 })

View File

@@ -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

View File

@@ -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. */

View File

@@ -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,

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
},

View 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,
}
}

View File

@@ -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",

View File

@@ -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

View File

@@ -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
View File

@@ -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