Compare commits

...

77 Commits

Author SHA1 Message Date
Balázs Orbán
58e30a6af6 chore(release): bump package version(s) [skip ci] 2022-11-07 21:33:48 +01:00
Balázs Orbán
b7ff987baf docs: update unstable_getServerSession in RSC 2022-11-07 21:20:06 +01:00
Balázs Orbán
782812a52b fix(next): correctly parse headers with RSC (#5753)
* fix(next): correctly parse headers with RSC

* chore(dev): simplify/fix dev app

* make authOptions optional for RSC case
2022-11-07 20:19:14 +00:00
Balázs Orbán
32f2a0cea3 chore(release): bump package version(s) [skip ci] 2022-11-07 03:40:46 +01:00
Balázs Orbán
3343ef18b2 fix(next): conditional RSC support (#5745)
* fix(next): conditional RSC

* use Node 16 for version determination

* convert cookies

* use map instead of reduce
2022-11-07 02:33:47 +00:00
Robert Soriano
6280fe9e10 docs: add Nuxt 3 playground (#5746) 2022-11-06 20:33:02 +01:00
Balázs Orbán
52a2bf3e28 chore(release): bump package version(s) [skip ci] 2022-11-06 06:24:30 +01:00
Balázs Orbán
180c6252d9 fix(next): build RSC+unstable_getServerSession 2022-11-06 06:09:27 +01:00
Balázs Orbán
362e981e6d chore(release): bump package version(s) [skip ci] 2022-11-06 06:07:47 +01:00
Balázs Orbán
5198eb19f7 fix(next): build RSC+unstable_getServerSession 2022-11-06 05:53:38 +01:00
Balázs Orbán
0210cfccf3 chore(release): bump package version(s) [skip ci] 2022-11-06 05:12:31 +01:00
Balázs Orbán
e90925bea0 feat(next): allow unstable_getServerSession in Server Components (#5741)
* feat(next): support Server Components with `unstable_getServerSession`

* chore: remove `.entries`

* docs(next): add documentation for RSC

* update beta docs

* chore(dev): add app dir

* fix text

* only show second warning if using with RSC

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

* Update core types

* Fix middleware

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

* Use new ResponseCookie API

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

* update node engines in packages/next-auth

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

* Adjust slogan

* Namespace tables for better DX

* Fix types

* Adjust docs

* Import type only

* Add scripts

* Fix types

* Update packages/adapter-xata/package.json

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

* Update packages/adapter-xata/package.json

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

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

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

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

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

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

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

* Update docs/docs/adapters/xata.md

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

* Update docs/docs/adapters/xata.md

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

* Address more comments

* Clarify codegen

* Fix by adding src

* Fix types

* More cleanup

* Fix import

* Clean up model

* Adjust docs

* Update docs

* Housekeeping

* Add tests

* Update lockfile

* Update packages/adapter-xata/tsconfig.json

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

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

Co-authored-by: Balázs Orbán <info@balazsorban.com>
Co-authored-by: Thang Vu <hi@thvu.dev>
2022-10-27 21:39:49 +07:00
Thang Vu
a787efc6be docs: improve documentation for adding new provider (#5633) 2022-10-25 10:05:52 +07:00
Bruno Crosier
261968b9bb docs: improve credentials docs (#5627) 2022-10-24 23:33:46 +07:00
Thang Vu
4dbbe5b2d9 chore(release): bump package version(s) [skip ci] 2022-10-23 22:17:19 +07:00
Balázs Orbán
d9df582fa8 feat(client): add refetchWhenOffline option (#4940)
* feat(client): add `refetchWhenOffline` option

* docs(client): document `refetchWhenOffline` option

* add TODO comment for next major

* feat: improve refetch hook logic

* fix: add todo back

* chore: small refactoring

Co-authored-by: Thang Vu <hi@thvu.dev>
2022-10-23 22:09:30 +07:00
Matsuoka
af840b2106 feat(providers): Add Todoist provider (#5253)
* feat: Add Todoist provider

* fix: use openid-client

* chore: add Todoist provider to issue template

Co-authored-by: Thang Vu <hi@thvu.dev>
2022-10-23 17:16:06 +07:00
jcdogo
ba89907d5a feat: Add allowDangerousEmailAccountLinking option for OAuth providers (#5513)
* Add opt-in for dangerous linking

* Add documentation for allowDangerousEmailAccountLinking option.

* Add link to FAQ.

* Fix nullish coalescing operator linting error.
2022-10-23 17:08:25 +07:00
Steven Tey
08eaeba79f docs: Fixed typo (#5609) 2022-10-21 10:07:13 +01:00
Usman Sabuwala (Max Programming)
c31eabfcc6 docs: Update the nodemailer well known page URL (#5573) 2022-10-19 22:28:40 +02:00
Balázs Orbán
4423673424 docs: update patreon.md 2022-10-18 21:32:51 +01:00
X
281d0948b9 docs: Typo error on Example (#5590)
Removed unwanted ")" from Example
2022-10-18 21:32:33 +01:00
Lluis Agusti
5246183c55 chore: docs updates (#5581)
* chore: fix version label

* upgrade docusaurus

* fix

* fix

* fix links, NextAuth -> NextAuth.js

* NextJS -> Next.js

* fix guides

* add docusaurus type

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-15 16:39:33 +01:00
Lluis Agusti
cb56cd44ca refactor(docs): re-structure (#4498)
* docs: beta initial commit

* docs(oauth): finish initial tutorial

* docs(oauth-tutorial): finish guide

* docs(docusaurus): just log broken links

* docs: re-organising beta

* docs(beta): sort documents for sorting

* docs: more re-structure

* docs: more re-structure (2)

* fix: more WIP

* fix: more WIP

* chore: more updates

* chore: wip

* chore: wip

* fix lock file

* docs(getting-started): credentials

* chore: remove json-server file

* chore: cleanup

* remove mongodb from dev app

* chore: cleanup

* revert

* chore: cleanup

* chore: more cleanup changes

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-15 15:45:33 +01:00
Mischa Spiegelmock
6758e1c6d1 refactor(core): allow trusting the forwarded host header (#5561)
* Non vercel-specific way to forward host header

* Update packages/next-auth/src/utils/detect-host.ts

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

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-15 14:17:20 +02:00
Thang Vu
462cca1087 chore(release): bump package version(s) [skip ci] 2022-10-14 08:52:04 +07:00
Thang Vu
ab48fcfe5b chore: remove codeql run on main push 2022-10-14 08:37:59 +07:00
Thang Vu
fe7aaeded8 fix(ts): TS Module Augmentation (#5556)
* fix: TS Module Augmentation

* match type to AdapterUser

* refactor authorize callback

* Apply suggestions from code review

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-13 09:39:12 +07:00
Anthony Shew
c53c09ea5c docs: options.md grammar fixes (#5562)
Update options.md

Just some grammar!
2022-10-12 20:07:53 +01:00
Matteo Giardino
4bcba45294 docs(client): typo (#5545) 2022-10-11 01:44:15 +01:00
David Walsh
eb5a9bad9d chore(dev): update SvelteKit playground to 1.0.0-next.511 (#5531)
* Update playground-sveltekit to sveltekit rc 511

* Remove prettier config and format

* Fix adapter comment
2022-10-10 18:20:51 +02:00
Balázs Orbán
9a6d95c17c chore: fix TS lint 2022-10-10 02:11:46 +02:00
Balázs Orbán
5b2fc7b570 chore: fix neo4j build 2022-10-10 02:04:09 +02:00
Balázs Orbán
6f459225fa Merge branch 'main' of github.com:nextauthjs/next-auth 2022-10-10 00:30:25 +02:00
Balázs Orbán
f38ee19a8a chore(dev): improve DX 2022-10-10 00:30:22 +02:00
Ranjan Purbey
38a03ed7d8 feat(providers): Add Pinterest Provider (#5485)
* feat(providers): Add Pinterest Provider

* Apply suggestions from code review

* Update pinterest.ts

* Update pinterest.ts

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-09 23:18:45 +01:00
Chris Abernethy
e1eb684cc6 fix(providers): change EVE Online to OAuth2 (#5459) 2022-10-10 00:16:17 +02:00
Thang Vu
777b7b2f23 chore(release): bump package version(s) [skip ci] 2022-10-09 22:52:53 +07:00
Balázs Orbán
6132c3fa75 fix(ts): match TS types better with implementation (#4953)
* refactor(ts): export `AdapterAccount` from `next-auth/adapters`

* chore: run linter, remove prisma warning

* fix(ts): match TS with implementation closer

* remove unused import

* rename error

* add missing dev dependency

* fix type

* fix type

* fix more types and tests

* remove unused `id`

* skip upstash tests in CI

* revert some changes

* fix type

* revert some change

* revert some change

* revert some change

* revert some changes

* update lock file

* revert line change

* revert some change

* improve adapter & oauth typing

* fix test, revert

* apply review suggestion

* Add test for new rejection logics

* Update assert.test.ts

* fix: Hubspot config

* restore some ts-expect-error

* fix: tests in mirko-orm

* fix: remove redundant id: string

* fix: use ts-expect-errors

* fix: simplify provider type

* fix: normalize user options

* restore ts-expect-errors

Co-authored-by: Thang Vu <hi@thvu.dev>
2022-10-09 21:54:01 +07:00
Usman Sabuwala (Max Programming)
94beef77e6 docs: Remove extra space in code (#5515) 2022-10-09 13:40:38 +02:00
Philipp
490d59dd17 fix(middleware): improve handling of custom Next.js basePath (#5109)
* fix(middleware): improve handling of custom nextjs basePath

* fix(middleware): improve extraction of nextjs base path from req.nextUrl

* adapt to req.nextUrl.basePath

* Fix indent

* Add middleware test for custom-base and simplified code a little bit

* Fix indent

* Add another test

* Rename basePath and nextJsBasePath

* Fix lint error
2022-10-09 11:31:28 +07:00
Thang Vu
26a8c5fc6d chore: lint in apps (#5507) 2022-10-06 22:14:12 +01:00
Colby Fayock
e26ec74720 docs(tutorial): Creating a Custom Adapter (#5506)
* Add new item to tutorials page

* Update tutorials.md

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-06 22:12:20 +01:00
Max Peintner
d13997e140 feat(providers): ZITADEL provider (#5479)
* feat: zitadel provider

* Update packages/next-auth/src/providers/zitadel.ts

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

* Update packages/next-auth/src/providers/zitadel.ts

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

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-06 09:44:21 +02:00
Balázs Orbán
d6efda077d chore(release): bump package version(s) [skip ci] 2022-10-05 19:30:28 +02:00
Eric Carboni
0a4b99de3b chore(docs): update middleware documentation link (#5492)
closes #5489
2022-10-04 19:25:56 +02:00
Daniel
2d2dfecc9d docs(core): update documentation callbacks to include user id as example (#5465)
* Add user id to `session` and `jwt` callback

* Minor changes

- Notes on why the id is not exposed by default is already documented in the `session` section.

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-03 16:03:33 +02:00
Thang Vu
2a2c3d7a45 chore: add security guidelines to PR & issue template (#5470)
* chore: add security guidelines to pr & issue template

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-03 15:59:19 +02:00
kesoji
82786ac440 chore: remove duplicate key in pacakges/tsconfig/package.json (#5469)
fix: remove duplicate key
2022-10-02 20:51:17 +02:00
Vedant Nandwana
dfe3e02132 docs(adapters): Add TS type to prisma client (#5463)
* docs(adapters): Add prisma client docs for typescript users

Add documentation for connecting prisma client w/ prisma adapter for typescript users.

* docs(adapters): remove prismadb.js for prismadb.ts

remove prismadb.js as it is identical to the prismadb.ts

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-01 22:17:41 +02:00
Itunu Lamina
92b38ed740 docs: fix 'JWKKeySupport' typo (#5452)
update 'JWKKeySupport' typo error
2022-09-29 15:34:23 +02:00
Tom Freudenberg
97feae7916 fix(types): export SessionContext #5437 (#5438)
Co-authored-by: Lluis Agusti <hi@llu.lu>

Fixes #5437
2022-09-28 18:48:42 +02:00
Balázs Orbán
24945895e9 chore(release): bump package version(s) [skip ci] 2022-09-28 18:10:38 +02:00
Balázs Orbán
6deccf610f fix(core): return JSON for non-HTML server route errors (#5442)
* fix(core): return JSON for non-HTML server route errors

* refactor: throw in `unstable_getServerSession`

* test: expect `unstable_getServerSession` to throw

* refactor: destructure

* fix unrelated test formatting

* catch error page
2022-09-28 17:01:39 +01:00
Etienne Martin
f770b90219 fix(react): safe use of localStorage API (#5444)
fix: safe use of localstorage

Co-authored-by: Etienne <>
2022-09-28 16:54:07 +01:00
Balázs Orbán
87f4786917 chore: bump release package 2022-09-28 13:51:41 +02:00
Balázs Orbán
191ef06471 chore(release): bump package version(s) [skip ci] 2022-09-28 13:00:32 +02:00
Philip
75e6d8f0aa docs(adapters): Update prisma.md (#5366)
* Update prisma.md

The referenced official doc page describes how to fix the `warn(prisma-client) There are already 10 instances of Prisma Client actively running.` error in development mode.

* Update prisma.md

Implemented best practice for Prisma Client creation.

* Fixed typo in Prisma db filename.
2022-09-28 11:15:55 +01:00
Yixuan Xu
17999edd30 chore(example): fix hydrate problem in react18 (#5439) 2022-09-28 10:50:40 +02:00
Tom Freudenberg
54b1845e58 fix(core): don't lock next in peerDependencies #5427 (#5430)
* Update peerDependencies #5427

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-27 00:04:50 +01:00
Tomas Pozo
879faf9fab docs(middleware): add tip on additional matcher patterns (#5404)
* docs(middleware): add tip on additional matcher patterns

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-26 13:39:32 +02:00
Balázs Orbán
3e3c36891e docs(example): use generic type in AppProps
closes #5401
2022-09-25 10:57:44 +01:00
Balázs Orbán
ac5d8a9795 chore(release): bump package version(s) [skip ci] 2022-09-25 11:42:17 +02:00
Matt Oliver
965c6267e2 feat(core): make session token with DB session strategy customizable (#5328)
* Add option for custom generateSessionToken

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-25 10:26:59 +01:00
Sébastien Vanvelthem
bfc429d20b fix: update jose to fix nextjs edge error with middleware (#5372)
fix: update jose to fix nextjs edge error
2022-09-25 15:46:02 +07:00
Balázs Orbán
2d8e910a19 chore(release): bump package version(s) [skip ci] 2022-09-25 10:29:56 +02:00
voinik
d16e04848e fix(adapters): check token during email verification in Upstash Adapter (#5377)
* Check token during email verification

* Undo accidental linter fix

* Update index.ts

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-25 09:10:55 +01:00
319 changed files with 24406 additions and 2778 deletions

View File

@@ -3,10 +3,27 @@ const path = require("path")
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
parserOptions: {
project: [path.resolve(__dirname, "./packages/**/tsconfig.eslint.json")],
},
extends: ["standard-with-typescript", "prettier"],
overrides: [
{
files: ["*.ts", "*.tsx"],
extends: ["standard-with-typescript", "prettier"],
rules: {
camelcase: "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/restrict-template-expressions": "off",
},
parserOptions: {
project: [
path.resolve(__dirname, "./packages/**/tsconfig.eslint.json"),
path.resolve(__dirname, "./apps/**/tsconfig.json"),
],
},
},
],
extends: ["prettier"],
globals: {
localStorage: "readonly",
location: "readonly",
@@ -14,10 +31,6 @@ module.exports = {
},
rules: {
camelcase: "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/restrict-template-expressions": "off",
},
plugins: ["jest"],
env: {

View File

@@ -5,6 +5,7 @@ body:
- type: markdown
attributes:
value: |
**NOTE:** Issues that are potentially security related should be reported to us by following the [Security guidelines](https://next-auth.js.org/security) rather than on GitHub.
Thanks for taking the time to fill out this issue after reading/searching through the [documentation](https://next-auth.js.org) first!
Is this your first time contributing? Check out this video: https://www.youtube.com/watch?v=cuoNzXFLitc

View File

@@ -5,6 +5,7 @@ body:
- type: markdown
attributes:
value: |
**NOTE:** Issues that are potentially security related should be reported to us by following the [Security guidelines](https://next-auth.js.org/security) rather than on GitHub.
Thanks for taking the time to fill out this [Provider](https://next-auth.js.org/providers/overview) related issue!
Is this your first time contributing? Check out this video: https://www.youtube.com/watch?v=cuoNzXFLitc
@@ -67,6 +68,7 @@ body:
- "Slack"
- "Spotify"
- "Strava"
- "Todoist"
- "Trakt"
- "Twitch"
- "Twitter"

View File

@@ -5,6 +5,7 @@ body:
- type: markdown
attributes:
value: |
**NOTE:** Issues that are potentially security related should be reported to us by following the [Security guidelines](https://next-auth.js.org/security) rather than on GitHub.
Thanks for taking the time to fill out this [Adapter](https://next-auth.js.org/adapters/overview) related issue!
Is this your first time contributing? Check out this video: https://www.youtube.com/watch?v=cuoNzXFLitc
@@ -32,6 +33,7 @@ body:
- "@next-auth/sequelize-adapter"
- "@next-auth/typeorm-legacy-adapter"
- "@next-auth/upstash-redis-adapter"
- "@next-auth/xata-adapter"
validations:
required: true
- type: textarea

View File

@@ -9,6 +9,7 @@ body:
- type: markdown
attributes:
value: |
**NOTE:** Issues that are potentially security related should be reported to us by following the [Security guidelines](https://next-auth.js.org/security) rather than on GitHub.
Thank you very much for reaching out to us regarding the awesome feature that you believe should be included in the NextAuth.js library.
_NOTE: Feature requests are converted to [discussions (Ideas 💡)](https://github.com/nextauthjs/next-auth/discussions/categories/ideas). Make sure your idea hasn't been asked yet, and upvote the existing one before opening a new instead._

View File

@@ -17,6 +17,7 @@ body:
- type: markdown
attributes:
value: |
**NOTE:** Issues that are potentially security related should be reported to us by following the [Security guidelines](https://next-auth.js.org/security) rather than on GitHub.
Make sure you [link]() to external documentation if necessary and provide inline code examples like so:
```js

View File

@@ -9,6 +9,7 @@ body:
- type: markdown
attributes:
value: |
**NOTE:** Issues that are potentially security related should be reported to us by following the [Security guidelines](https://next-auth.js.org/security) rather than on GitHub.
We are glad that you have a question about this library. Please provide the following information:
- type: textarea

View File

@@ -5,9 +5,14 @@ Please fill out the information below to expedite the review and (hopefully)
merge of your pull request!
-->
> _NOTE_:
>
> - It's a good idea to open an issue first to discuss potential changes.
> - Please make sure that you are _NOT_ opening a PR to fix a potential security vulnerability. Instead, please follow the [Security guidelines](../Security.md) to disclose the issue to us confidentially.
## ☕️ Reasoning
What changes are being made? What feature/bug is being fixed here?
<!-- What changes are being made? What feature/bug is being fixed here? -->
## 🧢 Checklist
@@ -23,6 +28,7 @@ Fixes: INSERT_ISSUE_LINK_HERE
## 📌 Resources
- [Contributing guidelines](./CONTRIBUTING.md)
- [Code of conduct](./CODE_OF_CONDUCT.md)
- [Security guidelines](../Security.md)
- [Contributing guidelines](../CONTRIBUTING.md)
- [Code of conduct](../CODE_OF_CONDUCT.md)
- [Contributing to Open Source](https://kcd.im/pull-request)

View File

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

View File

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

View File

@@ -2,7 +2,7 @@ name: Code Analysis
on:
push:
branches: [main, beta, next]
branches: [beta, next]
pull_request:
branches: [main]
schedule:

View File

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

2
.nvmrc
View File

@@ -1 +1 @@
16
18

View File

@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting info@balazsorban.com, yo@ndo.dev, thvu@hey.com and me@iaincollins.com.
reported by contacting hi@thvu.dev, info@balazsorban.com, yo@ndo.dev and me@iaincollins.com.
All complaints will be reviewed and investigated and will result in a response
that is deemed necessary and appropriate to the circumstances. The project team
is obligated to maintain confidentiality with regard to the reporter of an

View File

@@ -26,7 +26,6 @@ Anyone can be a contributor. Either you found a typo, or you have an awesome fea
A quick guide on how to setup _next-auth_ locally to work on it and test out any changes:
1. Clone the repo:
```sh
@@ -34,13 +33,21 @@ git clone git@github.com:nextauthjs/next-auth.git
cd next-auth
```
1. Install packages. Developing requires Node.js v16:
2. Set up the correct pnpm version, using [Corepack](https://nodejs.org/api/corepack.html). Run the following in the project'a root:
```sh
corepack enable pnpm
```
(Now, if you run `pnpm --version`, it should print the same verion as the `packageManager` property in the [`package.json` file](https://github.com/nextauthjs/next-auth/blob/main/package.json))
3. Install packages. Developing requires Node.js v18:
```sh
pnpm install
```
3. Populate `.env.local`:
4. Populate `.env.local`:
Copy `apps/dev/.env.local.example` to `apps/dev/.env.local`, and add your env variables for each provider you want to test.
@@ -52,11 +59,12 @@ cp .env.local.example .env.local
> NOTE: You can add any environment variables to .env.local that you would like to use in your dev app.
> You can find the next-auth config under`apps/dev/pages/api/auth/[...nextauth].js`.
4. Start the developer application/server:
5. Start the developer application/server:
```sh
pnpm dev
```
Your developer application will be available on `http://localhost:3000`
That's it! 🎉

View File

@@ -13,7 +13,7 @@ If you contact us regarding a serious issue:
- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
The best way to report an issue is by contacting us via email at info@balazsorban.com, yo@ndo.dev, thvu@hey.com and me@iaincollins.com, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
The best way to report an issue is by contacting us via email at hi@thvu.dev, info@balazsorban.com, yo@ndo.dev and me@iaincollins.com, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
> For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these publicly as bug reports or feature requests or to raise a question to open a discussion around them.

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,6 +6,7 @@
"scripts": {
"clean": "rm -rf .next",
"dev": "next dev",
"lint": "next lint",
"build": "next build",
"start": "next start",
"email": "fake-smtp-server",
@@ -18,7 +19,7 @@
"@next-auth/typeorm-legacy-adapter": "workspace:*",
"@prisma/client": "^3",
"faunadb": "^4",
"next": "12.2.0",
"next": "13.0.2",
"next-auth": "workspace:*",
"nodemailer": "^6",
"react": "^18",

View File

@@ -18,6 +18,7 @@ import Freshbooks from "next-auth/providers/freshbooks"
import GitHub from "next-auth/providers/github"
import Gitlab from "next-auth/providers/gitlab"
import Google from "next-auth/providers/google"
import Hubspot from "next-auth/providers/hubspot"
import IDS4 from "next-auth/providers/identity-server4"
import Instagram from "next-auth/providers/instagram"
import Keycloak from "next-auth/providers/keycloak"
@@ -29,53 +30,44 @@ import Osu from "next-auth/providers/osu"
import Patreon from "next-auth/providers/patreon"
import Slack from "next-auth/providers/slack"
import Spotify from "next-auth/providers/spotify"
import Todoist from "next-auth/providers/todoist"
import Trakt from "next-auth/providers/trakt"
import Twitch from "next-auth/providers/twitch"
import Twitter, { TwitterLegacy } from "next-auth/providers/twitter"
import Vk from "next-auth/providers/vk"
import Wikimedia from "next-auth/providers/wikimedia"
import WorkOS from "next-auth/providers/workos"
import Zitadel from "next-auth/providers/zitadel"
// Adapters
import { PrismaClient } from "@prisma/client"
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { Client as FaunaClient } from "faunadb"
import { FaunaAdapter } from "@next-auth/fauna-adapter"
import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
// Add an adapter you want to test here.
const adapters = {
prisma() {
const client = globalThis.prisma || new PrismaClient()
if (process.env.NODE_ENV !== "production") globalThis.prisma = client
return PrismaAdapter(client)
},
typeorm() {
return TypeORMLegacyAdapter({
type: "sqlite",
name: "next-auth-test-memory",
database: "./typeorm/dev.db",
synchronize: true,
})
},
fauna() {
const client =
globalThis.fauna ||
new FaunaClient({
secret: process.env.FAUNA_SECRET,
domain: process.env.FAUNA_DOMAIN,
})
if (process.env.NODE_ENV !== "production") global.fauna = client
return FaunaAdapter(client)
},
noop() {
return undefined
},
}
// // Prisma
// import { PrismaClient } from "@prisma/client"
// import { PrismaAdapter } from "@next-auth/prisma-adapter"
// const client = globalThis.prisma || new PrismaClient()
// if (process.env.NODE_ENV !== "production") globalThis.prisma = client
// const adapter = PrismaAdapter(client)
// // Fauna
// import { Client as FaunaClient } from "faunadb"
// import { FaunaAdapter } from "@next-auth/fauna-adapter"
// const opts = { secret: process.env.FAUNA_SECRET, domain: process.env.FAUNA_DOMAIN }
// const client = globalThis.fauna || new FaunaClient(opts)
// if (process.env.NODE_ENV !== "production") globalThis.fauna = client
// const adapter = FaunaAdapter(client)
// // TypeORM
// import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
// const adapter = TypeORMLegacyAdapter({
// type: "sqlite",
// name: "next-auth-test-memory",
// database: "./typeorm/dev.db",
// synchronize: true,
// })
export const authOptions: NextAuthOptions = {
adapter: adapters.noop(),
debug: true,
// adapter,
debug: process.env.NODE_ENV !== "production",
theme: {
logo: "https://next-auth.js.org/img/logo/logo-sm.png",
brandColor: "#1786fb",
@@ -102,6 +94,7 @@ export const authOptions: NextAuthOptions = {
GitHub({ clientId: process.env.GITHUB_ID, clientSecret: process.env.GITHUB_SECRET }),
Gitlab({ clientId: process.env.GITLAB_ID, clientSecret: process.env.GITLAB_SECRET }),
Google({ clientId: process.env.GOOGLE_ID, clientSecret: process.env.GOOGLE_SECRET }),
Hubspot({ clientId: process.env.HUBSPOT_ID, clientSecret: process.env.HUBSPOT_SECRET }),
IDS4({ clientId: process.env.IDS4_ID, clientSecret: process.env.IDS4_SECRET, issuer: process.env.IDS4_ISSUER }),
Instagram({ clientId: process.env.INSTAGRAM_ID, clientSecret: process.env.INSTAGRAM_SECRET }),
Keycloak({ clientId: process.env.KEYCLOAK_ID, clientSecret: process.env.KEYCLOAK_SECRET, issuer: process.env.KEYCLOAK_ISSUER }),
@@ -113,6 +106,7 @@ export const authOptions: NextAuthOptions = {
Patreon({ clientId: process.env.PATREON_ID, clientSecret: process.env.PATREON_SECRET }),
Slack({ clientId: process.env.SLACK_ID, clientSecret: process.env.SLACK_SECRET }),
Spotify({ clientId: process.env.SPOTIFY_ID, clientSecret: process.env.SPOTIFY_SECRET }),
Todoist({ clientId: process.env.TODOIST_ID, clientSecret: process.env.TODOIST_SECRET }),
Trakt({ clientId: process.env.TRAKT_ID, clientSecret: process.env.TRAKT_SECRET }),
Twitch({ clientId: process.env.TWITCH_ID, clientSecret: process.env.TWITCH_SECRET }),
Twitter({ version: "2.0", clientId: process.env.TWITTER_ID, clientSecret: process.env.TWITTER_SECRET }),
@@ -120,6 +114,7 @@ export const authOptions: NextAuthOptions = {
Vk({ clientId: process.env.VK_ID, clientSecret: process.env.VK_SECRET }),
Wikimedia({ clientId: process.env.WIKIMEDIA_ID, clientSecret: process.env.WIKIMEDIA_SECRET }),
WorkOS({ clientId: process.env.WORKOS_ID, clientSecret: process.env.WORKOS_SECRET }),
Zitadel({ issuer: process.env.ZITADEL_ISSUER, clientId: process.env.ZITADEL_CLIENT_ID, clientSecret: process.env.ZITADEL_CLIENT_SECRET }),
],
}

View File

@@ -9,6 +9,7 @@ export default async (req, res) => {
res.send({
content:
"This is protected content. You can access this content because you are signed in.",
session,
})
} else {
res.send({

View File

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

View File

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

18
apps/dev/types/nextauth.d.ts vendored Normal file
View File

@@ -0,0 +1,18 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import NextAuth from "next-auth"
declare module "next-auth" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user: {
/** The user's postal address. */
address: string
} & User
}
interface User {
foo: string
}
}

View File

@@ -1,110 +1,20 @@
# Logs
.DS_Store
node_modules/
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.yarn-integrity
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
*.tsbuildinfo
next-env.d.ts
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
.vercel
.now
.env.local
.DS_Store
.env*.local

View File

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

View File

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

View File

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

View File

@@ -2,12 +2,16 @@ import { SessionProvider } from "next-auth/react"
import "./styles.css"
import type { AppProps } from "next/app"
import type { Session } from "next-auth"
// Use of the <SessionProvider> is mandatory to allow components that call
// `useSession()` anywhere in your application to access the `session` object.
export default function App({ Component, pageProps }: AppProps) {
export default function App({
Component,
pageProps: { session, ...pageProps },
}: AppProps<{ session: Session }>) {
return (
<SessionProvider session={pageProps.session} refetchInterval={0}>
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
)

View File

@@ -4,8 +4,7 @@ import Layout from "../components/layout"
import AccessDenied from "../components/access-denied"
export default function ProtectedPage() {
const { data: session, status } = useSession()
const loading = status === "loading"
const { data: session } = useSession()
const [content, setContent] = useState()
// Fetch content from protected route
@@ -19,9 +18,7 @@ export default function ProtectedPage() {
}
fetchData()
}, [session])
// When rendering client side don't display anything until loading is complete
if (typeof window !== "undefined" && loading) return null
// If no session exists, display access denied message
if (!session) {

View File

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

View File

@@ -0,0 +1,12 @@
root = true
[*]
indent_size = 2
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@@ -0,0 +1,4 @@
dist
node_modules
tsconfig.json
package.json

View File

@@ -0,0 +1,10 @@
{
"extends": [
"@nuxtjs/eslint-config-typescript"
],
"rules": {
"@typescript-eslint/no-unused-vars": [
"off"
]
}
}

52
apps/playground-nuxt/.gitignore vendored Normal file
View File

@@ -0,0 +1,52 @@
# Dependencies
node_modules
# Logs
*.log*
# Temp directories
.temp
.tmp
.cache
# Yarn
**/.yarn/cache
**/.yarn/*state*
# Generated dirs
dist
# Nuxt
.nuxt
.output
.vercel_build_output
.build-*
.env
.netlify
# Env
.env
# Testing
reports
coverage
*.lcov
.nyc_output
# VSCode
.vscode
# Intellij idea
*.iml
.idea
# OSX
.DS_Store
.AppleDouble
.LSOverride
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
.vercel

View File

@@ -0,0 +1 @@
imports.autoImport=false

View File

@@ -0,0 +1,108 @@
# NextAuth + Nuxt 3 Playground
NextAuth.js is committed to bringing easy authentication to other frameworks. [#2294](https://github.com/nextauthjs/next-auth/issues/2294)
Nuxt 3 support with NextAuth.js is currently experimental. This directory contains a minimal, proof-of-concept application. Parts of this is expected to be abstracted away into a package like` @next-auth/nuxt.`
This package uses Nuxt's [module starter](https://github.com/nuxt/starter/tree/module).
Demo: https://next-auth-nuxt-demo.vercel.app
## Getting Started
### Add the module to the modules section of `nuxt.config.ts`:
```ts
export default defineNuxtConfig({
// temporary module name.
modules: ['next-auth-nuxt'],
// https://v3.nuxtjs.org/migration/runtime-config#runtime-config
runtimeConfig: {
secret: process.env.NEXTAUTH_SECRET
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
}
},
// https://v3.nuxtjs.org/guide/concepts/esm#aliasing-libraries
// Fix for GithubProvider (or whichever provider you choose) is not a function error in Vite
alias: {
'next-auth/providers/github': 'node_modules/next-auth/providers/github.js'
}
})
```
### Add API route
To add `NextAuth.js` to a project create a file called `[...].ts` in `server/api/auth`. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
```ts
// ~/server/api/auth/[...].ts
import { NextAuthNuxtHandler } from 'next-auth-nuxt/handler'
import GithubProvider from 'next-auth/providers/github'
const runtimeConfig = useRuntimeConfig()
export const authOptions = {
secret: runtimeConfig.secret,
providers: [
GithubProvider({
clientId: runtimeConfig.github.clientId,
clientSecret: runtimeConfig.github.clientSecret
}),
],
}
export default NextAuthNuxtHandler(authOptions)
```
All requests to `/api/auth/*` (`signIn`, `callback`, `signOut`, etc.) will automatically be handled by NextAuth.js.
### Frontend - Add Vue Composable
The `useSession()` Vue Composable is the easiest way to check if someone is signed in.
```html
<script setup lang="ts">
const { data: session } = useSession()
</script>
<template>
<div v-if="session">
Signed in as {{ session.user.email }} <br />
<button @click="signOut">Sign out</button>
</div>
<div v-else>
Not signed in <br />
<button @click="signIn">Sign in</button>
</div>
</template>
```
### Backend - API Route
To protect an API Route, you can use the `getServerSession()` method.
```ts
import { getServerSession } from 'next-auth-nuxt/handler'
import { authOptions } from '~/server/api/auth/[...]'
export default defineEventHandler(async (event) => {
const session = await getServerSession(event, authOptions)
if (session) {
return {
content: 'This is protected content. You can access this content because you are signed in.'
}
}
return {
error: 'You must be signed in to view the protected content on this page.'
}
})
```
## Development
- Run `pnpm dev:generate` to generate type stubs.
- Use `pnpm dev` to start `playground` in development mode.

1
apps/playground-nuxt/client.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from './dist/runtime/client'

1
apps/playground-nuxt/handler.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from './dist/runtime/server/handler'

View File

@@ -0,0 +1,49 @@
{
"name": "next-auth-nuxt",
"type": "module",
"version": "0.0.0",
"packageManager": "pnpm@7.1.1",
"license": "MIT",
"main": "./dist/module.cjs",
"types": "./dist/types.d.ts",
"exports": {
".": {
"import": "./dist/module.mjs",
"require": "./dist/module.cjs"
},
"./handler": {
"import": "./dist/runtime/server/handler.mjs",
"types": "./dist/runtime/server/handler.d.ts"
},
"./client": {
"import": "./dist/runtime/client/index.mjs",
"types": "./dist/runtime/client/index.d.ts"
}
},
"files": [
"dist",
"handler.d.ts",
"client.d.ts"
],
"scripts": {
"prepack": "nuxt-module-build",
"dev": "pnpm prepack && nuxi dev playground",
"dev:build": "nuxi build playground",
"dev:build:vercel": "NITRO_PRESET=vercel nuxi build playground",
"dev:prepare": "nuxt-module-build --stub && nuxi prepare playground"
},
"dependencies": {
"@nuxt/kit": "^3.0.0-rc.13",
"h3": "^0.8.6",
"next-auth": "^4.16.2",
"pathe": "^0.3.9"
},
"devDependencies": {
"@nuxt/module-builder": "^0.2.0",
"@nuxt/schema": "^3.0.0-rc.12",
"@nuxtjs/eslint-config-typescript": "^11.0.0",
"eslint": "^8.26.0",
"nuxt": "^3.0.0-rc.13",
"next-auth-nuxt": "workspace:*"
}
}

View File

@@ -0,0 +1,4 @@
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
NEXTAUTH_URL=
NEXTAUTH_SECRET=

View File

@@ -0,0 +1,40 @@
<template>
<div>
<Header />
<NuxtPage />
<Footer />
</div>
</template>
<style>
body {
font-family: -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
padding: 0 1rem 1rem 1rem;
max-width: 680px;
margin: 0 auto;
background: #fff;
color: #333;
}
li,
p {
line-height: 1.5rem;
}
a {
font-weight: 500;
}
hr {
border: 1px solid #ddd;
}
iframe {
background: #ccc;
border: 1px solid #ccc;
height: 10rem;
width: 100%;
border-radius: .5rem;
filter: invert(1);
}
</style>

View File

@@ -0,0 +1,8 @@
<template>
<div>
<h1>Access Denied</h1>
<p>
<a href="/api/auth/signin">You must be signed in to view this page</a>
</p>
</div>
</template>

View File

@@ -0,0 +1,30 @@
<template>
<footer class="fotter">
<hr>
<ul class="navItems">
<li class="navItem">
<a href="https://github.com/nextauthjs/next-auth/tree/main/apps/playground-nuxt">Demo GitHub</a>
</li>
<li class="navItem">
<a href="https://next-auth.js.org">Next.js Documentation</a>
</li>
</ul>
</footer>
</template>
<style>
.footer {
margin-top: 2rem;
}
.navItems {
margin-bottom: 1rem;
padding: 0;
list-style: none;
}
.navItem {
display: inline-block;
margin-right: 1rem;
}
</style>

View File

@@ -0,0 +1,155 @@
<script setup lang="ts">
import { useSession, signIn, signOut, computed } from '#imports'
const { data: session, status } = useSession()
const loading = computed(() => status.value === 'loading')
</script>
<template>
<header>
<div class="signedInStatus">
<p :class="['nojs-show', !session && loading ? 'loading' : 'loaded']">
<template v-if="session">
<span v-if="session.user?.image" :style="{ backgroundImage: `url(${session.user.image})` }" class="avatar" />
<span class="signedInText">
<small>Signed in as</small><br>
<strong>{{ session.user?.email || session.user?.name }}</strong>
</span>
<a href="/api/auth/signout" class="button" @click.prevent="signOut">Sign out</a>
</template>
<template v-else>
<span class="notSignedInText">You are not signed in</span>
<a href="/api/auth/signin" class="buttonPrimary" @click.prevent="signIn">Sign in</a>
</template>
</p>
</div>
<nav>
<ul class="navItems">
<li class="navItem">
<NuxtLink to="/">
Home
</NuxtLink>
</li>
<li class="navItem">
<NuxtLink to="/client">
Client
</NuxtLink>
</li>
<li class="navItem">
<NuxtLink to="/server">
Server
</NuxtLink>
</li>
<li class="navItem">
<NuxtLink to="/protected">
Protected
</NuxtLink>
</li>
<li class="navItem">
<NuxtLink to="/api-example">
API
</NuxtLink>
</li>
</ul>
</nav>
</header>
</template>
<style>
.nojs-show {
opacity: 1;
top: 0;
}
.signedInStatus {
display: block;
min-height: 4rem;
width: 100%;
}
.loading,
.loaded {
position: relative;
top: 0;
opacity: 1;
overflow: hidden;
border-radius: 0 0 .6rem .6rem;
padding: .6rem 1rem;
margin: 0;
background-color: rgba(0,0,0,.05);
transition: all 0.2s ease-in;
}
.loading {
top: -2rem;
opacity: 0;
}
.signedInText,
.notSignedInText {
position: absolute;
padding-top: .8rem;
left: 1rem;
right: 6.5rem;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
display: inherit;
z-index: 1;
line-height: 1.3rem;
}
.signedInText {
padding-top: 0rem;
left: 4.6rem;
}
.avatar {
border-radius: 2rem;
float: left;
height: 2.8rem;
width: 2.8rem;
background-color: white;
background-size: cover;
background-repeat: no-repeat;
}
.button,
.buttonPrimary {
float: right;
margin-right: -.4rem;
font-weight: 500;
border-radius: .3rem;
cursor: pointer;
font-size: 1rem;
line-height: 1.4rem;
padding: .7rem .8rem;
position: relative;
z-index: 10;
background-color: transparent;
color: #555;
}
.buttonPrimary {
background-color: #346df1;
border-color: #346df1;
color: #fff;
text-decoration: none;
padding: .7rem 1.4rem;
}
.buttonPrimary:hover {
box-shadow: inset 0 0 5rem rgba(0,0,0,0.2)
}
.navItems {
margin-bottom: 2rem;
padding: 0;
list-style: none;
}
.navItem {
display: inline-block;
margin-right: 1rem;
}
</style>

View File

@@ -0,0 +1,20 @@
import MyModule from '../src/module'
export default defineNuxtConfig({
modules: [
MyModule
],
// https://v3.nuxtjs.org/migration/runtime-config#runtime-config
runtimeConfig: {
secret: process.env.NEXTAUTH_SECRET,
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
}
},
// https://v3.nuxtjs.org/guide/concepts/esm#aliasing-libraries
// Fix for GithubProvider is not a function error in Vite
alias: {
'next-auth/providers/github': 'node_modules/next-auth/providers/github.js'
}
})

View File

@@ -0,0 +1,4 @@
{
"name": "playground",
"private": true
}

View File

@@ -0,0 +1,15 @@
<template>
<div>
<h1>API Example</h1>
<p>The examples below show responses from the example API endpoints.</p>
<p>
<em>You must be signed in to see responses.</em>
</p>
<h2>Session</h2>
<p>/api/examples/session</p>
<iframe src="/api/examples/session" />
<h2>JSON Web Token</h2>
<p>/api/examples/jwt</p>
<iframe src="/api/examples/jwt" />
</div>
</template>

View File

@@ -0,0 +1,18 @@
<template>
<div>
<h1>Client Side Rendering</h1>
<p>
This page uses the <strong>useSession()</strong> Vue Composable in the <strong>&lt;Header/&gt;</strong> component.
</p>
<p>
The <strong>useSession()</strong> Vue Composable is easy to use and allows pages to render very quickly.
</p>
<p>
The advantage of this approach is that session state is shared between pages by using a provided session via <strong>Vue Plugin</strong> so
that navigation between pages using <strong>useSession()</strong> is very fast.
</p>
<p>
The disadvantage of <strong>useSession()</strong> is that it requires client side JavaScript.
</p>
</div>
</template>

View File

@@ -0,0 +1,8 @@
<template>
<div>
<h1>Nuxt 3 + NextAuth.js Example</h1>
<p>
This is an example site to demonstrate how to use <a href="https://v3.nuxtjs.org/">Nuxt 3</a> with <a href="https://next-auth.js.org">NextAuth.js</a> for authentication.
</p>
</div>
</template>

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import { useSession, useFetch, useLazyFetch } from '#imports'
import AccessDenied from '~/components/AccessDenied.vue'
const { data: session } = useSession()
const { data } = await useLazyFetch('/api/examples/protected', {
server: false
})
</script>
<template>
<div>
<AccessDenied v-if="!session" />
<template v-else>
<h1>Protected Page</h1>
<p><strong>{{ data?.content || "\u00a0" }}</strong></p>
</template>
</div>
</template>

View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
import { useFetch } from '#imports'
await useFetch('/api/examples/session')
</script>
<template>
<div>
<h1>Server Side Rendering</h1>
<p>
This page uses the <strong>getServerSession()</strong> method inside an api route and is fetched using the <strong>useFetch()</strong> composable.
</p>
<p>
Using <strong>getServerSession()</strong> is the recommended approach if you need to
support Server Side Rendering with authentication.
</p>
<p>
The advantage of Server Side Rendering is this page does not require client side JavaScript.
</p>
<p>
The disadvantage of Server Side Rendering is that this page is slower to render.
</p>
</div>
</template>

View File

@@ -0,0 +1,17 @@
import { NextAuthNuxtHandler } from 'next-auth-nuxt/handler'
import GithubProvider from 'next-auth/providers/github'
import type { NextAuthOptions } from 'next-auth'
const runtimeConfig = useRuntimeConfig()
export const authOptions: NextAuthOptions = {
secret: runtimeConfig.secret,
providers: [
GithubProvider({
clientId: runtimeConfig.github.clientId,
clientSecret: runtimeConfig.github.clientSecret
})
]
}
export default NextAuthNuxtHandler(authOptions)

View File

@@ -0,0 +1,10 @@
import { getToken } from 'next-auth/jwt'
export default defineEventHandler(async (event) => {
// @ts-expect-error: cookies property is not present in h3
event.req.cookies = parseCookies(event)
const token = await getToken({
req: event.req
})
return token
})

View File

@@ -0,0 +1,16 @@
import { getServerSession } from 'next-auth-nuxt/handler'
import { authOptions } from '../auth/[...]'
export default defineEventHandler(async (event) => {
const session = await getServerSession(event, authOptions)
if (session) {
return {
content: 'This is protected content. You can access this content because you are signed in.'
}
}
return {
error: 'You must be signed in to view the protected content on this page.'
}
})

View File

@@ -0,0 +1,7 @@
import { getServerSession } from 'next-auth-nuxt/handler'
import { authOptions } from '../auth/[...]'
export default defineEventHandler(async (event) => {
const session = await getServerSession(event, authOptions)
return session
})

6386
apps/playground-nuxt/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
packages:
- playground

View File

@@ -0,0 +1,40 @@
import { fileURLToPath } from 'url'
import { addImports, addPlugin, defineNuxtModule, extendViteConfig } from '@nuxt/kit'
import { resolve } from 'pathe'
export interface ModuleOptions {
}
export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'next-auth-nuxt',
configKey: 'auth'
},
defaults: {
},
async setup (_options, nuxt) {
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
addPlugin(resolve(runtimeDir, 'plugin.client'))
// Composables are auto-imported in client.
const client = resolve(runtimeDir, 'client')
await addImports([
{ name: 'getSession', from: client },
{ name: 'getCsrfToken', from: client },
{ name: 'getProviders', from: client },
{ name: 'signIn', from: client },
{ name: 'signOut', from: client },
{ name: 'useSession', from: client }
])
// We can safely expose this to client.
extendViteConfig((config) => {
config.define = config.define || {}
config.define['process.env.NEXTAUTH_URL'] = JSON.stringify(process.env.NEXTAUTH_URL)
config.define['process.env.NEXTAUTH_URL_INTERNAL'] = JSON.stringify(process.env.NEXTAUTH_URL_INTERNAL)
config.define['process.env.VERCEL_URL'] = JSON.stringify(process.env.VERCEL_URL)
})
}
})

View File

@@ -0,0 +1,369 @@
import type { NextAuthClientConfig } from 'next-auth/client/_utils'
import type { Plugin, Ref } from 'vue'
import { ref, reactive, computed, inject, toRefs } from 'vue'
import { BroadcastChannel, apiBaseUrl, fetchData, now } from 'next-auth/client/_utils'
import type { Session } from 'next-auth'
import type {
BuiltInProviderType,
RedirectableProviderType
} from 'next-auth/providers'
import type { H3EventContext } from 'h3'
import parseUrl from '../lib/parse-url'
import _logger, { proxyLogger } from '../lib/logger'
import type {
ClientSafeProvider,
LiteralUnion,
SessionProviderProps,
SignInAuthorizationParams,
SignInOptions,
SignInResponse,
SignOutParams,
SignOutResponse
} from '../types'
// This behaviour mirrors the default behaviour for getting the site name that
// happens server side in server/index.js
// 1. An empty value is legitimate when the code is being invoked client side as
// relative URLs are valid in that context and so defaults to empty.
// 2. When invoked server side the value is picked up from an environment
// variable and defaults to 'http://localhost:3000'.
const __NEXTAUTH: NextAuthClientConfig = {
baseUrl: parseUrl(process.env.NEXTAUTH_URL ?? process.env.VERCEL_URL).origin,
basePath: parseUrl(process.env.NEXTAUTH_URL).path,
baseUrlServer: parseUrl(
process.env.NEXTAUTH_URL_INTERNAL ??
process.env.NEXTAUTH_URL ??
process.env.VERCEL_URL
).origin,
basePathServer: parseUrl(
process.env.NEXTAUTH_URL_INTERNAL ?? process.env.NEXTAUTH_URL
).path,
_lastSync: 0,
_session: undefined,
_getSession: () => {}
}
export interface CtxOrReq {
req?: H3EventContext['req']
event?: { req: H3EventContext['req'] }
}
export type GetSessionParams = CtxOrReq & {
event?: 'storage' | 'timer' | 'hidden' | string
triggerEvent?: boolean
broadcast?: boolean
}
const logger = proxyLogger(_logger, __NEXTAUTH.basePath)
const broadcast = BroadcastChannel()
function isServer () {
return (process as any).server
}
export async function getSession (params?: GetSessionParams) {
const session = await fetchData<Session>(
'session',
__NEXTAUTH,
logger,
params
)
if (params?.broadcast ?? true) { broadcast.post({ event: 'session', data: { trigger: 'getSession' } }) }
return session
}
/**
* Returns the current Cross Site Request Forgery Token (CSRF Token)
* required to make POST requests (e.g. for signing in and signing out).
* You likely only need to use this if you are not using the built-in
* `signIn()` and `signOut()` methods.
*
* [Documentation](https://next-auth.js.org/getting-started/client#getcsrftoken)
*/
export async function getCsrfToken (params?: CtxOrReq) {
const response = await fetchData<{ csrfToken: string }>(
'csrf',
__NEXTAUTH,
logger,
params
)
return response?.csrfToken
}
/**
* It calls `/api/auth/providers` and returns
* a list of the currently configured authentication providers.
* It can be useful if you are creating a dynamic custom sign in page.
*
* [Documentation](https://next-auth.js.org/getting-started/client#getproviders)
*/
export async function getProviders () {
return await fetchData<
Record<LiteralUnion<BuiltInProviderType>, ClientSafeProvider>
>('providers', __NEXTAUTH, logger)
}
/**
* Client-side method to initiate a signin flow
* or send the user to the signin page listing all possible providers.
* Automatically adds the CSRF token to the request.
*
* [Documentation](https://next-auth.js.org/getting-started/client#signin)
*/
export async function signIn<
P extends RedirectableProviderType | undefined = undefined,
> (
provider?: LiteralUnion<BuiltInProviderType>,
options?: SignInOptions,
authorizationParams?: SignInAuthorizationParams
): Promise<
P extends RedirectableProviderType ? SignInResponse | undefined : undefined
> {
const { callbackUrl = window.location.href, redirect = true } = options ?? {}
const baseUrl = apiBaseUrl(__NEXTAUTH)
const providers = await getProviders()
if (!providers) {
window.location.href = `${baseUrl}/error`
return
}
if (!provider || !(provider in providers)) {
window.location.href = `${baseUrl}/signin?${new URLSearchParams({
callbackUrl
})}`
return
}
const isCredentials = providers[provider].type === 'credentials'
const isEmail = providers[provider].type === 'email'
const isSupportingReturn = isCredentials || isEmail
const signInUrl = `${baseUrl}/${
isCredentials ? 'callback' : 'signin'
}/${provider}`
const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`
const res = await fetch(_signInUrl, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
// @ts-expect-error: Internal
body: new URLSearchParams({
...options,
csrfToken: await getCsrfToken(),
callbackUrl,
json: true
})
})
const data = await res.json()
if (redirect || !isSupportingReturn) {
const url = data.url ?? callbackUrl
window.location.href = url
// If url contains a hash, the browser does not reload the page. We reload manually
if (url.includes('#')) { window.location.reload() }
return
}
const error = new URL(data.url).searchParams.get('error')
if (res.ok) { await __NEXTAUTH._getSession({ event: 'storage' }) }
return {
error,
status: res.status,
ok: res.ok,
url: error ? null : data.url
} as any
}
/**
* Signs the user out, by removing the session cookie.
* Automatically adds the CSRF token to the request.
*
* [Documentation](https://next-auth.js.org/getting-started/client#signout)
*/
export async function signOut<R extends boolean = true> (
options?: SignOutParams<R>
): Promise<R extends true ? undefined : SignOutResponse> {
const { callbackUrl = window.location.href } = options ?? {}
const baseUrl = apiBaseUrl(__NEXTAUTH)
const fetchOptions = {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
// @ts-expect-error: Internal
body: new URLSearchParams({
csrfToken: await getCsrfToken(),
callbackUrl,
json: true
})
}
const res = await fetch(`${baseUrl}/signout`, fetchOptions)
const data = await res.json()
broadcast.post({ event: 'session', data: { trigger: 'signout' } })
if (options?.redirect ?? true) {
const url = data.url ?? callbackUrl
window.location.href = url
// If url contains a hash, the browser does not reload the page. We reload manually
if (url.includes('#')) { window.location.reload() }
// @ts-expect-error: Internal
return
}
await __NEXTAUTH._getSession({ event: 'storage' })
return data
}
export function SessionProviderPlugin (options: SessionProviderProps): Plugin {
return {
install (app) {
const { basePath } = options
if (basePath) { __NEXTAUTH.basePath = basePath }
/**
* If session was `null`, there was an attempt to fetch it,
* but it failed, but we still treat it as a valid initial value.
*/
const hasInitialSession = options.session !== undefined
/** If session was passed, initialize as already synced */
__NEXTAUTH._lastSync = hasInitialSession ? now() : 0
if (hasInitialSession) { __NEXTAUTH._session = options.session }
const session = ref(options.session)
/** If session was passed, initialize as not loading */
const loading = ref(!hasInitialSession)
__NEXTAUTH._getSession = async ({ event } = {}) => {
try {
const storageEvent = event === 'storage'
// We should always update if we don't have a client session yet
// or if there are events from other tabs/windows
if (storageEvent || __NEXTAUTH._session === undefined) {
__NEXTAUTH._lastSync = now()
__NEXTAUTH._session = await getSession({
broadcast: !storageEvent
})
session.value = __NEXTAUTH._session
return
}
if (
// If there is no time defined for when a session should be considered
// stale, then it's okay to use the value we have until an event is
// triggered which updates it
!event ||
// If the client doesn't have a session then we don't need to call
// the server to check if it does (if they have signed in via another
// tab or window that will come through as a "stroage" event
// event anyway)
__NEXTAUTH._session === null ||
// Bail out early if the client session is not stale yet
now() < __NEXTAUTH._lastSync
) { return }
// An event or session staleness occurred, update the client session.
__NEXTAUTH._lastSync = now()
__NEXTAUTH._session = await getSession()
session.value = __NEXTAUTH._session
} catch (error) {
logger.error('CLIENT_SESSION_ERROR', error as Error)
} finally {
loading.value = false
}
}
__NEXTAUTH._getSession()
const { refetchOnWindowFocus = true } = options
// Listen for when the page is visible, if the user switches tabs
// and makes our tab visible again, re-fetch the session, but only if
// this feature is not disabled.
const visibilityHandler = () => {
if (refetchOnWindowFocus && document.visibilityState === 'visible') { __NEXTAUTH._getSession({ event: 'visibilitychange' }) }
}
document.addEventListener('visibilitychange', visibilityHandler, false)
const unsubscribeFromBroadcast = broadcast.receive(() =>
__NEXTAUTH._getSession({ event: 'storage' })
)
const { refetchInterval } = options
let refetchIntervalTimer: NodeJS.Timer
if (refetchInterval) {
refetchIntervalTimer = setInterval(() => {
if (__NEXTAUTH._session) { __NEXTAUTH._getSession({ event: 'poll' }) }
}, refetchInterval * 1000)
}
const originalUnmount = app.unmount
app.unmount = function nextAuthUnmount () {
document.removeEventListener('visibilitychange', visibilityHandler, false)
unsubscribeFromBroadcast?.()
clearInterval(refetchIntervalTimer)
__NEXTAUTH._lastSync = 0
__NEXTAUTH._session = undefined
__NEXTAUTH._getSession = () => {}
originalUnmount()
}
const status = computed(() => loading.value ? 'loading' : session.value ? 'authenticated' : 'unauthenticated')
const value = reactive({
data: session,
status
})
app.provide('SessionKey', value)
}
}
}
/**
* Vue Composable that gives you access
* to the logged in user's session data.
*
* [Documentation](https://next-auth.js.org/getting-started/client#usesession)
*/
export function useSession (): {
data: Ref<SessionProviderProps['session']>;
status: Ref<string>;
} {
if (typeof window === 'undefined') {
return {
data: ref(null),
status: ref('loading')
}
}
const value = inject<{
data: SessionProviderProps['session']
status: string
}>('SessionKey')
if (!value) {
throw new Error('Could not resolve provided session value')
}
const { data, status } = toRefs(value)
return {
data,
status
}
}

View File

@@ -0,0 +1,115 @@
import type { Adapter } from 'next-auth/adapters'
import type { EventCallbacks, LoggerInstance } from 'next-auth'
/**
* Same as the default `Error`, but it is JSON serializable.
* @source https://iaincollins.medium.com/error-handling-in-javascript-a6172ccdf9af
*/
export class UnknownError extends Error {
code: string
constructor (error: Error | string) {
super((error as Error)?.message ?? error)
this.name = 'UnknownError'
this.code = (error as any).code
if (error instanceof Error) { this.stack = error.stack }
}
toJSON () {
return {
name: this.name,
message: this.message,
stack: this.stack
}
}
}
export class OAuthCallbackError extends UnknownError {
name = 'OAuthCallbackError'
}
/**
* Thrown when an Email address is already associated with an account
* but the user is trying an OAuth account that is not linked to it.
*/
export class AccountNotLinkedError extends UnknownError {
name = 'AccountNotLinkedError'
}
export class MissingAPIRoute extends UnknownError {
name = 'MissingAPIRouteError'
code = 'MISSING_NEXTAUTH_API_ROUTE_ERROR'
}
export class MissingSecret extends UnknownError {
name = 'MissingSecretError'
code = 'NO_SECRET'
}
export class MissingAuthorize extends UnknownError {
name = 'MissingAuthorizeError'
code = 'CALLBACK_CREDENTIALS_HANDLER_ERROR'
}
export class MissingAdapter extends UnknownError {
name = 'MissingAdapterError'
code = 'EMAIL_REQUIRES_ADAPTER_ERROR'
}
export class UnsupportedStrategy extends UnknownError {
name = 'UnsupportedStrategyError'
code = 'CALLBACK_CREDENTIALS_JWT_ERROR'
}
type Method = (...args: any[]) => Promise<any>
export function upperSnake (s: string) {
return s.replace(/([A-Z])/g, '_$1').toUpperCase()
}
export function capitalize (s: string) {
return `${s[0].toUpperCase()}${s.slice(1)}`
}
/**
* Wraps an object of methods and adds error handling.
*/
export function eventsErrorHandler (
methods: Partial<EventCallbacks>,
logger: LoggerInstance
): Partial<EventCallbacks> {
return Object.keys(methods).reduce<any>((acc, name) => {
acc[name] = async (...args: any[]) => {
try {
const method: Method = methods[name as keyof Method]
return await method(...args)
} catch (e) {
logger.error(`${upperSnake(name)}_EVENT_ERROR`, e as Error)
}
}
return acc
}, {})
}
/** Handles adapter induced errors. */
export function adapterErrorHandler (
adapter: Adapter | undefined,
logger: LoggerInstance
): Adapter | undefined {
if (!adapter) { return }
return Object.keys(adapter).reduce<any>((acc, name) => {
acc[name] = async (...args: any[]) => {
try {
logger.debug(`adapter_${name}`, { args })
const method: Method = adapter[name as keyof Method]
return await method(...args)
} catch (error) {
logger.error(`adapter_error_${name}`, error as Error)
const e = new UnknownError(error as Error)
e.name = `${capitalize(name)}Error`
throw e
}
}
return acc
}, {})
}

View File

@@ -0,0 +1,113 @@
import { UnknownError } from './errors'
// TODO: better typing
/** Makes sure that error is always serializable */
function formatError (o: unknown): unknown {
if (o instanceof Error && !(o instanceof UnknownError)) { return { message: o.message, stack: o.stack, name: o.name } }
if (hasErrorProperty(o)) {
o.error = formatError(o.error) as Error
o.message = o.message ?? o.error.message
}
return o
}
function hasErrorProperty (
x: unknown
): x is { error: Error; [key: string]: unknown } {
return !!(x as any)?.error
}
export type WarningCode =
| 'NEXTAUTH_URL'
| 'NO_SECRET'
| 'TWITTER_OAUTH_2_BETA'
| 'DEBUG_ENABLED'
/**
* Override any of the methods, and the rest will use the default logger.
*
* [Documentation](https://next-auth.js.org/configuration/options#logger)
*/
export interface LoggerInstance extends Record<string, Function> {
warn: (code: WarningCode) => void
error: (
code: string,
/**
* Either an instance of (JSON serializable) Error
* or an object that contains some debug information.
* (Error is still available through `metadata.error`)
*/
metadata: Error | { error: Error; [key: string]: unknown }
) => void
debug: (code: string, metadata: unknown) => void
}
const _logger: LoggerInstance = {
error (code, metadata) {
metadata = formatError(metadata) as Error
console.error(
`[next-auth][error][${code}]`,
`\nhttps://next-auth.js.org/errors#${code.toLowerCase()}`,
metadata.message,
metadata
)
},
warn (code) {
console.warn(
`[next-auth][warn][${code}]`,
`\nhttps://next-auth.js.org/warnings#${code.toLowerCase()}`
)
},
debug (code, metadata) {
// eslint-disable-next-line no-console
console.log(`[next-auth][debug][${code}]`, metadata)
}
}
/**
* Override the built-in logger with user's implementation.
* Any `undefined` level will use the default logger.
*/
export function setLogger (
newLogger: Partial<LoggerInstance> = {},
debug?: boolean
) {
// Turn off debug logging if `debug` isn't set to `true`
if (!debug) { _logger.debug = () => {} }
if (newLogger.error) { _logger.error = newLogger.error }
if (newLogger.warn) { _logger.warn = newLogger.warn }
if (newLogger.debug) { _logger.debug = newLogger.debug }
}
export default _logger
/** Serializes client-side log messages and sends them to the server */
export function proxyLogger (
logger: LoggerInstance = _logger,
basePath?: string
): LoggerInstance {
try {
if (typeof window === 'undefined') { return logger }
const clientLogger: Record<string, unknown> = {}
for (const level in logger) {
clientLogger[level] = (code: string, metadata: Error) => {
_logger[level](code, metadata) // Logs to console
if (level === 'error') {
metadata = formatError(metadata) as Error
}(metadata as any).client = true
const url = `${basePath}/_log`
const body = new URLSearchParams({ level, code, ...(metadata as any) })
if (navigator.sendBeacon) { return navigator.sendBeacon(url, body) }
return fetch(url, { method: 'POST', body, keepalive: true })
}
}
return clientLogger as unknown as LoggerInstance
} catch {
return _logger
}
}

View File

@@ -0,0 +1,34 @@
export interface InternalUrl {
/** @default "http://localhost:3000" */
origin: string
/** @default "localhost:3000" */
host: string
/** @default "/api/auth" */
path: string
/** @default "http://localhost:3000/api/auth" */
base: string
/** @default "http://localhost:3000/api/auth" */
toString: () => string
}
/** Returns an `URL` like object to make requests/redirects from server-side */
export default function parseUrl (url?: string): InternalUrl {
const defaultUrl = new URL('http://localhost:3000/api/auth')
if (url && !url.startsWith('http')) { url = `https://${url}` }
const _url = new URL(url ?? defaultUrl)
const path = (_url.pathname === '/' ? defaultUrl.pathname : _url.pathname)
// Remove trailing slash
.replace(/\/$/, '')
const base = `${_url.origin}${path}`
return {
origin: _url.origin,
host: _url.host,
path,
base,
toString: () => base
}
}

View File

@@ -0,0 +1,7 @@
// @ts-expect-error: Nuxt auto-import
import { defineNuxtPlugin } from '#app'
import { SessionProviderPlugin } from './client'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(SessionProviderPlugin({}))
})

View File

@@ -0,0 +1,93 @@
import type { NextAuthAction, NextAuthOptions, Session } from 'next-auth'
import type { RequestInternal } from 'next-auth/core'
import { NextAuthHandler } from 'next-auth/core'
import {
appendHeader,
defineEventHandler,
isMethod,
sendRedirect,
setCookie,
readBody,
parseCookies,
getQuery
} from 'h3'
import type { H3Event } from 'h3'
export function NextAuthNuxtHandler (options: NextAuthOptions) {
return defineEventHandler(async (event) => {
// Catch-all route params in Nuxt goes to the underscore property
const nextauth = event.context.params._.split('/')
const req: RequestInternal | Request = {
host: process.env.NEXTAUTH_URL,
body: undefined,
query: getQuery(event),
headers: event.req.headers,
method: event.req.method,
cookies: parseCookies(event),
action: nextauth[0] as NextAuthAction,
providerId: nextauth[1],
error: nextauth[1]
}
if (isMethod(event, 'POST')) {
req.body = await readBody(event)
}
const response = await NextAuthHandler({
req,
options
})
const { headers, cookies, body, redirect, status = 200 } = response
event.res.statusCode = status
headers?.forEach((header) => {
appendHeader(event, header.key, header.value)
})
cookies?.forEach((cookie) => {
setCookie(event, cookie.name, cookie.value, cookie.options)
})
if (redirect) {
if (isMethod(event, 'POST')) {
const body = await readBody(event)
if (body?.json !== 'true') { await sendRedirect(event, redirect, 302) }
return {
url: redirect
}
} else {
await sendRedirect(event, redirect, 302)
}
}
return body
})
}
export async function getServerSession (
event: H3Event,
options: NextAuthOptions
): Promise<Session | null> {
options.secret = process.env.NEXTAUTH_SECRET
const session = await NextAuthHandler<Session>({
req: {
host: process.env.NEXTAUTH_URL,
action: 'session',
method: 'GET',
cookies: parseCookies(event),
headers: event.req.headers
},
options
})
const { body } = session
if (body && Object.keys(body).length) {
return body
}
return null
}

View File

@@ -0,0 +1,78 @@
import type { Session } from 'next-auth'
import type { BuiltInProviderType, ProviderType } from 'next-auth/providers'
export interface UseSessionOptions<R extends boolean> {
required: R
/** Defaults to `signIn` */
onUnauthenticated?: () => void
}
/**
* Util type that matches some strings literally, but allows any other string as well.
* @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611
*/
export type LiteralUnion<T extends U, U = string> =
| T
| (U & Record<never, never>)
export interface ClientSafeProvider {
id: LiteralUnion<BuiltInProviderType>
name: string
type: ProviderType
signinUrl: string
callbackUrl: string
}
export interface SignInOptions extends Record<string, unknown> {
/**
* Defaults to the current URL.
* @docs https://next-auth.js.org/getting-started/client#specifying-a-callbackurl
*/
callbackUrl?: string
/** @docs https://next-auth.js.org/getting-started/client#using-the-redirect-false-option */
redirect?: boolean
}
export interface SignInResponse {
error: string | undefined
status: number
ok: boolean
url: string | null
}
/** Match `inputType` of `new URLSearchParams(inputType)` */
export type SignInAuthorizationParams =
| string
| string[][]
| Record<string, string>
| URLSearchParams
/** @docs https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
export interface SignOutResponse {
url: string
}
export interface SignOutParams<R extends boolean = true> {
/** @docs https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1 */
callbackUrl?: string
/** @docs https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
redirect?: R
}
/** @docs: https://next-auth.js.org/getting-started/client#options */
export interface SessionProviderProps {
// children: React.ReactNode
session?: Session | null
baseUrl?: string
basePath?: string
/**
* A time interval (in seconds) after which the session will be re-fetched.
* If set to `0` (default), the session is not polled.
*/
refetchInterval?: number
/**
* `SessionProvider` automatically refetches the session when the user switches between windows.
* This option activates this behaviour if set to `true` (default).
*/
refetchOnWindowFocus?: boolean
}

View File

@@ -0,0 +1,4 @@
{
// https://v3.nuxtjs.org/concepts/typescript
"extends": "./playground/.nuxt/tsconfig.json"
}

View File

@@ -7,7 +7,7 @@ module.exports = {
"prettier",
],
plugins: ["svelte3", "@typescript-eslint"],
ignorePatterns: ["*.cjs"],
ignorePatterns: ["*.cjs", "build/**/*"],
overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),

View File

@@ -4,6 +4,15 @@ NextAuth.js is committed to bringing easy authentication to other frameworks. ht
SvelteKit support with NextAuth.js is currently experimental. This directory contains a minimal, proof-of-concept application. Parts of this is expected to be abstracted away into a package like `@next-auth/sveltekit`
## Running this Demo
- Copy `.env.example` to `.env`
- In `.env`, set `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET`
- See [https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app))
- When creating the OAuth app, set "Homepage URL" to `http://localhost:5173` and Authorization callack URL to `http://localhost:5173/api/auth/callback/github`
- In `.env`, set `NEXTAUTH_SECRET` to any random string
- Build and run the application: `yarn build && yarn start`
## Existing Project
### Add API Route

View File

@@ -6,14 +6,16 @@
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"start": "HOST=127.0.0.1 PORT=5173 ORIGIN=http://localhost:5173 node ./build",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "1.0.0-next.66",
"@sveltejs/kit": "1.0.0-next.443",
"@sveltejs/adapter-auto": "^1.0.0-next.80",
"@sveltejs/adapter-node": "1.0.0-next.96",
"@sveltejs/kit": "1.0.0-next.511",
"@types/cookie": "^0.5.1",
"@typescript-eslint/eslint-plugin": "^5.35.1",
"@typescript-eslint/parser": "^5.35.1",
@@ -27,7 +29,7 @@
"svelte-preprocess": "^4.10.7",
"tslib": "^2.4.0",
"typescript": "~4.8.2",
"vite": "^2.9.13"
"vite": "^3.1.0"
},
"type": "module",
"dependencies": {

View File

@@ -1,12 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>

View File

@@ -6,7 +6,9 @@ export const handle: Handle = async function handle({
resolve,
}): Promise<Response> {
const session = await getServerSession(event.request, nextAuthOptions)
event.locals.session = session
if (session) {
event.locals.session = session
}
return resolve(event)
}

View File

@@ -11,8 +11,8 @@ import {
NEXTAUTH_SECRET,
} from "$env/static/private"
import { PUBLIC_NEXTAUTH_URL } from "$env/static/public"
import getFormBody from "./utils/get-form-body"
// @ts-expect-error import is exported on .default during SSR
const github = GithubProvider?.default || GithubProvider
export const options: NextAuthOptions = {
@@ -24,9 +24,11 @@ export const options: NextAuthOptions = {
],
}
const toSvelteKitResponse = async (
const toSvelteKitResponse = async <
T extends string | any[] | Record<string, any>
>(
request: Request,
nextAuthResponse: NextAuthResponse<unknown>
nextAuthResponse: NextAuthResponse<T>
): Promise<Response> => {
const { cookies, redirect } = nextAuthResponse
@@ -50,14 +52,14 @@ const toSvelteKitResponse = async (
let status = nextAuthResponse.status || 200
if (redirect) {
let formData = null
let formData: FormData | null = null
try {
formData = await request.formData()
formData = getFormBody(formData)
} catch {
// no formData passed
}
if (formData?.json !== "true") {
const { json } = Object.fromEntries(formData ?? [])
if (json !== "true") {
status = 302
headers.set("Location", redirect)
} else {
@@ -79,17 +81,16 @@ const SKNextAuthHandler = async (
options: NextAuthOptions
): Promise<Response> => {
const [action, provider] = params.nextauth!.split("/")
let body = undefined
let body: FormData | undefined
try {
body = await request.formData()
body = getFormBody(body)
} catch {
// no formData passed
}
options.secret = NEXTAUTH_SECRET
const req: RequestInternal = {
host: PUBLIC_NEXTAUTH_URL,
body,
body: Object.fromEntries(body ?? []),
query: Object.fromEntries(url.searchParams),
headers: request.headers,
method: request.method,
@@ -135,8 +136,8 @@ export const getServerSession = async (
export const NextAuth = (
options: NextAuthOptions
): {
GET: (event) => Promise<unknown>
POST: (event) => Promise<unknown>
GET: (event: ServerLoadEvent) => Promise<unknown>
POST: (event: ServerLoadEvent) => Promise<unknown>
} => ({
GET: (event) => SKNextAuthHandler(event, options),
POST: (event) => SKNextAuthHandler(event, options),

View File

@@ -1,15 +0,0 @@
// https://dev.to/danawoodman/getting-form-body-data-in-your-sveltekit-endpoints-4a85
export default function getFormBody(
body: FormData | null
): Record<string, any> {
if (!body) return {}
// @ts-expect-error: Entries property type missing
return [...body.entries()].reduce((data, [k, v]) => {
const value = v
if (k in data)
data[k] = Array.isArray(data[k]) ? [...data[k], value] : [data[k], value]
else data[k] = value
return data
}, {})
}

View File

@@ -1,4 +1,4 @@
import adapter from "@sveltejs/adapter-auto"
import adapter from "@sveltejs/adapter-node" // or use https://github.com/sveltejs/kit/tree/master/packages/adapter-auto
import preprocess from "svelte-preprocess"
/** @type {import('@sveltejs/kit').Config} */
@@ -6,14 +6,8 @@ const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),
kit: {
adapter: adapter(),
// Override http methods in the Todo forms
methodOverride: {
allowed: ["PATCH", "DELETE"],
},
},
}

View File

@@ -10,14 +10,19 @@
regenerator-runtime "^0.13.4"
"@cloudflare/workers-types@^3.14.0":
version "3.15.0"
resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-3.15.0.tgz#b8b17f923181c61220880aaa8ef30d75d59a1219"
integrity sha512-meL/Afy5qdIsgfdnlbVfcYUh/YjHk23EWUvgmULf6iDrDbrBcd+fse2os3CC7rxSfScdP1OqJVTHgRSEjUm/Pw==
version "3.16.0"
resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-3.16.0.tgz#011658ca3f9810373e0eb4a2b5d6cabe4848d8d6"
integrity sha512-gaBUSaKS65mN3iKZEgichbXYEmAa/pXkc5Gbt+1BptYphdGkj09ggdsiE4w8g0F/uI1g36QaTKrzVnBAWMipvQ==
"@esbuild/linux-loong64@0.14.54":
version "0.14.54"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028"
integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==
"@esbuild/android-arm@0.15.10":
version "0.15.10"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.10.tgz#a5f9432eb221afc243c321058ef25fe899886892"
integrity sha512-FNONeQPy/ox+5NBkcSbYJxoXj9GWu8gVGJTVmUyoOCKQFDTrHVKgNSzChdNt0I8Aj/iKcsDf2r9BFwv+FSNUXg==
"@esbuild/linux-loong64@0.15.10":
version "0.15.10"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz#78a42897c2cf8db9fd5f1811f7590393b77774c7"
integrity sha512-w0Ou3Z83LOYEkwaui2M8VwIp+nLi/NA60lBLMvaJ+vXVMcsARYdEzLNE7RSm4+lSg4zq4d7fAVuzk7PNQ5JFgg==
"@eslint/eslintrc@^1.3.1":
version "1.3.1"
@@ -82,9 +87,9 @@
"@jridgewell/sourcemap-codec" "^1.4.10"
"@mapbox/node-pre-gyp@^1.0.5":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc"
integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==
version "1.0.10"
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c"
integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==
dependencies:
detect-libc "^2.0.0"
https-proxy-agent "^5.0.0"
@@ -127,6 +132,47 @@
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
"@rollup/plugin-commonjs@^22.0.1":
version "22.0.2"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz#ee8ca8415cda30d383b4096aad5222435b4b69b6"
integrity sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==
dependencies:
"@rollup/pluginutils" "^3.1.0"
commondir "^1.0.1"
estree-walker "^2.0.1"
glob "^7.1.6"
is-reference "^1.2.1"
magic-string "^0.25.7"
resolve "^1.17.0"
"@rollup/plugin-json@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3"
integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==
dependencies:
"@rollup/pluginutils" "^3.0.8"
"@rollup/plugin-node-resolve@^14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz#f2fa475405cd7fed6420bf438fe393f988a9bc96"
integrity sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw==
dependencies:
"@rollup/pluginutils" "^3.1.0"
"@types/resolve" "1.17.1"
deepmerge "^4.2.2"
is-builtin-module "^3.1.0"
is-module "^1.0.0"
resolve "^1.19.0"
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
dependencies:
"@types/estree" "0.0.39"
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@rollup/pluginutils@^4.2.1":
version "4.2.1"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
@@ -135,77 +181,96 @@
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@sveltejs/adapter-auto@1.0.0-next.66":
version "1.0.0-next.66"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.66.tgz#93a6de02a7a4ebef11160bf8d012ef349839656e"
integrity sha512-p78AQaSDHkLS5EFGqCF2xrLHMjKxx6wTLUvnP26cu2llh/VV4NihQ0rheVNgPWL+tGZpVznhrUG8fWmJxPciug==
"@sveltejs/adapter-auto@^1.0.0-next.80":
version "1.0.0-next.80"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.80.tgz#15d331bbfca89cb39b719c3086d134cc1a7227b1"
integrity sha512-352WoZr9fQgxJqgNENvxRr2gsA+wTF6V9AVaQaaatDYd3RVEBaXTYOOalFaRLSa25mRUJaLYP2aaliqczMl23g==
dependencies:
"@sveltejs/adapter-cloudflare" "1.0.0-next.32"
"@sveltejs/adapter-netlify" "1.0.0-next.72"
"@sveltejs/adapter-vercel" "1.0.0-next.68"
"@sveltejs/adapter-cloudflare" "1.0.0-next.38"
"@sveltejs/adapter-netlify" "1.0.0-next.78"
"@sveltejs/adapter-vercel" "1.0.0-next.77"
"@sveltejs/adapter-cloudflare@1.0.0-next.32":
version "1.0.0-next.32"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.32.tgz#2e164e50786cf50d907f79a1d9ec8e0ab72a99df"
integrity sha512-tzkUsdQlBk9xUjcGUOBYos4HKaeaXvz9v4TQ1QS2yIHEtL5xvMEDPZ94/DB2gPL4LZCnYbdY2lsy5HCsoN0hkQ==
"@sveltejs/adapter-cloudflare@1.0.0-next.38":
version "1.0.0-next.38"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.38.tgz#b4c6e7314de79f2a3ab1d8e2f88274a8c224e325"
integrity sha512-N6jdTomRZkdKlcNoguwYD7lpdXSt0beIyUJsp0MS/YLm/4gI83y698zFYInFKJ9t5e6DAnuEBSAXcg568z2oFA==
dependencies:
"@cloudflare/workers-types" "^3.14.0"
esbuild "^0.14.48"
esbuild "^0.15.7"
worktop "0.8.0-next.14"
"@sveltejs/adapter-netlify@1.0.0-next.72":
version "1.0.0-next.72"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.72.tgz#5fe42a4944de476baa089cdc7f525ae6037585c9"
integrity sha512-g570hYAMkgrJfo/TRg3DZFmlR7bNFHECFPOMgc8R+f28ROap/nXA8ICbiSBF7+zJ5JXvJbqHGjERSsyhEq+59g==
"@sveltejs/adapter-netlify@1.0.0-next.78":
version "1.0.0-next.78"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.78.tgz#a18e750ac9d146afb308c527649f24c40b746d59"
integrity sha512-Yyn/j/0QcLK3Db442ducLUZmyvkO74j7Gdcwu9xN0fQN3kBlCJP9Itx5o4SySrPFGc4Q8cLJ5ELNg+mWduLBAA==
dependencies:
"@iarna/toml" "^2.2.5"
esbuild "^0.14.48"
esbuild "^0.15.7"
set-cookie-parser "^2.4.8"
tiny-glob "^0.2.9"
"@sveltejs/adapter-vercel@1.0.0-next.68":
version "1.0.0-next.68"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.68.tgz#ccd0707f02d8aff9185b373a484366d961f58753"
integrity sha512-ImM+fDwGkVaf920Wzh284nfAfu/WoPXCpMwog0kveIODVgCozbpJY55fO860LccqdS0YDyeFqOUrZJCqcYNx4w==
"@sveltejs/adapter-node@1.0.0-next.96":
version "1.0.0-next.96"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.96.tgz#3f071a0677f787f9e8b2157b087b5403c4df4b6c"
integrity sha512-tIHaRolUYy2PiHl4RUWaOsYxEjK5lN9501qzCzFbYr/uoLnZcnPGSXNJICwX0AX9AUkV6cvkZey6bLbUQcwH0Q==
dependencies:
"@vercel/nft" "^0.21.0"
esbuild "^0.14.48"
"@rollup/plugin-commonjs" "^22.0.1"
"@rollup/plugin-json" "^4.1.0"
"@rollup/plugin-node-resolve" "^14.1.0"
rollup "^2.78.1"
"@sveltejs/kit@1.0.0-next.443":
version "1.0.0-next.443"
resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.0.0-next.443.tgz#5797a3c21d839562b3e96d19151beefa957dbf37"
integrity sha512-Stdjwj6iL/u40O/+20UKTWtCBYxYaKwX2nRV5devrGk5hvq6/FbAqw+azwoWKvNoz3PGtrSmHIyeLcAx8iKQcw==
"@sveltejs/adapter-vercel@1.0.0-next.77":
version "1.0.0-next.77"
resolved "https://registry.yarnpkg.com/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.77.tgz#be9bfa2b46fd63723893d37ecdacbb1d735515c3"
integrity sha512-r4MqtP+lzx83HfcvI8PU0Yxzmxt6WQq9nzZETLboJouJzhSBUFIN5RmNZfEn6nNIlUwZbGQUEK/FxsRnnxI/Ig==
dependencies:
"@sveltejs/vite-plugin-svelte" "^1.0.1"
"@vercel/nft" "^0.22.0"
esbuild "^0.15.7"
"@sveltejs/kit@1.0.0-next.511":
version "1.0.0-next.511"
resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.0.0-next.511.tgz#d045d0737ec93d21de5a27b6ca619daf79f8e4f7"
integrity sha512-A/fxd4qHWDD07Mjo6qEEEfsBEkoj5C4/dPSzx6xPUoWmPvRPhU8t+P0oMc8BOn5YHOhPDq3coH8bmafbh73zKg==
dependencies:
"@sveltejs/vite-plugin-svelte" "^1.0.5"
"@types/cookie" "^0.5.1"
cookie "^0.5.0"
devalue "^2.0.1"
devalue "^4.0.0"
kleur "^4.1.4"
magic-string "^0.26.2"
mime "^3.0.0"
node-fetch "^3.2.4"
sade "^1.8.1"
set-cookie-parser "^2.4.8"
sirv "^2.0.2"
tiny-glob "^0.2.9"
undici "^5.8.1"
undici "^5.11.0"
"@sveltejs/vite-plugin-svelte@^1.0.1":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.3.tgz#f760677e03074b9f42335dbde33ba988c95d1e67"
integrity sha512-0Qu51m2W9RBlxWPp8i31KJpnqmjWMOne8vAzgmOX6ZM9uX+/RAv6BNhEMcNoP5MsyLjyW1ZTCiJoaZZ5EeqpFg==
"@sveltejs/vite-plugin-svelte@^1.0.5":
version "1.0.9"
resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.9.tgz#b19bde0ba1929a06205888e94475595e3ac0c258"
integrity sha512-+SDrAnT7TDi8sdj4OfD2SC4s9DNrpNVBrue8fT2PmKks9Ddu0JIfSeX91wXZb/1xHz4EkGb+rli8GTRI0yGOjg==
dependencies:
"@rollup/pluginutils" "^4.2.1"
debug "^4.3.4"
deepmerge "^4.2.2"
kleur "^4.1.5"
magic-string "^0.26.2"
svelte-hmr "^0.14.12"
magic-string "^0.26.5"
svelte-hmr "^0.15.0"
"@types/cookie@^0.5.1":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.5.1.tgz#b29aa1f91a59f35e29ff8f7cb24faf1a3a750554"
integrity sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==
"@types/estree@*":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2"
integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/json-schema@^7.0.9":
version "7.0.9"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
@@ -221,6 +286,13 @@
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.6.tgz#f830323c88172e66826d0bde413498b61054b5a6"
integrity sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==
"@types/resolve@1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
dependencies:
"@types/node" "*"
"@types/sass@^1.16.0":
version "1.43.1"
resolved "https://registry.yarnpkg.com/@types/sass/-/sass-1.43.1.tgz#86bb0168e9e881d7dade6eba16c9ed6d25dc2f68"
@@ -309,10 +381,10 @@
"@typescript-eslint/types" "5.36.1"
eslint-visitor-keys "^3.3.0"
"@vercel/nft@^0.21.0":
version "0.21.0"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.21.0.tgz#e0715b1997cd7021a7c7c48b584ef2295fd4b810"
integrity sha512-hFCAETfI5cG8l5iAiLhMC2bReC5K7SIybzrxGorv+eGspIbIFsVw7Vg85GovXm/LxA08pIDrAlrhR6GN36XB/Q==
"@vercel/nft@^0.22.0":
version "0.22.1"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.22.1.tgz#0d91d2a21e3a7f0b23ce1550da9870eac4942828"
integrity sha512-lYYZIoxRurqDOSoVIdBicGnpUIpfyaS5qVjdPq+EfI285WqtZK3NK/dyCkiyBul+X2U2OEhRyeMdXPCHGJbohw==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.6.0"
@@ -443,6 +515,18 @@ buffer-crc32@^0.2.5:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
builtin-modules@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
busboy@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
dependencies:
streamsearch "^1.1.0"
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -493,6 +577,11 @@ color-support@^1.1.2:
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -522,11 +611,6 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"
data-uri-to-buffer@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b"
integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==
debug@4, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
@@ -566,10 +650,10 @@ detect-libc@^2.0.0:
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd"
integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==
devalue@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/devalue/-/devalue-2.0.1.tgz#5d368f9adc0928e47b77eea53ca60d2f346f9762"
integrity sha512-I2TiqT5iWBEyB8GRfTDP0hiLZ0YeDJZ+upDxjBfOC2lebO5LezQMv7QvIUTzdb64jQyAKLf1AHADtGN+jw6v8Q==
devalue@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/devalue/-/devalue-4.0.0.tgz#efeadbc922894d468ad903029d4a7e65e37f4952"
integrity sha512-w25siwXyuMUqMr7jPlEjyNCp1vn0Jzj/fNg3qVt/r/Dpe8HjESh2V92L0jmh3uq4iJt0BvjH+Azk1pQzkcnDWA==
dir-glob@^3.0.1:
version "3.0.1"
@@ -595,132 +679,133 @@ es6-promise@^3.1.2:
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=
esbuild-android-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be"
integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==
esbuild-android-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.10.tgz#8a59a84acbf2eca96996cadc35642cf055c494f0"
integrity sha512-UI7krF8OYO1N7JYTgLT9ML5j4+45ra3amLZKx7LO3lmLt1Ibn8t3aZbX5Pu4BjWiqDuJ3m/hsvhPhK/5Y/YpnA==
esbuild-android-arm64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771"
integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==
esbuild-android-arm64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.10.tgz#f453851dc1d8c5409a38cf7613a33852faf4915d"
integrity sha512-EOt55D6xBk5O05AK8brXUbZmoFj4chM8u3riGflLa6ziEoVvNjRdD7Cnp82NHQGfSHgYR06XsPI8/sMuA/cUwg==
esbuild-darwin-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25"
integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==
esbuild-darwin-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.10.tgz#778bd29c8186ff47b176c8af58c08cf0fb8e6b86"
integrity sha512-hbDJugTicqIm+WKZgp208d7FcXcaK8j2c0l+fqSJ3d2AzQAfjEYDRM3Z2oMeqSJ9uFxyj/muSACLdix7oTstRA==
esbuild-darwin-arm64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73"
integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==
esbuild-darwin-arm64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.10.tgz#b30bbefb46dc3c5d4708b0435e52f6456578d6df"
integrity sha512-M1t5+Kj4IgSbYmunf2BB6EKLkWUq+XlqaFRiGOk8bmBapu9bCDrxjf4kUnWn59Dka3I27EiuHBKd1rSO4osLFQ==
esbuild-freebsd-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d"
integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==
esbuild-freebsd-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.10.tgz#ab301c5f6ded5110dbdd611140bef1a7c2e99236"
integrity sha512-KMBFMa7C8oc97nqDdoZwtDBX7gfpolkk6Bcmj6YFMrtCMVgoU/x2DI1p74DmYl7CSS6Ppa3xgemrLrr5IjIn0w==
esbuild-freebsd-arm64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48"
integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==
esbuild-freebsd-arm64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.10.tgz#a5b09b867a6ff49110f52343b6f12265db63d43f"
integrity sha512-m2KNbuCX13yQqLlbSojFMHpewbn8wW5uDS6DxRpmaZKzyq8Dbsku6hHvh2U+BcLwWY4mpgXzFUoENEf7IcioGg==
esbuild-linux-32@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5"
integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==
esbuild-linux-32@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.10.tgz#5282fe9915641caf9c8070e4ba2c3e16d358f837"
integrity sha512-guXrwSYFAvNkuQ39FNeV4sNkNms1bLlA5vF1H0cazZBOLdLFIny6BhT+TUbK/hdByMQhtWQ5jI9VAmPKbVPu1w==
esbuild-linux-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz#de5fdba1c95666cf72369f52b40b03be71226652"
integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==
esbuild-linux-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.10.tgz#f3726e85a00149580cb19f8abfabcbb96f5d52bb"
integrity sha512-jd8XfaSJeucMpD63YNMO1JCrdJhckHWcMv6O233bL4l6ogQKQOxBYSRP/XLWP+6kVTu0obXovuckJDcA0DKtQA==
esbuild-linux-arm64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b"
integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==
esbuild-linux-arm64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.10.tgz#2f0056e9d5286edb0185b56655caa8c574d8dbe7"
integrity sha512-GByBi4fgkvZFTHFDYNftu1DQ1GzR23jws0oWyCfhnI7eMOe+wgwWrc78dbNk709Ivdr/evefm2PJiUBMiusS1A==
esbuild-linux-arm@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59"
integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==
esbuild-linux-arm@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.10.tgz#40a9270da3c8ffa32cf72e24a79883e323dff08d"
integrity sha512-6N8vThLL/Lysy9y4Ex8XoLQAlbZKUyExCWyayGi2KgTBelKpPgj6RZnUaKri0dHNPGgReJriKVU6+KDGQwn10A==
esbuild-linux-mips64le@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34"
integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==
esbuild-linux-mips64le@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.10.tgz#90ce1c4ee0202edb4ac69807dea77f7e5804abc4"
integrity sha512-BxP+LbaGVGIdQNJUNF7qpYjEGWb0YyHVSKqYKrn+pTwH/SiHUxFyJYSP3pqkku61olQiSBnSmWZ+YUpj78Tw7Q==
esbuild-linux-ppc64le@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e"
integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==
esbuild-linux-ppc64le@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.10.tgz#782837ae7bd5b279178106c9dd801755a21fabdf"
integrity sha512-LoSQCd6498PmninNgqd/BR7z3Bsk/mabImBWuQ4wQgmQEeanzWd5BQU2aNi9mBURCLgyheuZS6Xhrw5luw3OkQ==
esbuild-linux-riscv64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8"
integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==
esbuild-linux-riscv64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.10.tgz#d7420d806ece5174f24f4634303146f915ab4207"
integrity sha512-Lrl9Cr2YROvPV4wmZ1/g48httE8z/5SCiXIyebiB5N8VT7pX3t6meI7TQVHw/wQpqP/AF4SksDuFImPTM7Z32Q==
esbuild-linux-s390x@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6"
integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==
esbuild-linux-s390x@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.10.tgz#21fdf0cb3494a7fb520a71934e4dffce67fe47be"
integrity sha512-ReP+6q3eLVVP2lpRrvl5EodKX7EZ1bS1/z5j6hsluAlZP5aHhk6ghT6Cq3IANvvDdscMMCB4QEbI+AjtvoOFpA==
esbuild-netbsd-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81"
integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==
esbuild-netbsd-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.10.tgz#6c06b3107e3df53de381e6299184d4597db0440f"
integrity sha512-iGDYtJCMCqldMskQ4eIV+QSS/CuT7xyy9i2/FjpKvxAuCzrESZXiA1L64YNj6/afuzfBe9i8m/uDkFHy257hTw==
esbuild-openbsd-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b"
integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==
esbuild-openbsd-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.10.tgz#4daef5f5d8e74bbda53b65160029445d582570cf"
integrity sha512-ftMMIwHWrnrYnvuJQRJs/Smlcb28F9ICGde/P3FUTCgDDM0N7WA0o9uOR38f5Xe2/OhNCgkjNeb7QeaE3cyWkQ==
esbuild-sunos-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da"
integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==
esbuild-sunos-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.10.tgz#5fe7bef267a02f322fd249a8214d0274937388a7"
integrity sha512-mf7hBL9Uo2gcy2r3rUFMjVpTaGpFJJE5QTDDqUFf1632FxteYANffDZmKbqX0PfeQ2XjUDE604IcE7OJeoHiyg==
esbuild-windows-32@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31"
integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==
esbuild-windows-32@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.10.tgz#48e3dde25ab0135579a288b30ab6ddef6d1f0b28"
integrity sha512-ttFVo+Cg8b5+qHmZHbEc8Vl17kCleHhLzgT8X04y8zudEApo0PxPg9Mz8Z2cKH1bCYlve1XL8LkyXGFjtUYeGg==
esbuild-windows-64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4"
integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==
esbuild-windows-64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz#387a9515bef3fee502d277a5d0a2db49a4ecda05"
integrity sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==
esbuild-windows-arm64@0.14.54:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982"
integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==
esbuild-windows-arm64@0.15.10:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.10.tgz#5a6fcf2fa49e895949bf5495cf088ab1b43ae879"
integrity sha512-S+th4F+F8VLsHLR0zrUcG+Et4hx0RKgK1eyHc08kztmLOES8BWwMiaGdoW9hiXuzznXQ0I/Fg904MNbr11Nktw==
esbuild@^0.14.27, esbuild@^0.14.48:
version "0.14.54"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.54.tgz#8b44dcf2b0f1a66fc22459943dccf477535e9aa2"
integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==
esbuild@^0.15.7, esbuild@^0.15.9:
version "0.15.10"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.10.tgz#85c2f8446e9b1fe04fae68daceacba033eedbd42"
integrity sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==
optionalDependencies:
"@esbuild/linux-loong64" "0.14.54"
esbuild-android-64 "0.14.54"
esbuild-android-arm64 "0.14.54"
esbuild-darwin-64 "0.14.54"
esbuild-darwin-arm64 "0.14.54"
esbuild-freebsd-64 "0.14.54"
esbuild-freebsd-arm64 "0.14.54"
esbuild-linux-32 "0.14.54"
esbuild-linux-64 "0.14.54"
esbuild-linux-arm "0.14.54"
esbuild-linux-arm64 "0.14.54"
esbuild-linux-mips64le "0.14.54"
esbuild-linux-ppc64le "0.14.54"
esbuild-linux-riscv64 "0.14.54"
esbuild-linux-s390x "0.14.54"
esbuild-netbsd-64 "0.14.54"
esbuild-openbsd-64 "0.14.54"
esbuild-sunos-64 "0.14.54"
esbuild-windows-32 "0.14.54"
esbuild-windows-64 "0.14.54"
esbuild-windows-arm64 "0.14.54"
"@esbuild/android-arm" "0.15.10"
"@esbuild/linux-loong64" "0.15.10"
esbuild-android-64 "0.15.10"
esbuild-android-arm64 "0.15.10"
esbuild-darwin-64 "0.15.10"
esbuild-darwin-arm64 "0.15.10"
esbuild-freebsd-64 "0.15.10"
esbuild-freebsd-arm64 "0.15.10"
esbuild-linux-32 "0.15.10"
esbuild-linux-64 "0.15.10"
esbuild-linux-arm "0.15.10"
esbuild-linux-arm64 "0.15.10"
esbuild-linux-mips64le "0.15.10"
esbuild-linux-ppc64le "0.15.10"
esbuild-linux-riscv64 "0.15.10"
esbuild-linux-s390x "0.15.10"
esbuild-netbsd-64 "0.15.10"
esbuild-openbsd-64 "0.15.10"
esbuild-sunos-64 "0.15.10"
esbuild-windows-32 "0.15.10"
esbuild-windows-64 "0.15.10"
esbuild-windows-arm64 "0.15.10"
escape-string-regexp@^4.0.0:
version "4.0.0"
@@ -858,6 +943,11 @@ estree-walker@^0.6.1:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362"
integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==
estree-walker@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -896,14 +986,6 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
version "3.2.0"
resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
dependencies:
node-domexception "^1.0.0"
web-streams-polyfill "^3.0.3"
file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@@ -944,13 +1026,6 @@ flatted@^3.1.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
formdata-polyfill@^4.0.10:
version "4.0.10"
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
dependencies:
fetch-blob "^3.1.2"
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -1019,6 +1094,18 @@ glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^7.1.6:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.1.1"
once "^1.3.0"
path-is-absolute "^1.0.0"
globals@^13.15.0:
version "13.17.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4"
@@ -1126,10 +1213,17 @@ is-binary-path@~2.1.0:
dependencies:
binary-extensions "^2.0.0"
is-core-module@^2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
is-builtin-module@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0"
integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==
dependencies:
builtin-modules "^3.3.0"
is-core-module@^2.9.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed"
integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==
dependencies:
has "^1.0.3"
@@ -1150,11 +1244,23 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
is-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-reference@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
dependencies:
"@types/estree" "*"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -1233,6 +1339,13 @@ magic-string@^0.26.2:
dependencies:
sourcemap-codec "^1.4.8"
magic-string@^0.26.5:
version "0.26.6"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.26.6.tgz#b61e417c9f40b7b53bf7e73c0a803258e20d25ee"
integrity sha512-6d+3bFybzyQFJYSoRsl9ZC0wheze8M1LrQC7tNMRqXR4izUTDOLMd9BtSuExK9iAukFh+s5K0WAhc/dlQ+HKYA==
dependencies:
sourcemap-codec "^1.4.8"
make-dir@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@@ -1271,7 +1384,7 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@^3.0.4, minimatch@^3.1.2:
minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -1350,11 +1463,6 @@ next-auth@latest:
preact-render-to-string "^5.1.19"
uuid "^8.3.2"
node-domexception@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
@@ -1362,15 +1470,6 @@ node-fetch@^2.6.7:
dependencies:
whatwg-url "^5.0.0"
node-fetch@^3.2.4:
version "3.2.10"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.10.tgz#e8347f94b54ae18b57c9c049ef641cef398a85c8"
integrity sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==
dependencies:
data-uri-to-buffer "^4.0.0"
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"
node-gyp-build@^4.2.2:
version "4.5.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40"
@@ -1503,10 +1602,10 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatc
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
postcss@^8.4.13:
version "8.4.16"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c"
integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==
postcss@^8.4.16:
version "8.4.17"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.17.tgz#f87863ec7cd353f81f7ab2dec5d67d861bbb1be5"
integrity sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
@@ -1595,12 +1694,12 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve@^1.22.0:
version "1.22.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.1:
version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
dependencies:
is-core-module "^2.8.1"
is-core-module "^2.9.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
@@ -1630,10 +1729,17 @@ rollup-pluginutils@^2.8.2:
dependencies:
estree-walker "^0.6.1"
rollup@^2.59.0:
version "2.67.3"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.67.3.tgz#3f04391fc296f807d067c9081d173e0a33dbd37e"
integrity sha512-G/x1vUwbGtP6O5ZM8/sWr8+p7YfZhI18pPqMRtMYMWSbHjKZ/ajHGiM+GWNTlWyOR0EHIdT8LHU+Z4ciIZ1oBw==
rollup@^2.78.1:
version "2.79.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
optionalDependencies:
fsevents "~2.3.2"
rollup@~2.78.0:
version "2.78.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.1.tgz#52fe3934d9c83cb4f7c4cb5fb75d88591be8648f"
integrity sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==
optionalDependencies:
fsevents "~2.3.2"
@@ -1672,9 +1778,9 @@ semver@^6.0.0:
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
dependencies:
lru-cache "^6.0.0"
@@ -1746,6 +1852,11 @@ sourcemap-codec@^1.3.0, sourcemap-codec@^1.4.4, sourcemap-codec@^1.4.8:
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
streamsearch@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
@@ -1807,10 +1918,10 @@ svelte-check@^2.8.1:
svelte-preprocess "^4.0.0"
typescript "*"
svelte-hmr@^0.14.12:
version "0.14.12"
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.14.12.tgz#a127aec02f1896500b10148b2d4d21ddde39973f"
integrity sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==
svelte-hmr@^0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.15.0.tgz#c8304b5dd33f006415329d91470761d19417a324"
integrity sha512-Aw21SsyoohyVn4yiKXWPNCSW2DQNH/76kvUnE9kpt4h9hcg9tfyQc6xshx9hzgMfGF0kVx0EGD8oBMWSnATeOg==
svelte-preprocess@^4.0.0:
version "4.10.3"
@@ -1922,10 +2033,12 @@ typescript@~4.8.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.2.tgz#e3b33d5ccfb5914e4eeab6699cf208adee3fd790"
integrity sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==
undici@^5.8.1:
version "5.10.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.10.0.tgz#dd9391087a90ccfbd007568db458674232ebf014"
integrity sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==
undici@^5.11.0:
version "5.11.0"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.11.0.tgz#1db25f285821828fc09d3804b9e2e934ae86fc13"
integrity sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==
dependencies:
busboy "^1.6.0"
uri-js@^4.2.2:
version "4.4.1"
@@ -1944,23 +2057,18 @@ uuid@^8.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
vite@^2.9.13:
version "2.9.13"
resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.13.tgz#859cb5d4c316c0d8c6ec9866045c0f7858ca6abc"
integrity sha512-AsOBAaT0AD7Mhe8DuK+/kE4aWYFMx/i0ZNi98hJclxb4e0OhQcZYUrvLjIaQ8e59Ui7txcvKMiJC1yftqpQoDw==
vite@^3.1.0:
version "3.1.6"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.1.6.tgz#4c6db3000326342c918204a42a130fb3ffed2414"
integrity sha512-qMXIwnehvvcK5XfJiXQUiTxoYAEMKhM+jqCY6ZSTKFBKu1hJnAKEzP3AOcnTerI0cMZYAaJ4wpW1wiXLMDt4mA==
dependencies:
esbuild "^0.14.27"
postcss "^8.4.13"
resolve "^1.22.0"
rollup "^2.59.0"
esbuild "^0.15.9"
postcss "^8.4.16"
resolve "^1.22.1"
rollup "~2.78.0"
optionalDependencies:
fsevents "~2.3.2"
web-streams-polyfill@^3.0.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"

View File

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

View File

@@ -12,15 +12,28 @@ npm install next-auth @prisma/client @next-auth/prisma-adapter
npm install prisma --save-dev
```
Create a file with your Prisma Client:
```typescript title="lib/prismadb.ts"
import { PrismaClient } from "@prisma/client"
declare global {
var prisma: PrismaClient | undefined
}
const client = globalThis.prisma || new PrismaClient()
if (process.env.NODE_ENV !== "production") globalThis.prisma = client
export default client
```
Configure your NextAuth.js to use the Prisma Adapter:
```javascript title="pages/api/auth/[...nextauth].js"
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()
import prisma from "../../../lib/prismadb"
export default NextAuth({
adapter: PrismaAdapter(prisma),

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

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

View File

@@ -112,15 +112,16 @@ Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`,
- As with database persisted session expiry times, token expiry time is extended whenever a session is active.
- The arguments _user_, _account_, _profile_ and _isNewUser_ are only passed the first time this callback is called on a new session, after the user signs in. In subsequent calls, only `token` will be available.
The contents _user_, _account_, _profile_ and _isNewUser_ will vary depending on the provider and on if you are using a database or not. You can persist data such as User ID, OAuth Access Token in this token. To make it available in the browser, check out the [`session()` callback](#session-callback) as well.
The contents _user_, _account_, _profile_ and _isNewUser_ will vary depending on the provider and if you are using a database. You can persist data such as User ID, OAuth Access Token in this token, see the example below for `access_token` and `user.id`. To expose it on the client side, check out the [`session()` callback](#session-callback) as well.
```js title="pages/api/auth/[...nextauth].js"
...
callbacks: {
async jwt({ token, account }) {
// Persist the OAuth access_token to the token right after signin
async jwt({ token, account, profile }) {
// Persist the OAuth access_token and or the user id to the token right after signin
if (account) {
token.accessToken = account.access_token
token.id = profile.id
}
return token
}
@@ -134,7 +135,7 @@ Use an if branch to check for the existence of parameters (apart from `token`).
## Session callback
The session callback is called whenever a session is checked. By default, only a subset of the token is returned for increased security. If you want to make something available you added to the token through the `jwt()` callback, you have to explicitly forward it here to make it available to the client.
The session callback is called whenever a session is checked. By default, **only a subset of the token is returned for increased security**. If you want to make something available you added to the token (like `access_token` and `user.id` from above) via the `jwt()` callback, you have to explicitly forward it here to make it available to the client.
e.g. `getSession()`, `useSession()`, `/api/auth/session`
@@ -145,8 +146,10 @@ e.g. `getSession()`, `useSession()`, `/api/auth/session`
...
callbacks: {
async session({ session, token, user }) {
// Send properties to the client, like an access_token from a provider.
// Send properties to the client, like an access_token and user id from a provider.
session.accessToken = token.accessToken
session.user.id = token.id
return session
}
}
@@ -155,7 +158,7 @@ callbacks: {
:::tip
When using JSON Web Tokens the `jwt()` callback is invoked before the `session()` callback, so anything you add to the
JSON Web Token will be immediately available in the session callback, like for example an `access_token` from a provider.
JSON Web Token will be immediately available in the session callback, like for example an `access_token` or `id` from a provider.
:::
:::warning

View File

@@ -24,7 +24,7 @@ export const authOptions: NextAuthOptions = {
export default NextAuth(authOptions);
```
In `getServerSideProps`:
### In `getServerSideProps`:
```js
import { authOptions } from 'pages/api/auth/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
@@ -48,7 +48,8 @@ export async function getServerSideProps(context) {
}
}
```
In API routes:
### In API Routes:
```js
import { authOptions } from 'pages/api/auth/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
@@ -68,6 +69,23 @@ export async function handler(req, res) {
}
```
### In `app/` directory:
You can also use `unstable_getServerSession` in Next.js' server components:
```tsx
import { unstable_getServerSession } from "next-auth/next"
export default async function Page() {
const session = await unstable_getServerSession()
return <pre>{JSON.stringify(session, null, 2)}</pre>
}
```
:::warning
Currently, the underlying Next.js `cookies()` method does [only provides read access](https://beta.nextjs.org/docs/api-reference/cookies) to the request cookies. This means that the `expires` value is stripped away from `session` in Server Components. Furthermore, there is a hard expiry on sessions, after which the user will be required to sign in again. (The default expiry is 30 days).
:::
## Middleware
You can use a Next.js Middleware with NextAuth.js to protect your site.

View File

@@ -13,12 +13,12 @@ When deploying to production, set the `NEXTAUTH_URL` environment variable to the
NEXTAUTH_URL=https://example.com
```
If your Next.js application uses a custom base path, specify the route to the API endpoint in full. More informations about the usage of custom base path [here](/getting-started/client#custom-base-path).
If your Next.js application uses a custom base path, specify the route to the API endpoint in full. More information about the usage of custom base path [here](/getting-started/client#custom-base-path).
_e.g. `NEXTAUTH_URL=https://example.com/custom-route/api/auth`_
:::tip
When you're using a custom base path, you will need to pass the `basePath` page prop to the `<SessionProvider>`. More informations [here](/getting-started/client#custom-base-path).
When you're using a custom base path, you will need to pass the `basePath` page prop to the `<SessionProvider>`. More information [here](/getting-started/client#custom-base-path).
:::
:::note
@@ -114,6 +114,12 @@ session: {
// Use it to limit write operations. Set to 0 to always update the database.
// Note: This option is ignored if using JSON Web Tokens
updateAge: 24 * 60 * 60, // 24 hours
// The session token is usually either a random UUID or string, however if you
// need a more customized session token string, you can define your own generate function.
generateSessionToken: () => {
return randomUUID?.() ?? randomBytes(32).toString("hex")
}
}
```

View File

@@ -83,7 +83,7 @@ TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET
4. Now you can add the provider settings to the NextAuth.js options object. You can add as many OAuth providers as you like, as you can see `providers` is an array.
```js title="pages/api/auth/[...nextauth].js"
import TwitterProvider from "next-auth/providers/"
import TwitterProvider from "next-auth/providers/twitter"
...
providers: [
TwitterProvider({
@@ -156,7 +156,7 @@ interface OAuthConfig {
*/
id: string
version: string
profile(profile: P, tokens: TokenSet): Awaitable<User & { id: string }>
profile(profile: P, tokens: TokenSet): Awaitable<User>
checks?: ChecksType | ChecksType[]
clientId: string
clientSecret: string
@@ -173,6 +173,7 @@ interface OAuthConfig {
region?: string
issuer?: string
client?: Partial<ClientMetadata>
allowDangerousEmailAccountLinking?: boolean
}
```
@@ -278,6 +279,10 @@ If your Provider is OpenID Connect (OIDC) compliant, we recommend using the `wel
An advanced option, hopefully you won't need it in most cases. `next-auth` uses `openid-client` under the hood, see the docs on this option [here](https://github.com/panva/node-openid-client/blob/main/docs/README.md#new-clientmetadata-jwks-options).
### `allowDangerousEmailAccountLinking` option
Normally, when you sign in with an OAuth provider and another account with the same email address already exists, the accounts are not linked automatically. Automatic account linking on sign in is not secure between arbitrary providers and is disabled by default (see our [Security FAQ](https://next-auth.js.org/faq#security)). However, it may be desirable to allow automatic account linking if you trust that the provider involved has securely verified the email address associated with the account. Just set `allowDangerousEmailAccountLinking: true` in your provider configuration to enable automatic account linking.
## Using a custom provider
You can use an OAuth provider that isn't built-in by using a custom object.
@@ -404,14 +409,27 @@ GoogleProvider({
})
```
An example of how to enable automatic account linking:
```js title=/api/auth/[...nextauth].js
import GoogleProvider from "next-auth/providers/google"
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
allowDangerousEmailAccountLinking: true,
})
```
### Adding a new built-in provider
If you think your custom provider might be useful to others, we encourage you to open a PR and add it to the built-in list so others can discover it much more easily!
You only need to add two changes:
You only need to add three changes:
1. Add your config: [`src/providers/{provider}.ts`](https://github.com/nextauthjs/next-auth/tree/main/packages/next-auth/src/providers)<br />
• make sure you use a named default export, like this: `export default function YourProvider`
2. Add provider documentation: [`/docs/providers/{provider}.md`](https://github.com/nextauthjs/next-auth/tree/main/docs/docs/providers)
3. Add the new provider name to the `Provider type` dropdown options in [`the provider issue template`](<[http](https://github.com/nextauthjs/next-auth/edit/main/.github/ISSUE_TEMPLATE/2_bug_provider.yml)>)
That's it! 🎉 Others will be able to discover and use this provider much more easily now!

View File

@@ -136,7 +136,7 @@ The `callbackUrl` provided was either invalid or not defined. See [specifying a
#### JWT_SESSION_ERROR
JWKKeySupport: the key does not support HS512 verify algorithm
JWTKeySupport: the key does not support HS512 verify algorithm
The algorithm used for generating your key isn't listed as supported. You can generate a HS512 key using

View File

@@ -58,7 +58,7 @@ export default function Component() {
`useSession()` returns an object containing two values: `data` and `status`:
- **`data`**: This can be three values: [`Session`](https://github.com/nextauthjs/next-auth/blob/8ff4b260143458c5d8a16b80b11d1b93baa0690f/types/index.d.ts#L437-L444) / `undefined` / `null`.
- when the session hasn't been fetched yet, `data` will `undefined`
- when the session hasn't been fetched yet, `data` will be `undefined`
- in case it failed to retrieve the session, `data` will be `null`
- in case of success, `data` will be [`Session`](https://github.com/nextauthjs/next-auth/blob/8ff4b260143458c5d8a16b80b11d1b93baa0690f/types/index.d.ts#L437-L444).
- **`status`**: enum mapping to three possible session states: `"loading" | "authenticated" | "unauthenticated"`
@@ -290,7 +290,7 @@ export default ({ email }) => (
### Specifying a `callbackUrl`
The `callbackUrl` specifies to which URL the user will be redirected after signing in. It defaults to the current URL of a user.
The `callbackUrl` specifies to which URL the user will be redirected after signing in. Defaults to the page URL the sign-in is initiated from.
You can specify a different `callbackUrl` by specifying it as the second argument of `signIn()`. This works for all providers.
@@ -491,6 +491,8 @@ If set to any value other than zero, it specifies in seconds how often the clien
The value for `refetchInterval` should always be lower than the value of the session `maxAge` [session option](/configuration/options#session).
By default, session polling will keep trying, even when the device has no internet access. To circumvent this, you can also set `refetchWhenOffline` to `false`. This will use [`navigator.onLine`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/onLine) to only poll when the device is online.
#### Refetch On Window Focus
The `refetchOnWindowFocus` option can be used to control whether it automatically updates the session state when you switch a focus on tabs/windows.

View File

@@ -7,11 +7,8 @@ title: Guides
We have internal guides in three levels of difficulty.
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
<DocCardList items={useCurrentSidebarCategory().items}/>
```
- [Basics](/guides/basics)
- [Fullstack](/guides/fullstack)
- [Testing](/guides/testing)
If you can't find what you're looking for here, maybe take a look at our third-party [tutorials](/tutorials) page.

View File

@@ -44,17 +44,17 @@ providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. "Sign in with...")
name: "Credentials",
// The credentials is used to generate a suitable form on the sign in page.
// You can specify whatever fields you are expecting to be submitted.
// `credentials` is used to generate a form on the sign in page.
// You can specify which fields should be submitted, by adding keys to the `credentials` object.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
username: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password" }
password: { label: "Password", type: "password" }
},
async authorize(credentials, req) {
// Add logic here to look up the user from the credentials supplied
const user = { id: 1, name: "J Smith", email: "jsmith@example.com" }
const user = { id: "1", name: "J Smith", email: "jsmith@example.com" }
if (user) {
// Any object returned will be saved in `user` property of the JWT

View File

@@ -15,6 +15,7 @@ The Email provider can be used in conjunction with (or instead of) one or more O
On initial sign in, a **Verification Token** is sent to the email address provided. By default this token is valid for 24 hours. If the Verification Token is used within that time (i.e. by clicking on the link in the email) an account is created for the user and they are signed in.
If someone provides the email address of an _existing account_ when signing in, an email is sent and they are signed into the account associated with that email address when they follow the link in the email.
:::tip
@@ -32,7 +33,7 @@ You can override any of the options to suit your own use case.
## Configuration
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`](http://nodemailer.com/smtp/well-known/).
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.
@@ -250,4 +251,4 @@ 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.
:::
:::

View File

@@ -30,7 +30,7 @@ providers: [
PatreonProvider({
clientId: process.env.PATREON_ID,
clientSecret: process.env.PATREON_SECRET,
}))
})
]
...
```

View File

@@ -0,0 +1,37 @@
---
id: pinterest
title: Pinterest
---
## Documentation
https://developers.pinterest.com/docs/getting-started/authentication/
## Configuration
https://developers.pinterest.com/apps/
## Options
The **Pinterest Provider** comes with a set of default options:
- [Pinterest Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/pinterest.ts)
You can override any of the options to suit your own use case.
## Example
```ts
import PinterestProvider from "next-auth/providers/pinterest"
...
providers: [
PinterestProvider({
clientId: process.env.PINTEREST_ID,
clientSecret: process.env.PINTEREST_SECRET
})
]
...
:::tip
To use in production, make sure the app has standard API access and not trial access
:::

View File

@@ -0,0 +1,35 @@
---
id: todoist
title: Todoist
---
## Documentation
https://developer.todoist.com/guides/#oauth
## Configuration
https://developer.todoist.com/appconsole.html
## Options
The **Todoist Provider** comes with a set of default options:
- [Todoist Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/todoist.ts)
You can override any of the options to suit your own use case.
## Example
```js
import TodoistProvider from "next-auth/providers/todoist";
...
providers: [
TodoistProvider({
clientId: process.env.TODOIST_ID,
clientSecret: process.env.TODOIST_SECRET
})
]
...
```

View File

@@ -0,0 +1,87 @@
---
id: zitadel
title: Zitadel
---
## Documentation
https://docs.zitadel.com/docs/apis/openidoauth/endpoints
## Configuration
https://docs.zitadel.com/docs/guides/integrate/oauth-recommended-flows
The Redirect URIs used when creating the credentials must include your full domain and end in the callback path. For example:
- For production: `https://{YOUR_DOMAIN}/api/auth/callback/zitadel`
- For development: `http://localhost:3000/api/auth/callback/zitadel`
Make sure to enable **dev mode** in ZITADEL console to allow redirects for local development.
## Options
The **ZITADEL Provider** comes with a set of default options:
- [ZITADEL Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/zitadel.ts)
You can override any of the options to suit your own use case.
## Example
```js
import ZitadelProvider from "next-auth/providers/zitadel";
...
providers: [
ZitadelProvider({
issuer: process.env.ZITADEL_ISSUER,
clientId: process.env.ZITADEL_CLIENT_ID,
clientSecret: process.env.ZITADEL_CLIENT_SECRET,
})
]
...
```
If you need access to ZITADEL APIs or need additional information, make sure to add the corresponding scopes.
To get the full list of supported claims take a look [here](https://docs.zitadel.com/docs/apis/openidoauth/endpoints).
```js
const options = {
...
providers: [
ZitadelProvider({
clientId: process.env.ZITADEL_CLIENT_ID,
authorization: {
params: {
scope: `openid email profile urn:zitadel:iam:org:project:id:${process.env.ZITADEL_PROJECT_ID}:aud`
}
}
})
],
...
}
```
:::
:::tip
ZITADEL also returns a `email_verified` boolean property in the profile.
You can use this property to restrict access to people with verified accounts.
```js
const options = {
...
callbacks: {
async signIn({ account, profile }) {
if (account.provider === "zitadel") {
return profile.email_verified;
}
return true; // Do different verification for other providers that don't have `email_verified`
},
}
...
}
```
:::

View File

@@ -16,7 +16,7 @@ If you contact us regarding a serious issue:
- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
The best way to report an issue is by contacting us via email at info@balazsorban.com, yo@ndo.dev, thvu@hey.com and me@iaincollins.com, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
The best way to report an issue is by contacting us via email at hi@thvu.dev, info@balazsorban.com, yo@ndo.dev and me@iaincollins.com, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
:::note
For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these these publically as bug reports or feature requests or to raise a question to open a discussion around them.

View File

@@ -105,6 +105,11 @@ This tutorial covers:
## Database
#### [Create a NextAuth.js Custom Adapter with HarperDB & Next.js](https://spacejelly.dev/posts/how-to-create-a-nextauth-js-custom-adapter-with-harperdb-next-js/) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
- Use a custom database in a Custom Adapter for persisted NextAuth.js sessions using HarperDB as an example.
- Video tutorial also available: <https://www.youtube.com/watch?v=pu7xBv7sZ8s>
#### [Using NextAuth.js with Prisma and PlanetScale serverless databases](https://github.com/planetscale/nextjs-planetscale-starter) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
- How to set up a PlanetScale database to fetch and store user / account data with the Prisma adapter.

View File

@@ -3,7 +3,7 @@ id: corporate-proxy
title: Add support for HTTP Proxy
--
Using NextAuth.js behind a corporate proxy is not supported out of the box. This is due to the fact that the underlying library we use, [`openid-client`](https://npm.im/openid-client), uses the built-in Node.js `http` / `https` libraries, which do not support proxys by default. (See: [`http` docs](https://nodejs.org/dist/latest-v16.x/docs/api/http.html), [`https` docs](https://nodejs.org/dist/latest-v16.x/docs/api/https.html)).
Using NextAuth.js behind a corporate proxy is not supported out of the box. This is due to the fact that the underlying library we use, [`openid-client`](https://npm.im/openid-client), uses the built-in Node.js `http` / `https` libraries, which do not support proxys by default. (See: [`http` docs](https://nodejs.org/dist/latest-v18.x/docs/api/http.html), [`https` docs](https://nodejs.org/dist/latest-v18.x/docs/api/https.html)).
Therefore, we'll need to an additional proxy agent to the http client, such as `https-proxy-agent`. `openid-client` allows the user to set an `agent` for requests ([Source](https://github.com/panva/node-openid-client/blob/main/docs/README.md#customizing-individual-http-requests).

View File

@@ -62,11 +62,7 @@ export default NextAuth({
async session({ session, token }) {
return { ...session, user: { username: token.username } }
},
},
secret: process.env.NEXTAUTH_SECRET,
jwt: {
secret: process.env.JWT_SECRET,
},
}
})
```
@@ -77,7 +73,6 @@ This is then passed back to any API routes and retrieved as such:
```js title="/pages/api/doLDAPWork.js"
token = await jwt.getToken({
req,
secret: process.env.NEXTAUTH_SECRET,
})
const { username, password } = token
```

View File

@@ -42,7 +42,7 @@ export default function Page() {
### Next.js (Middleware)
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `_middleware.js` file in your root `pages` directory which looks like this:
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `middleware.js` file in your root `pages` directory which looks like this:
```js title="/middleware.js"
export { default } from "next-auth/middleware"
@@ -60,6 +60,12 @@ For the time being, the `withAuth` middleware only supports `"jwt"` as [session
More details can be found [here](https://next-auth.js.org/configuration/nextjs#middleware).
:::tip
To inclue all `dashboard` nested routes (sub pages like `/dashboard/settings`, `/dashboard/profile`) you can pass `matcher: "/dashboard/:path*"` to `config`.
For other patterns check out the [Next.js Middleware documentation](https://nextjs.org/docs/advanced-features/middleware#matcher).
:::
### Server Side
You can protect server side rendered pages using the `unstable_getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly.

Some files were not shown because too many files have changed in this diff Show More