mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
124 Commits
@next-auth
...
@next-auth
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46304838af | ||
|
|
76560aed5a | ||
|
|
25517b7315 | ||
|
|
4daa63d5e1 | ||
|
|
81afeef194 | ||
|
|
008f29e6f8 | ||
|
|
e4ee520b4a | ||
|
|
358b80d4ce | ||
|
|
0a7a916228 | ||
|
|
612c35e8c2 | ||
|
|
9f6949816c | ||
|
|
46089eb5ae | ||
|
|
7d8cc70faf | ||
|
|
75602a3f04 | ||
|
|
5b8a619cd0 | ||
|
|
16622f6428 | ||
|
|
e203801f30 | ||
|
|
cfc0a55080 | ||
|
|
dda4e0a7d8 | ||
|
|
374f886e84 | ||
|
|
db188b872f | ||
|
|
2838dd7e0f | ||
|
|
08f6b31e41 | ||
|
|
602668f93c | ||
|
|
641d917175 | ||
|
|
70d59bb6e7 | ||
|
|
0c86d5a370 | ||
|
|
0ac8773c2b | ||
|
|
714579e8d6 | ||
|
|
8b6d2e3972 | ||
|
|
4f29d39521 | ||
|
|
042ed82ca0 | ||
|
|
a6901db11b | ||
|
|
0b953bd047 | ||
|
|
268c0636d7 | ||
|
|
c6903d3e85 | ||
|
|
a74d215745 | ||
|
|
18174fae36 | ||
|
|
d4fb7af6f5 | ||
|
|
bc15e2866e | ||
|
|
aee5ec2e4f | ||
|
|
f0ed23acf6 | ||
|
|
fb4bbc3b08 | ||
|
|
4c832f855e | ||
|
|
e3ace6e649 | ||
|
|
8a75911567 | ||
|
|
8288ae5be8 | ||
|
|
9f40cd1bd9 | ||
|
|
39b4d62336 | ||
|
|
1faae313fa | ||
|
|
e71118b996 | ||
|
|
afdb3c8d7c | ||
|
|
fd755bc29e | ||
|
|
59daa0e43f | ||
|
|
58d06ed727 | ||
|
|
82159d3e8f | ||
|
|
abb9fed7aa | ||
|
|
5471c0f675 | ||
|
|
b2da0b38d4 | ||
|
|
b3b8d4be46 | ||
|
|
182e118d9b | ||
|
|
7183b06939 | ||
|
|
bd10e87bf4 | ||
|
|
d07abfe517 | ||
|
|
c1110cdc98 | ||
|
|
8ed038d891 | ||
|
|
b25425795b | ||
|
|
ad1650a817 | ||
|
|
a4a487a22a | ||
|
|
b30de36126 | ||
|
|
41e4e515ad | ||
|
|
cde1f82e3c | ||
|
|
c39782007b | ||
|
|
984a089c15 | ||
|
|
26f8b8c1f1 | ||
|
|
afc9b43c53 | ||
|
|
cdbd9ac2e6 | ||
|
|
3d8cc316f1 | ||
|
|
3b8c568f79 | ||
|
|
16668d307d | ||
|
|
6e15bdcb2d | ||
|
|
7a4bf038b1 | ||
|
|
11ad64f617 | ||
|
|
0a278b9297 | ||
|
|
8c8070f30b | ||
|
|
6442d089c1 | ||
|
|
63398d4c3f | ||
|
|
0d54170e83 | ||
|
|
174f0d6aec | ||
|
|
f91b9dc03d | ||
|
|
8763e4aeb9 | ||
|
|
e936c51575 | ||
|
|
8d7ba75bca | ||
|
|
67038b4022 | ||
|
|
5b7ce98a87 | ||
|
|
1c468f057d | ||
|
|
ef22c5b835 | ||
|
|
a912739b24 | ||
|
|
ae318788c3 | ||
|
|
affa459fcc | ||
|
|
b88a31ef1a | ||
|
|
bc82d6555a | ||
|
|
11954567c2 | ||
|
|
6e28ccf84f | ||
|
|
f542b400ba | ||
|
|
d1b76bc302 | ||
|
|
3f396be5d9 | ||
|
|
bf4916dd70 | ||
|
|
5100784d72 | ||
|
|
3853e16268 | ||
|
|
4c0cc9e614 | ||
|
|
d0112aae61 | ||
|
|
e373ff2473 | ||
|
|
6d6d0a8679 | ||
|
|
8152752cc8 | ||
|
|
966381ac9b | ||
|
|
8199c96b76 | ||
|
|
6a06b8e054 | ||
|
|
68bab17914 | ||
|
|
47b4765941 | ||
|
|
6d45ad4840 | ||
|
|
e5e49aca1c | ||
|
|
ea944ebb86 | ||
|
|
ca8af7fcd5 |
38
.github/PULL_REQUEST_TEMPLATE.md
vendored
38
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,48 +1,28 @@
|
||||
<!--
|
||||
Thanks for your interest in the project. Bugs filed and PRs submitted are appreciated!
|
||||
|
||||
Please make sure that you are familiar with and follow the Code of Conduct for
|
||||
this project (found in the CODE_OF_CONDUCT.md file).
|
||||
|
||||
Also, please make sure you're familiar with and follow the instructions in the
|
||||
contributing guidelines (found in the CONTRIBUTING.md file).
|
||||
|
||||
If you're new to contributing to open source projects, you might find this free
|
||||
video course helpful: https://kcd.im/pull-request
|
||||
|
||||
Please fill out the information below to expedite the review and (hopefully)
|
||||
merge of your pull request!
|
||||
-->
|
||||
|
||||
<!-- What changes are being made? (What feature/bug is being fixed here?) -->
|
||||
## ☕️ Reasoning
|
||||
|
||||
## 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 🧢
|
||||
|
||||
<!-- Feel free cross items ( like this `~[] item~` ) if they're irrelevant to your changes.
|
||||
|
||||
To check an item, place an `x` in the box like so: `- [x] Documentation`. -->
|
||||
## 🧢 Checklist
|
||||
|
||||
- [ ] Documentation
|
||||
- [ ] Tests
|
||||
- [ ] Ready to be merged
|
||||
|
||||
<!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
|
||||
## 🎫 Affected issues
|
||||
|
||||
## Affected issues 🎟
|
||||
|
||||
<!--
|
||||
Please [scout and link issues](https://github.com/nextauthjs/next-auth/issues) that might be solved by this PR.
|
||||
|
||||
If you write `"Fixes"` or `"Closes"` before the issue link like so:
|
||||
Fixes: INSERT_ISSUE_LINK_HERE
|
||||
|
||||
```
|
||||
Fixes #359
|
||||
```
|
||||
## 📌 Resources
|
||||
|
||||
the connected issue will be automatically closed once the PR is merged and hence help with maintenance of the library 😊
|
||||
|
||||
-->
|
||||
- [Contributing guidelines](./CONTRIBUTING.md)
|
||||
- [Code of conduct](./CODE_OF_CONDUCT.md)
|
||||
- [Contributing to Open Source](https://kcd.im/pull-request)
|
||||
|
||||
69
.github/workflows/release.yml
vendored
69
.github/workflows/release.yml
vendored
@@ -16,26 +16,23 @@ jobs:
|
||||
steps:
|
||||
- name: Init
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
with:
|
||||
version: 6.32.8
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: "yarn"
|
||||
- name: Cache Node Modules
|
||||
id: cache-node
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: yarn --prefer-offline --frozen-lockfile
|
||||
run: pnpm install
|
||||
- name: Build
|
||||
run: yarn build
|
||||
run: pnpm build
|
||||
- name: Run tests
|
||||
run: yarn test
|
||||
run: pnpm test
|
||||
env:
|
||||
UPSTASH_REDIS_URL: ${{ secrets.UPSTASH_REDIS_URL }}
|
||||
UPSTASH_REDIS_KEY: ${{ secrets.UPSTASH_REDIS_KEY }}
|
||||
@@ -55,30 +52,25 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
with:
|
||||
version: 6.32.8
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: "yarn"
|
||||
- name: Cache Node Modules
|
||||
id: cache-node
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: yarn --prefer-offline --frozen-lockfile
|
||||
run: pnpm install
|
||||
- name: Publish to npm and GitHub
|
||||
run: |
|
||||
git config --global user.email "balazsorban44@users.noreply.github.com"
|
||||
git config --global user.name "Balázs Orbán"
|
||||
yarn release
|
||||
pnpm release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN_PKG }}
|
||||
NPM_TOKEN_ORG: ${{ secrets.NPM_TOKEN_ORG }}
|
||||
release-pr:
|
||||
name: Publish PR
|
||||
@@ -89,22 +81,17 @@ jobs:
|
||||
steps:
|
||||
- name: Init
|
||||
uses: actions/checkout@v2
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
with:
|
||||
version: 6.32.8
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: "yarn"
|
||||
- name: Cache Node Modules
|
||||
id: cache-node
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
cache-node_modules-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}-
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: yarn --prefer-offline --frozen-lockfile
|
||||
run: pnpm install
|
||||
- name: Determine version
|
||||
uses: ./.github/version-pr
|
||||
id: determine-version
|
||||
@@ -114,7 +101,7 @@ jobs:
|
||||
run: |
|
||||
cd packages/next-auth
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
|
||||
npm publish --access public --tag experimental
|
||||
pnpm publish --no-git-checks --access public --tag experimental
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Comment version on PR
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
# Misc
|
||||
.DS_Store
|
||||
.npmrc
|
||||
|
||||
.env
|
||||
.env.local
|
||||
@@ -11,6 +12,7 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
firebase-debug.log
|
||||
.pnpm-debug.log
|
||||
|
||||
|
||||
# Dependencies
|
||||
|
||||
@@ -6,19 +6,20 @@
|
||||
"scripts": {
|
||||
"clean": "rm -rf .next",
|
||||
"copy:css": "cpx \"../../packages/next-auth/css/**/*\" src/css --watch",
|
||||
"watch:css": "cd ../../packages/next-auth && npm run watch:css",
|
||||
"dev": "npm-run-all --parallel dev:next watch:css copy:css",
|
||||
"dev:next": "npx next dev",
|
||||
"build": "npx next build",
|
||||
"watch:css": "cd ../../packages/next-auth && pnpm watch:css",
|
||||
"dev": "concurrently \"pnpm dev:next\" \"pnpm watch:css\" \"pnpm copy:css\"",
|
||||
"dev:next": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"email": "npx fake-smtp-server",
|
||||
"start:email": "npm run email"
|
||||
"email": "fake-smtp-server",
|
||||
"start:email": "pnpm email"
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@next-auth/fauna-adapter": "^1.0.1",
|
||||
"@next-auth/prisma-adapter": "^1.0.1",
|
||||
"@prisma/client": "^3.10.0",
|
||||
"cpx": "^1.5.0",
|
||||
"fake-smtp-server": "^0.8.0",
|
||||
"faunadb": "^4.4.1",
|
||||
"next": "^12.1.0",
|
||||
@@ -29,6 +30,7 @@
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.37",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"concurrently": "^7.1.0",
|
||||
"prisma": "^3.10.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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';
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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";
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"cookie": "0.4.1",
|
||||
"next-auth": "^4.2.1"
|
||||
"next-auth": "^4.3.3"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
|
||||
<style>
|
||||
:global(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";
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -1201,9 +1201,9 @@ minimatch@^3.0.4:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
||||
mkdirp@^0.5.1:
|
||||
version "0.5.5"
|
||||
@@ -1232,10 +1232,10 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||
|
||||
next-auth@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.2.1.tgz#042e4858d9f67b4f702d3a55bae0d2f04db3cac3"
|
||||
integrity sha512-XDtt7nqevkNf4EJ2zKAKkI+MFsURf11kx11vPwxrBYA1MHeqWwaWbGOUOI2ekNTvfAg4nTEJJUH3LV2cLrH3Tg==
|
||||
next-auth@^4.3.3:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.3.3.tgz#5ff892e73648a0f33c2af0e9d7cafda729f63ae7"
|
||||
integrity sha512-bUs+oOOPT18Pq/+4v9q4PA/DGoVoAX6jwY7RTfE/akFXwlny+y/mNS6lPSUwpqcHjljqBaq34PQA3+01SdOOPw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.16.3"
|
||||
"@panva/hkdf" "^1.0.1"
|
||||
|
||||
@@ -119,6 +119,8 @@ NextAuthTable:
|
||||
KeyType: RANGE
|
||||
GlobalSecondaryIndexes:
|
||||
- IndexName: GSI1
|
||||
Projection:
|
||||
ProjectionType: ALL
|
||||
KeySchema:
|
||||
- AttributeName: GSI1PK
|
||||
KeyType: HASH
|
||||
|
||||
@@ -133,12 +133,22 @@ npx prisma migrate dev
|
||||
|
||||
### MongoDB
|
||||
|
||||
Prisma supports MongoDB, and so does NextAuth.js. Following the instructions of the [Prisma documentation](https://www.prisma.io/docs/concepts/database-connectors/mongodb) on the MongoDB connector, the only thing you have to change is making sure that the `id` fields are mapped correctly:
|
||||
Prisma supports MongoDB, and so does NextAuth.js. Following the instructions of the [Prisma documentation](https://www.prisma.io/docs/concepts/database-connectors/mongodb) on the MongoDB connector, things you have to change are:
|
||||
|
||||
1. Make sure that the id fields are mapped correctly
|
||||
|
||||
```prisma
|
||||
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||
```
|
||||
|
||||
2. The Native database type attribute to `@db.String` from `@db.Text`.
|
||||
|
||||
```prisma
|
||||
refresh_token String? @db.String
|
||||
access_token String? @db.String
|
||||
id_token String? @db.String
|
||||
```
|
||||
|
||||
Everything else should be the same.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
@@ -87,10 +87,11 @@ The default redirect callback looks like this:
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
...
|
||||
callbacks: {
|
||||
redirect({ url, baseUrl }) {
|
||||
if (url.startsWith(baseUrl)) return url
|
||||
async redirect({ url, baseUrl }) {
|
||||
// Allows relative callback URLs
|
||||
else if (url.startsWith("/")) return new URL(url, baseUrl).toString()
|
||||
if (url.startsWith("/")) return `${baseUrl}${url}`
|
||||
// Allows callback URLs on the same origin
|
||||
else if (new URL(url).origin === baseUrl) return url
|
||||
return baseUrl
|
||||
}
|
||||
}
|
||||
@@ -104,7 +105,7 @@ The redirect callback may be invoked more than once in the same flow.
|
||||
## JWT callback
|
||||
|
||||
This callback is called whenever a JSON Web Token is created (i.e. at sign
|
||||
in) or updated (i.e whenever a session is accessed in the client). The returned value will be [signed and optionally encrypted](/configuration/options#jwt), and it is stored in a cookie.
|
||||
in) or updated (i.e whenever a session is accessed in the client). The returned value will be [encrypted](/configuration/options#jwt), and it is stored in a cookie.
|
||||
|
||||
Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`, `useSession()` will invoke this function, but only if you are using a [JWT session](/configuration/options#session). This method is not invoked when you persist sessions in a database.
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ Sent when an account in a given provider is linked to a user in our user databas
|
||||
The message object will contain:
|
||||
|
||||
- `user`: The user object from your adapter.
|
||||
- `providerAccount`: The object returned from the provider.
|
||||
- `account`: The object returned from the provider.
|
||||
|
||||
### session
|
||||
|
||||
|
||||
@@ -16,16 +16,53 @@ You must set the [`NEXTAUTH_SECRET`](/configuration/options#nextauth_secret) env
|
||||
|
||||
**We strongly recommend** replacing the `secret` value completely with this `NEXTAUTH_SECRET` environment variable. This environment variable will be picked up by both the [NextAuth config](/configuration/options#options), as well as the middleware config.
|
||||
|
||||
---
|
||||
|
||||
### Basic usage
|
||||
```js
|
||||
import withAuth from "next-auth/middleware"
|
||||
// or
|
||||
import { withAuth } from "next-auth/middleware"
|
||||
```
|
||||
|
||||
---
|
||||
### Custom JWT decode method
|
||||
|
||||
If you have custom jwt decode method set in `[...nextauth].ts`, you must also pass the same `decode` method to `withAuth` in order to read the custom-signed JWT correctly. You may want to extract the encode/decode logic to a separate function for consistency.
|
||||
|
||||
`[...nextauth].ts`
|
||||
```ts
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
export default NextAuth({
|
||||
providers: [...],
|
||||
secret: /* Please use `process.env.NEXTAUTH_SECRET` */,
|
||||
jwt: {
|
||||
encode: async ({ secret, token }) => {
|
||||
return jwt.sign(token as any, secret);
|
||||
},
|
||||
decode: async ({ secret, token }) => {
|
||||
return jwt.verify(token as string, secret) as any;
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Any `_middleware.ts`
|
||||
```ts
|
||||
import withAuth from "next-auth/middleware"
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
export default withAuth({
|
||||
jwt: {
|
||||
decode: async ({ secret, token }) => {
|
||||
return jwt.verify(token, secret) as any;
|
||||
},
|
||||
},
|
||||
callbacks: {
|
||||
authorized: ({ token }) => !!token,
|
||||
},
|
||||
})
|
||||
```
|
||||
---
|
||||
### `callbacks`
|
||||
|
||||
- **Required:** No
|
||||
|
||||
@@ -25,7 +25,7 @@ Using [System Environment Variables](https://vercel.com/docs/concepts/projects/e
|
||||
|
||||
Used to encrypt the NextAuth.js JWT, and to hash [email verification tokens](/adapters/models#verification-token). This is the default value for the [`secret`](/configuration/options#secret) option. The `secret` option might be removed in the future in favor of this.
|
||||
|
||||
If you are using [Middleware](/configuration/nextjs#prerequisites) this environment variables must be set.
|
||||
If you are using [Middleware](/configuration/nextjs#prerequisites) this environment variable must be set.
|
||||
|
||||
### NEXTAUTH_URL_INTERNAL
|
||||
|
||||
@@ -97,7 +97,7 @@ Default values for this option are shown below:
|
||||
```js
|
||||
session: {
|
||||
// Choose how you want to save the user session.
|
||||
// The default is `"jwt"`, an encrypted JWT (JWE) in the session cookie.
|
||||
// The default is `"jwt"`, an encrypted JWT (JWE) stored in the session cookie.
|
||||
// If you use an `adapter` however, we default it to `"database"` instead.
|
||||
// You can still force a JWT session by explicitly defining `"jwt"`.
|
||||
// When using `"database"`, the session cookie will only contain a `sessionToken` value,
|
||||
@@ -123,7 +123,7 @@ session: {
|
||||
|
||||
#### Description
|
||||
|
||||
JSON Web Tokens can be used for session tokens if enabled with `session: { strategy: "jwt" }` option. JSON Web Tokens are enabled by default if you have not specified an adapter. JSON Web Tokens are encrypted (JWE) by default. We recommend you keep this behaviour. See the [Override JWT `encode` and `decode` methods] advanced option.(#override-jwt-encode-and-decode-methods)
|
||||
JSON Web Tokens can be used for session tokens if enabled with `session: { strategy: "jwt" }` option. JSON Web Tokens are enabled by default if you have not specified an adapter. JSON Web Tokens are encrypted (JWE) by default. We recommend you keep this behaviour. See the [Override JWT `encode` and `decode` methods](#override-jwt-encode-and-decode-methods) advanced option.
|
||||
|
||||
#### JSON Web Token Options
|
||||
|
||||
@@ -226,6 +226,10 @@ pages: {
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
When using this configuration, ensure that these pages actually exist. For example `error: '/auth/error'` refers to a page file at `pages/auth/error.js`.
|
||||
:::
|
||||
|
||||
See the documentation for the [pages option](/configuration/pages) for more information.
|
||||
|
||||
---
|
||||
@@ -285,7 +289,6 @@ events: {
|
||||
async updateUser(message) { /* user updated - e.g. their email was verified */ },
|
||||
async linkAccount(message) { /* account (e.g. Twitter) linked to a user */ },
|
||||
async session(message) { /* session is active */ },
|
||||
async error(message) { /* error in authentication flow */ }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -482,6 +485,8 @@ Using a custom cookie policy may introduce security flaws into your application
|
||||
|
||||
NextAuth.js uses encrypted JSON Web Tokens ([JWE](https://datatracker.ietf.org/doc/html/rfc7516)) by default. Unless you have a good reason, we recommend keeping this behaviour. Although you can override this using the `encode` and `decode` methods. Both methods must be defined at the same time.
|
||||
|
||||
**IMPORTANT: If you use middleware to protect routes, make sure the same method is also set in the [`_middleware.ts` options](/configuration/nextjs#custom-jwt-decode-method)**
|
||||
|
||||
```js
|
||||
jwt: {
|
||||
async encode(params: {
|
||||
@@ -495,7 +500,7 @@ jwt: {
|
||||
async decode(params: {
|
||||
token: string
|
||||
secret: string
|
||||
}: Promise<JWT | null>) {
|
||||
}): Promise<JWT | null> {
|
||||
// return a `JWT` object, or `null` if decoding failed
|
||||
return {}
|
||||
},
|
||||
|
||||
@@ -21,6 +21,10 @@ To add a custom login page, you can use the `pages` option:
|
||||
...
|
||||
```
|
||||
|
||||
:::note
|
||||
When using this configuration, ensure that these pages actually exist. For example `error: '/auth/error'` refers to a page file at `pages/auth/error.js`.
|
||||
:::
|
||||
|
||||
## Error codes
|
||||
|
||||
We purposefully restrict the returned error codes for increased security.
|
||||
@@ -51,7 +55,7 @@ The following errors are passed as error query parameters to the default or over
|
||||
- **SessionRequired**: The content of this page requires you to be signed in at all times. See [useSession](/getting-started/client#require-session) for configuration.
|
||||
- **Default**: Catch all, will apply, if none of the above matched
|
||||
|
||||
Example: `/auth/error?error=Default`
|
||||
Example: `/auth/signin?error=Default`
|
||||
|
||||
## Theming
|
||||
|
||||
@@ -90,24 +94,16 @@ export default function SignIn({ providers }) {
|
||||
)
|
||||
}
|
||||
|
||||
// This is the recommended way for Next.js 9.3 or newer
|
||||
export async function getServerSideProps(context) {
|
||||
const providers = await getProviders()
|
||||
return {
|
||||
props: { providers },
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// If older than Next.js 9.3
|
||||
SignIn.getInitialProps = async () => {
|
||||
return {
|
||||
providers: await getProviders()
|
||||
}
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
There is another, more fully styled example signin page available [here](https://github.com/ndom91/next-auth-example-sign-in-page).
|
||||
|
||||
### Email Sign in
|
||||
|
||||
If you create a custom sign in form for email sign in, you will need to submit both fields for the **email** address and **csrfToken** from **/api/auth/csrf** in a POST request to **/api/auth/signin/email**.
|
||||
@@ -128,22 +124,12 @@ export default function SignIn({ csrfToken }) {
|
||||
)
|
||||
}
|
||||
|
||||
// This is the recommended way for Next.js 9.3 or newer
|
||||
export async function getServerSideProps(context) {
|
||||
const csrfToken = await getCsrfToken(context)
|
||||
return {
|
||||
props: { csrfToken },
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// If older than Next.js 9.3
|
||||
SignIn.getInitialProps = async (context) => {
|
||||
return {
|
||||
csrfToken: await getCsrfToken(context)
|
||||
}
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
You can also use the `signIn()` function which will handle obtaining the CSRF token for you:
|
||||
@@ -176,7 +162,6 @@ export default function SignIn({ csrfToken }) {
|
||||
)
|
||||
}
|
||||
|
||||
// This is the recommended way for Next.js 9.3 or newer
|
||||
export async function getServerSideProps(context) {
|
||||
return {
|
||||
props: {
|
||||
@@ -184,15 +169,6 @@ export async function getServerSideProps(context) {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// If older than Next.js 9.3
|
||||
SignIn.getInitialProps = async (context) => {
|
||||
return {
|
||||
csrfToken: await getCsrfToken(context)
|
||||
}
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
You can also use the `signIn()` function which will handle obtaining the CSRF token for you:
|
||||
|
||||
@@ -21,8 +21,33 @@ Without going into too much detail, the OAuth flow generally has 6 parts:
|
||||
5. The application requests the resource from the resource server (API) and presents the access token for authentication
|
||||
6. If the access token is valid, the resource server (API) serves the resource to the application
|
||||
|
||||
<img src="https://i2.wp.com/blogs.innovationm.com/wp-content/uploads/2019/07/blog-open1.png" alt="OAuth Flow Diagram" /><br />
|
||||
<small>Source: https://dzone.com/articles/open-id-connect-authentication-with-oauth20-author</small>
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Browser
|
||||
participant App Server
|
||||
participant Auth Server (Github)
|
||||
Note left of Browser: User clicks on "Sign in"
|
||||
Browser->>App Server: GET<br/>"api/auth/signin"
|
||||
App Server->>App Server: Computes the available<br/>sign in providers<br/>from the "providers" option
|
||||
App Server->>Browser: Redirects to Sign in page
|
||||
Note left of Browser: Sign in options<br/>are shown the user<br/>(Github, Twitter, etc...)
|
||||
Note left of Browser: User clicks on<br/>"Sign in with Github"
|
||||
Browser->>App Server: POST<br/>"api/auth/signin/github"
|
||||
App Server->>App Server: Computes sign in<br/>options for Github<br/>(scopes, callback URL, etc...)
|
||||
App Server->>Auth Server (Github): GET<br/>"github.com/login/oauth/authorize"
|
||||
Note left of Auth Server (Github): Sign in options<br> are supplied as<br/>query params<br/>(clientId, <br/>scope, etc...)
|
||||
Auth Server (Github)->>Browser: Shows sign in page<br/>in Github.com<br/>to the user
|
||||
Note left of Browser: User inserts their<br/>credentials in Github
|
||||
Browser->>Auth Server (Github): Github validates the inserted credentials
|
||||
Auth Server (Github)->>Auth Server (Github): Generates one time access code<br/>and calls callback<br>URL defined in<br/>App settings
|
||||
Auth Server (Github)->>App Server: GET<br/>"api/auth/github/callback?code=123"
|
||||
App Server->>App Server: Grabs code<br/>to exchange it for<br/>access token
|
||||
App Server->>Auth Server (Github): POST<br/>"github.com/login/oauth/access_token"<br/>{code: 123}
|
||||
Auth Server (Github)->>Auth Server (Github): Verifies code is<br/>valid and generates<br/>access token
|
||||
Auth Server (Github)->>App Server: { access_token: 16C7x... }
|
||||
App Server->>App Server: Generates session token<br/>and stores session
|
||||
App Server->>Browser: You're now logged in!
|
||||
```
|
||||
|
||||
For more details, check out Aaron Parecki's blog post [OAuth2 Simplified](https://aaronparecki.com/oauth-2-simplified/) or Postman's blog post [OAuth 2.0: Implicit Flow is Dead, Try PKCE Instead](https://blog.postman.com/pkce-oauth-how-to/).
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@ Preview deployments at Vercel are often available via multiple URLs. For example
|
||||
|
||||
Netlify is very similar to Vercel in that you can deploy a Next.js project without almost any extra work.
|
||||
|
||||
In order to setup NextAuth.js correctly here, you will want to make sure you add your `NEXTAUTH_SECRET` and `NEXTAUTH_URL` environment variables in the project settings. Netlify also exposes some [system environment variables](https://docs.netlify.com/configure-builds/environment-variables/) from which you can check which `NODE_ENV` you are currently in and much more.
|
||||
In order to setup NextAuth.js correctly here, you will want to make sure you add your `NEXTAUTH_SECRET` environment variable in the project settings. If you are using the [Essential Next.js Build Plugin](https://github.com/netlify/netlify-plugin-nextjs) within your project, you **do not** need to set the `NEXTAUTH_URL` environment variable as it is set automatically as part of the build process.
|
||||
|
||||
Netlify also exposes some [system environment variables](https://docs.netlify.com/configure-builds/environment-variables/) from which you can check which `NODE_ENV` you are currently in and much more.
|
||||
|
||||
After this, just make sure you either have your OAuth provider setup correctly with `clientId` / `clientSecret`'s and callback URLs.
|
||||
|
||||
@@ -99,7 +99,7 @@ This is required to store the verification token. Please see the [email provider
|
||||
|
||||
The Credentials Provider can only be used if JSON Web Tokens are used for sessions.
|
||||
|
||||
JSON Web Tokens are used for Sessions by default if you have not specified a database. However, if you are using a database, then Database Sessions are enabled by default and you need to [explicitly enable JWT Sessions](https://next-auth.js.org/configuration/options#session) to use the Credentials Provider.
|
||||
JSON Web Tokens are used for Sessions by default if you have not specified a database. However, if you are using a database, then Database Sessions are enabled by default and you need to [explicitly enable JWT Sessions](/configuration/options#session) to use the Credentials Provider.
|
||||
|
||||
If you are using a Credentials Provider, NextAuth.js will not persist users or sessions in a database - user accounts used with the Credentials Provider must be created and managed outside of NextAuth.js.
|
||||
|
||||
@@ -111,9 +111,17 @@ This error occurs when there was no `authorize()` handler defined on the credent
|
||||
|
||||
#### PKCE_ERROR
|
||||
|
||||
The provider you tried to use failed when setting [PKCE or Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636#section-4.2).
|
||||
The provider you tried to use failed when setting [PKCE or Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636#section-4).
|
||||
The `code_verifier` is saved in a cookie called (by default) `__Secure-next-auth.pkce.code_verifier` which expires after 15 minutes.
|
||||
Check if `cookies.pkceCodeVerifier` is configured correctly. The default `code_challenge_method` is `"S256"`. This is currently not configurable to `"plain"`, as it is not recommended, and in most cases, it is only supported for backward compatibility.
|
||||
Check if `cookies.pkceCodeVerifier` is configured correctly.
|
||||
|
||||
The default `code_challenge_method` is `"S256"`. This is currently not configurable to `"plain"`, [as per RFC7636](https://datatracker.ietf.org/doc/html/rfc7636#section-4.2):
|
||||
> If the client is capable of using "S256", it MUST use "S256", as
|
||||
S256" is Mandatory To Implement (MTI) on the server.
|
||||
|
||||
#### INVALID_CALLBACK_URL_ERROR
|
||||
|
||||
The `callbackUrl` provided was either invalid or not defined. See [specifying a `callbackUrl`](/getting-started/client#specifying-a-callbackurl) for more information.
|
||||
|
||||
---
|
||||
|
||||
@@ -121,7 +129,7 @@ Check if `cookies.pkceCodeVerifier` is configured correctly. The default `code_c
|
||||
|
||||
#### JWT_SESSION_ERROR
|
||||
|
||||
https://next-auth.js.org/errors#jwt_session_error JWKKeySupport: the key does not support HS512 verify algorithm
|
||||
JWKKeySupport: 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
|
||||
|
||||
@@ -157,7 +165,7 @@ Make sure the file is there and the filename is written correctly.
|
||||
|
||||
#### NO_SECRET
|
||||
|
||||
In production, we expect you to define a `secret` property in your configuration. In development, this is shown as a warning for convenience. [Read more](https://next-auth.js.org/configuration/options#secret)
|
||||
In production, we expect you to define a `secret` property in your configuration. In development, this is shown as a warning for convenience. [Read more](/configuration/options#secret)
|
||||
|
||||
#### oauth_callback_error expected 200 OK with body but no body was returned
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ Ultimately if your request is not accepted or is not actively in development, yo
|
||||
</summary>
|
||||
<p>
|
||||
|
||||
NextAuth.js by default uses JSON Web Tokens for saving the user's session. However, if you use a [database adapter](/adapters/overview), the database will be used to persist the user's session. You can force the usage of JWT when using a database [through the configuration options](/configuration/options#session).
|
||||
NextAuth.js by default uses JSON Web Tokens for saving the user's session. However, if you use a [database adapter](/adapters/overview), the database will be used to persist the user's session. You can force the usage of JWT when using a database [through the configuration options](/configuration/options#session). Since v4 all our JWT tokens are now encrypted by default with A256GCM.
|
||||
|
||||
</p>
|
||||
</details>
|
||||
@@ -285,11 +285,9 @@ JSON Web Tokens can be used for session tokens, but are also used for lots of ot
|
||||
|
||||
- Advantages of using a JWT as a session token include that they do not require a database to store sessions, this can be faster and cheaper to run and easier to scale.
|
||||
|
||||
- JSON Web Tokens in NextAuth.js are secured using cryptographic signing (JWS) by default and it is easy for services and API endpoints to verify tokens without having to contact a database to verify them.
|
||||
- JSON Web Tokens in NextAuth.js are secured using cryptographic encryption (JWE) to store the included information directly in a JWT session token. You may then use the token to pass information between services and APIs on the same domain without having to contact a database to verify the included information.
|
||||
|
||||
- You can enable encryption (JWE) to store include information directly in a JWT session token that you wish to keep secret and use the token to pass information between services / APIs on the same domain.
|
||||
|
||||
- You can use JWT to securely store information you do not mind the client knowing even without encryption, as the JWT is stored in a server-readable-only-token so data in the JWT is not accessible to third party JavaScript running on your site.
|
||||
- You can use JWT to securely store information you do not mind the client knowing even without encryption, as the JWT is stored in a server-readable-only cookie so data in the JWT is not accessible to third party JavaScript running on your site.
|
||||
|
||||
</p>
|
||||
</details>
|
||||
@@ -308,7 +306,7 @@ JSON Web Tokens can be used for session tokens, but are also used for lots of ot
|
||||
|
||||
- As with database session tokens, JSON Web Tokens are limited in the amount of data you can store in them. There is typically a limit of around 4096 bytes per cookie, though the exact limit varies between browsers, proxies and hosting services. If you want to support most browsers, then do not exceed 4096 bytes per cookie. If you want to save more data, you will need to persist your sessions in a database (Source: [browsercookielimits.iain.guru](http://browsercookielimits.iain.guru/))
|
||||
|
||||
The more data you try to store in a token and the more other cookies you set, the closer you will come to this limit. If you wish to store more than ~4 KB of data you're probably at the point where you need to store a unique ID in the token and persist the data elsewhere (e.g. in a server-side key/value store).
|
||||
The more data you try to store in a token and the more other cookies you set, the closer you will come to this limit. Since v4 we have implemented cookie chunking so that cookies over the 4kb limit get split and reassembled upon parsing. However since this data needs to be transmitted on every request, if you wish to store more than ~4 KB of data you're probably at the point where you want to store a unique ID in the token and persist the data elsewhere (e.g. in a server-side key/value store).
|
||||
|
||||
- Data stored in an encrypted JSON Web Token (JWE) may be compromised at some point.
|
||||
|
||||
@@ -316,9 +314,8 @@ JSON Web Tokens can be used for session tokens, but are also used for lots of ot
|
||||
|
||||
Avoid storing any data in a token that might be problematic if it were to be decrypted in the future.
|
||||
|
||||
- If you do not explicitly specify a secret for for NextAuth.js, existing sessions will be invalidated any time your NextAuth.js configuration changes, as NextAuth.js will default to an auto-generated secret.
|
||||
- If you do not explicitly specify a secret for for NextAuth.js, existing sessions will be invalidated any time your NextAuth.js configuration changes, as NextAuth.js will default to an auto-generated secret. Since v4 this only impacts development and generating a secret is required in production.
|
||||
|
||||
If using JSON Web Token you should at least specify a secret and ideally configure public/private keys.
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
@@ -123,20 +123,18 @@ export default function App({
|
||||
}
|
||||
|
||||
function Auth({ children }) {
|
||||
const { data: session, status } = useSession({ required: true })
|
||||
const isUser = !!session?.user
|
||||
// if `{ required: true }` is supplied, `status` can only be "loading" or "authenticated"
|
||||
const { status } = useSession({ required: true })
|
||||
|
||||
if (isUser) {
|
||||
return children
|
||||
if (status === 'loading') {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
// Session is being fetched, or no user.
|
||||
// If no user, useEffect() will redirect.
|
||||
return <div>Loading...</div>
|
||||
|
||||
return children
|
||||
}
|
||||
```
|
||||
|
||||
It can be easily be extended/modified to support something like an options object for role based authentication on pages. An example:
|
||||
It can be easily extended/modified to support something like an options object for role based authentication on pages. An example:
|
||||
|
||||
```jsx title="pages/admin.jsx"
|
||||
AdminDashboard.auth = {
|
||||
@@ -312,11 +310,11 @@ You can specify a different `callbackUrl` by specifying it as the second argumen
|
||||
|
||||
e.g.
|
||||
|
||||
- `signIn(null, { callbackUrl: 'http://localhost:3000/foo' })`
|
||||
- `signIn('google', { callbackUrl: 'http://localhost:3000/foo' })`
|
||||
- `signIn(undefined, { callbackUrl: '/foo' })`
|
||||
- `signIn('google', { callbackUrl: 'http://localhost:3000/bar' })`
|
||||
- `signIn('email', { email, callbackUrl: 'http://localhost:3000/foo' })`
|
||||
|
||||
The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect-callback). By default it requires the URL to be an absolute URL at the same host name, or else it will redirect to the homepage. You can define your own [redirect callback](/configuration/callbacks#redirect-callback) to allow other URLs, including supporting relative URLs.
|
||||
The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect-callback). By default it requires the URL to be an absolute URL at the same host name, or a relative url starting with a slash. If it does not match it will redirect to the homepage. You can define your own [redirect callback](/configuration/callbacks#redirect-callback) to allow other URLs.
|
||||
|
||||
### Using the `redirect: false` option
|
||||
|
||||
@@ -400,7 +398,7 @@ As with the `signIn()` function, you can specify a `callbackUrl` parameter by pa
|
||||
|
||||
e.g. `signOut({ callbackUrl: 'http://localhost:3000/foo' })`
|
||||
|
||||
The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect-callback). By default this means it must be an absolute URL at the same host name (or else it will default to the homepage); you can define your own custom [redirect callback](/configuration/callbacks#redirect-callback) to allow other URLs, including supporting relative URLs.
|
||||
The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect-callback). By default, it requires the URL to be an absolute URL at the same host name, or you can also supply a relative URL starting with a slash. If it does not match it will redirect to the homepage. You can define your own [redirect callback](/configuration/callbacks#redirect-callback) to allow other URLs.
|
||||
|
||||
### Using the `redirect: false` option
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ The easiest way to get started is to clone the [example app](https://github.com/
|
||||
|
||||
To add NextAuth.js to a project create a file called `[...nextauth].js` in `pages/api/auth`. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
```javascript title="pages/api/auth/[...nextauth].js" showLineNumbers
|
||||
import NextAuth from "next-auth"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
|
||||
@@ -42,8 +42,7 @@ All requests to `/api/auth/*` (`signIn`, `callback`, `signOut`, etc.) will autom
|
||||
|
||||
To be able to use `useSession` first you'll need to expose the session context, [`<SessionProvider />`](/getting-started/client#sessionprovider), at the top level of your application:
|
||||
|
||||
```javascript
|
||||
// pages/_app.js
|
||||
```jsx title="pages/_app.jsx" showLineNumbers
|
||||
import { SessionProvider } from "next-auth/react"
|
||||
|
||||
export default function App({
|
||||
@@ -68,7 +67,7 @@ Check out the [client documentation](/getting-started/client) to see how you can
|
||||
|
||||
The [`useSession()`](/getting-started/client#usesession) React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
|
||||
|
||||
```javascript
|
||||
```jsx title="components/login-btn.jsx" showLineNumbers
|
||||
import { useSession, signIn, signOut } from "next-auth/react"
|
||||
|
||||
export default function Component() {
|
||||
@@ -96,7 +95,7 @@ You can use the `useSession` hook from anywhere in your application (e.g. in a h
|
||||
|
||||
To protect an API Route, you can use the [`getSession()`](/getting-started/client#getsession) method in the NextAuth.js client.
|
||||
|
||||
```javascript
|
||||
```javascript title="pages/api/restricted.js" showLineNumbers
|
||||
import { getSession } from "next-auth/react"
|
||||
|
||||
export default async (req, res) => {
|
||||
@@ -123,18 +122,20 @@ NextAuth.js allows you to hook into various parts of the authentication flow via
|
||||
|
||||
For example, to pass a value from the sign-in to the frontend, client-side, you can use a combination of the [`session`](/configuration/callbacks#session-callback) and [`jwt`](/configuration/callbacks#jwt-callback) callback like so:
|
||||
|
||||
```javascript
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
...
|
||||
callbacks: {
|
||||
async jwt({ token, account }) {
|
||||
// Persist the OAuth access_token to the token right after signin
|
||||
if (account) {
|
||||
// highlight-next-line
|
||||
token.accessToken = account.access_token
|
||||
}
|
||||
return token
|
||||
},
|
||||
async session({ session, token, user }) {
|
||||
// Send properties to the client, like an access_token from a provider.
|
||||
// highlight-next-line
|
||||
session.accessToken = token.accessToken
|
||||
return session
|
||||
}
|
||||
@@ -144,10 +145,11 @@ callbacks: {
|
||||
|
||||
Now whenever you call `getSession` or `useSession`, the data object which is returned will include the `accessToken` value.
|
||||
|
||||
```js
|
||||
```jsx title="components/accessToken.jsx" showLineNumbers
|
||||
import { useSession, signIn, signOut } from "next-auth/react"
|
||||
|
||||
export default function Component() {
|
||||
// highlight-next-line
|
||||
const { data } = useSession()
|
||||
const { accessToken } = data
|
||||
|
||||
@@ -158,7 +160,7 @@ export default function Component() {
|
||||
## Configuring callback URL (OAuth only)
|
||||
|
||||
If you are using an OAuth provider either through one of our [built-in providers](/configuration/providers/oauth)
|
||||
or through a [custom provider](/configuration/providers/oauth#using-a-custom-provider), you'll need to configure
|
||||
or through a [custom provider](/configuration/providers/oauth#using-a-custom-provider), you'll need to configure
|
||||
a callback URL in your provider's settings. Each provider has a "Configuration" section that should give you pointers on how to do that.
|
||||
|
||||
Follow [these steps](/configuration/providers/oauth#how-to) to learn how to integrate with an OAuth provider.
|
||||
|
||||
@@ -38,8 +38,7 @@ _Note: Email sign-in requires a database to be configured to store single-use ve
|
||||
- Designed to be secure by default and encourage best practices for safeguarding user data
|
||||
- Uses Cross-Site Request Forgery Tokens on POST routes (sign in, sign out)
|
||||
- Default cookie policy aims for the most restrictive policy appropriate for each cookie
|
||||
- When JSON Web Tokens are enabled, they are signed by default (JWS) with HS512
|
||||
- Use JWT encryption (JWE) by setting the option `encryption: true` (defaults to A256GCM)
|
||||
- When JSON Web Tokens are enabled, they are encrypted by default (JWE) with A256GCM
|
||||
- Auto-generates symmetric signing and encryption keys for developer convenience
|
||||
- Features tab/window syncing and keepalive messages to support short-lived sessions
|
||||
- Attempts to implement the latest guidance published by [Open Web Application Security Project](https://owasp.org/)
|
||||
|
||||
@@ -47,7 +47,7 @@ This will work in code editors with a strong TypeScript integration like VSCode
|
||||
|
||||
Let's look at `Session`:
|
||||
|
||||
```ts title="pages/api/[...nextauth].ts"
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
export default NextAuth({
|
||||
|
||||
@@ -331,7 +331,7 @@ The way we save data with adapters have slightly changed. With the new Adapter A
|
||||
- `user_id`/`userId` consistently named `userId`.
|
||||
- `compound_id`/`compoundId` is removed from Account.
|
||||
- `access_token`/`accessToken` is removed from Session.
|
||||
- `email_verified`/`emailVerified` on User is consistently named `email_verified`.
|
||||
- `email_verified`/`emailVerified` on User is consistently named `emailVerified`.
|
||||
- `provider_id`/`providerId` renamed to `provider` on Account
|
||||
- `provider_type`/`providerType` renamed to `type` on Account
|
||||
- `provider_account_id`/`providerAccountId` on Account is consistently named `providerAccountId`
|
||||
@@ -419,8 +419,8 @@ They are designed to be run directly against the database itself. So instead of
|
||||
/* ACCOUNT */
|
||||
ALTER TABLE accounts
|
||||
CHANGE "access_token_expires" "expires_at" int
|
||||
CHANGE "user_id" "userId" varchar(191)
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
CHANGE "user_id" "userId" varchar(255)
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY (userId) REFERENCES users(id)
|
||||
RENAME COLUMN "provider_id" "provider"
|
||||
RENAME COLUMN "provider_account_id" "providerAccountId"
|
||||
DROP COLUMN "provider_type"
|
||||
@@ -429,14 +429,14 @@ DROP COLUMN "compound_id"
|
||||
DROP COLUMN "created_at"
|
||||
DROP COLUMN "updated_at"
|
||||
|
||||
ADD COLUMN "token_type" varchar(191) NULL
|
||||
ADD COLUMN "scope" varchar(191) NULL
|
||||
ADD COLUMN "id_token" varchar(191) NULL
|
||||
ADD COLUMN "session_state" varchar(191) NULL
|
||||
ADD COLUMN "token_type" varchar(255) NULL
|
||||
ADD COLUMN "scope" varchar(255) NULL
|
||||
ADD COLUMN "id_token" varchar(255) NULL
|
||||
ADD COLUMN "session_state" varchar(255) NULL
|
||||
|
||||
/* Note: These are only needed if you're going to be using the old Twitter OAuth 1.0 provider. */
|
||||
ADD COLUMN "oauth_token_secret" varchar(191) NULL
|
||||
ADD COLUMN "oauth_token" varchar(191) NULL
|
||||
ADD COLUMN "oauth_token_secret" varchar(255) NULL
|
||||
ADD COLUMN "oauth_token" varchar(255) NULL
|
||||
|
||||
/* USER */
|
||||
ALTER TABLE users
|
||||
@@ -448,15 +448,16 @@ DROP COLUMN "updated_at"
|
||||
/* SESSION */
|
||||
ALTER TABLE sessions
|
||||
RENAME COLUMN "session_token" "sessionToken"
|
||||
CHANGE "user_id" "userId" varchar(191)
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
CHANGE "user_id" "userId" varchar(255)
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY (userId) REFERENCES users(id)
|
||||
DROP COLUMN "access_token"
|
||||
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||
DROP COLUMN "created_at"
|
||||
DROP COLUMN "updated_at"
|
||||
|
||||
/* VERIFICATION REQUESTS */
|
||||
ALTER TABLE verification_requests
|
||||
ALTER TABLE verification_requests RENAME verification_tokens
|
||||
ALTER TABLE verification_tokens
|
||||
DROP COLUMN id
|
||||
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||
DROP COLUMN "created_at"
|
||||
@@ -467,50 +468,84 @@ DROP COLUMN "updated_at"
|
||||
|
||||
```sql
|
||||
/* ACCOUNT */
|
||||
ALTER TABLE accounts RENAME COLUMN "user_id" TO "userId";
|
||||
ALTER TABLE accounts RENAME COLUMN "provider_id" TO "provider";
|
||||
ALTER TABLE accounts RENAME COLUMN "provider_account_id" TO "providerAccountId";
|
||||
ALTER TABLE accounts RENAME COLUMN "access_token_expires" TO "expires_at";
|
||||
ALTER TABLE accounts RENAME COLUMN "provider_type" TO "type";
|
||||
|
||||
/* Do conversion of TIMESTAMPTZ to BIGINT */
|
||||
ALTER TABLE accounts ALTER COLUMN "expires_at" TYPE TEXT USING CAST(extract(epoch FROM "expires_at") AS BIGINT)*1000;
|
||||
|
||||
/* Keep id as SERIAL with autoincrement when using ORM. Using new v4 uuid format won't work because of incompatibility */
|
||||
/* ALTER TABLE accounts ALTER COLUMN "id" TYPE TEXT; */
|
||||
/* ALTER TABLE accounts ALTER COLUMN "userId" TYPE TEXT; */
|
||||
ALTER TABLE accounts ALTER COLUMN "type" TYPE TEXT;
|
||||
ALTER TABLE accounts ALTER COLUMN "provider" TYPE TEXT;
|
||||
ALTER TABLE accounts ALTER COLUMN "providerAccountId" TYPE TEXT;
|
||||
|
||||
ALTER TABLE accounts ADD CONSTRAINT fk_user_id FOREIGN KEY ("userId") REFERENCES users(id);
|
||||
ALTER TABLE accounts
|
||||
CHANGE "access_token_expires" "expires_at" int
|
||||
CHANGE "user_id" "userId" text
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
RENAME COLUMN "provider_id" "provider"
|
||||
RENAME COLUMN "provider_account_id" "providerAccountId"
|
||||
DROP COLUMN "provider_type"
|
||||
DROP COLUMN "compound_id"
|
||||
DROP COLUMN IF EXISTS "compound_id";
|
||||
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||
DROP COLUMN "created_at"
|
||||
DROP COLUMN "updated_at"
|
||||
|
||||
ADD COLUMN "token_type" text NULL
|
||||
ADD COLUMN "scope" text NULL
|
||||
ADD COLUMN "id_token" text NULL
|
||||
ADD COLUMN "session_state" text NULL
|
||||
ALTER TABLE accounts
|
||||
DROP COLUMN IF EXISTS "created_at",
|
||||
DROP COLUMN IF EXISTS "updated_at";
|
||||
|
||||
ALTER TABLE accounts
|
||||
ADD COLUMN IF NOT EXISTS "token_type" TEXT NULL,
|
||||
ADD COLUMN IF NOT EXISTS "scope" TEXT NULL,
|
||||
ADD COLUMN IF NOT EXISTS "id_token" TEXT NULL,
|
||||
ADD COLUMN IF NOT EXISTS "session_state" TEXT NULL;
|
||||
/* Note: These are only needed if you're going to be using the old Twitter OAuth 1.0 provider. */
|
||||
ADD COLUMN "oauth_token_secret" text NULL
|
||||
ADD COLUMN "oauth_token" text NULL
|
||||
/* ALTER TABLE accounts
|
||||
ADD COLUMN IF NOT EXISTS "oauth_token_secret" TEXT NULL,
|
||||
ADD COLUMN IF NOT EXISTS "oauth_token" TEXT NULL; */
|
||||
|
||||
/* USER */
|
||||
ALTER TABLE users
|
||||
RENAME COLUMN "email_verified" "emailVerified"
|
||||
ALTER TABLE users RENAME COLUMN "email_verified" TO "emailVerified";
|
||||
|
||||
/* Keep id as SERIAL with autoincrement when using ORM. Using new v4 uuid format won't work because of incompatibility */
|
||||
/* ALTER TABLE users ALTER COLUMN "id" TYPE TEXT; */
|
||||
ALTER TABLE users ALTER COLUMN "name" TYPE TEXT;
|
||||
ALTER TABLE users ALTER COLUMN "email" TYPE TEXT;
|
||||
ALTER TABLE users ALTER COLUMN "image" TYPE TEXT;
|
||||
/* Do conversion of TIMESTAMPTZ to BIGINT and then TEXT */
|
||||
ALTER TABLE users ALTER COLUMN "emailVerified" TYPE TEXT USING CAST(CAST(extract(epoch FROM "emailVerified") AS BIGINT)*1000 AS TEXT);
|
||||
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||
DROP COLUMN "created_at"
|
||||
DROP COLUMN "updated_at"
|
||||
ALTER TABLE users
|
||||
DROP COLUMN IF EXISTS "created_at",
|
||||
DROP COLUMN IF EXISTS "updated_at";
|
||||
|
||||
/* SESSION */
|
||||
ALTER TABLE sessions
|
||||
RENAME COLUMN "session_token" "sessionToken"
|
||||
CHANGE "user_id" "userId" text
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
DROP COLUMN "access_token"
|
||||
ALTER TABLE sessions RENAME COLUMN "session_token" TO "sessionToken";
|
||||
ALTER TABLE sessions RENAME COLUMN "user_id" TO "userId";
|
||||
|
||||
/* Keep id as SERIAL with autoincrement when using ORM. Using new v4 uuid format won't work because of incompatibility */
|
||||
/* ALTER TABLE sessions ALTER COLUMN "id" TYPE TEXT; */
|
||||
/* ALTER TABLE sessions ALTER COLUMN "userId" TYPE TEXT; */
|
||||
ALTER TABLE sessions ALTER COLUMN "sessionToken" TYPE TEXT;
|
||||
ALTER TABLE sessions ADD CONSTRAINT fk_user_id FOREIGN KEY ("userId") REFERENCES users(id);
|
||||
/* Do conversion of TIMESTAMPTZ to BIGINT and then TEXT */
|
||||
ALTER TABLE sessions ALTER COLUMN "expires" TYPE TEXT USING CAST(CAST(extract(epoch FROM "expires") AS BIGINT)*1000 AS TEXT);
|
||||
ALTER TABLE sessions DROP COLUMN IF EXISTS "access_token";
|
||||
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||
DROP COLUMN "created_at"
|
||||
DROP COLUMN "updated_at"
|
||||
ALTER TABLE sessions
|
||||
DROP COLUMN IF EXISTS "created_at",
|
||||
DROP COLUMN IF EXISTS "updated_at";
|
||||
|
||||
/* VERIFICATION REQUESTS */
|
||||
ALTER TABLE verification_requests
|
||||
DROP COLUMN id
|
||||
ALTER TABLE verification_requests RENAME TO verification_tokens;
|
||||
/* Keep id as ORM needs it */
|
||||
/* ALTER TABLE verification_tokens DROP COLUMN IF EXISTS id; */
|
||||
ALTER TABLE verification_tokens ALTER COLUMN "identifier" TYPE TEXT;
|
||||
ALTER TABLE verification_tokens ALTER COLUMN "token" TYPE TEXT;
|
||||
/* Do conversion of TIMESTAMPTZ to BIGINT and then TEXT */
|
||||
ALTER TABLE verification_tokens ALTER COLUMN "expires" TYPE TEXT USING CAST(CAST(extract(epoch FROM "expires") AS BIGINT)*1000 AS TEXT);
|
||||
/* The following two timestamp columns have never been necessary for NextAuth.js to function, but can be kept if you want */
|
||||
DROP COLUMN "created_at"
|
||||
DROP COLUMN "updated_at"
|
||||
ALTER TABLE verification_tokens
|
||||
DROP COLUMN IF EXISTS "created_at",
|
||||
DROP COLUMN IF EXISTS "updated_at";
|
||||
```
|
||||
|
||||
#### MongoDB
|
||||
|
||||
12
docs/docs/guides/basics.md
Normal file
12
docs/docs/guides/basics.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
id: basics
|
||||
title: Basics
|
||||
---
|
||||
|
||||
### [Securing pages and API routes](/tutorials/securing-pages-and-api-routes)
|
||||
|
||||
- How to restrict access to pages and API routes.
|
||||
|
||||
### [Usage with class components](/tutorials/usage-with-class-components)
|
||||
|
||||
- How to use `useSession()` hook with class components.
|
||||
34
docs/docs/guides/fullstack.md
Normal file
34
docs/docs/guides/fullstack.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
id: fullstack
|
||||
title: Fullstack
|
||||
---
|
||||
|
||||
### [Refresh Token Rotation](/tutorials/refresh-token-rotation)
|
||||
|
||||
- How to implement refresh token rotation.
|
||||
|
||||
### [LDAP Authentication](/tutorials/ldap-auth-example)
|
||||
|
||||
- How to use the Credentials Provider to authenticate against an LDAP database. This approach can be used to authenticate existing user accounts against any backend.
|
||||
|
||||
### [Adding HTTP(S) Proxy Support](/tutorials/corporate-proxy)
|
||||
|
||||
- Add support for HTTP/HTTPS Proxy support to `openid-client` in order to use NextAuth.js behind a corporate proxy or other locked down network.
|
||||
|
||||
### [Using the Email Provider behind Corporate Email Scanning Services](/tutorials/avoid-corporate-link-checking-email-provider)
|
||||
|
||||
- An internal tutorial on modifying the catch-all API Route to gracefully handle `HEAD` requests.
|
||||
|
||||
## Database
|
||||
|
||||
### [Custom models with TypeORM](/adapters/typeorm#custom-models)
|
||||
|
||||
- How to use models with custom properties using the TypeORM adapter.
|
||||
|
||||
### [Creating a database adapter](/tutorials/creating-a-database-adapter)
|
||||
|
||||
- How to create a custom adapter, to use any database to fetch and store user / account data.
|
||||
|
||||
### [Adding role based login to database session strategy](/tutorials/role-based-login-strategy)
|
||||
|
||||
- Implement a role based login system by adding a custom session callback.
|
||||
17
docs/docs/guides/index.md
Normal file
17
docs/docs/guides/index.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: guides
|
||||
title: Guides
|
||||
---
|
||||
|
||||
# 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}/>
|
||||
```
|
||||
|
||||
If you can't find what you're looking for here, maybe take a look at our third-party [tutorials](/tutorials) page.
|
||||
8
docs/docs/guides/testing.md
Normal file
8
docs/docs/guides/testing.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: testing
|
||||
title: Testing
|
||||
---
|
||||
|
||||
### [Testing with Cypress](/tutorials/testing-with-cypress)
|
||||
|
||||
- How to write tests using Cypress.
|
||||
@@ -31,5 +31,5 @@ providers: [
|
||||
```
|
||||
|
||||
:::note
|
||||
`issuer` should include the slug – e.g. `https://my-authentik-domain.com/application/o/My_Slug/`
|
||||
`issuer` should include the slug without a trailing slash – e.g., `https://my-authentik-domain.com/application/o/My_Slug`
|
||||
:::
|
||||
|
||||
@@ -30,7 +30,7 @@ import BoxyHQSAMLProvider from "next-auth/providers/boxyhq-saml"
|
||||
...
|
||||
providers: [
|
||||
BoxyHQSAMLProvider({
|
||||
issuer: "http://localhost:5000",
|
||||
issuer: "http://localhost:5225",
|
||||
clientId: "dummy", // The dummy here is necessary since we'll pass tenant and product custom attributes in the client code
|
||||
clientSecret: "dummy", // The dummy here is necessary since we'll pass tenant and product custom attributes in the client code
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@ The **Credentials Provider** comes with a set of default options:
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
## Example
|
||||
## Example - Username / Password
|
||||
|
||||
The Credentials provider is specified like other providers, except that you need to define a handler for `authorize()` that accepts credentials submitted via HTTP POST as input and returns either:
|
||||
|
||||
@@ -73,9 +73,19 @@ providers: [
|
||||
|
||||
See the [callbacks documentation](/configuration/callbacks) for more information on how to interact with the token.
|
||||
|
||||
## Example - Web3 / Signin With Ethereum
|
||||
|
||||
The credentials provider can also be used to integrate with a service like [Sign-in With Ethereum](https://login.xyz).
|
||||
|
||||
For more information, check out the links below:
|
||||
|
||||
- [Tutorial](https://docs.login.xyz/integrations/nextauth.js)
|
||||
- [Example App Repo](https://github.com/spruceid/siwe-next-auth-example).
|
||||
- [Example App Demo](https://siwe-next-auth-example2.vercel.app/).
|
||||
|
||||
## Multiple providers
|
||||
|
||||
### Example code
|
||||
### Example
|
||||
|
||||
You can specify more than one credentials provider by specifying a unique `id` for each one.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ https://discord.com/developers/applications
|
||||
|
||||
The **Discord Provider** comes with a set of default options:
|
||||
|
||||
- [Discord Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/discord.js)
|
||||
- [Discord Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/discord.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ https://developers.google.com/identity/protocols/oauth2
|
||||
|
||||
https://console.developers.google.com/apis/credentials
|
||||
|
||||
The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path. For example;
|
||||
|
||||
- For production: `https://{YOUR_DOMAIN}/api/auth/callback/google`
|
||||
- For development: `http://localhost:3000/api/auth/callback/google`
|
||||
|
||||
## Options
|
||||
|
||||
The **Google Provider** comes with a set of default options:
|
||||
|
||||
@@ -37,5 +37,5 @@ providers: [
|
||||
```
|
||||
|
||||
:::note
|
||||
`issuer` should include the realm – e.g. `https://my-keycloak-domain.com/auth/realms/My_Realm`
|
||||
`issuer` should include the realm – e.g. `https://my-keycloak-domain.com/realms/My_Realm`
|
||||
:::
|
||||
|
||||
@@ -41,9 +41,9 @@ providers: [
|
||||
You must enable the _"Request email address from users"_ option in your app permissions if you want to obtain the users email address.
|
||||
:::
|
||||
|
||||

|
||||

|
||||
|
||||
## OAuth 2
|
||||
## OAuth 2.0
|
||||
|
||||
Twitter supports OAuth 2, which is currently opt-in. To enable it, simply add `version: "2.0"` to your Provider configuration:
|
||||
|
||||
@@ -56,3 +56,7 @@ TwitterProvider({
|
||||
```
|
||||
|
||||
Keep in mind that although this change is easy, it changes how and with which of [Twitter APIs](https://developer.twitter.com/en/docs/api-reference-index) you can interact with. Read the official [Twitter OAuth 2 documentation](https://developer.twitter.com/en/docs/authentication/oauth-2-0) for more details.
|
||||
|
||||
:::note
|
||||
Email is currently not supported by Twitter OAuth 2.0.
|
||||
:::
|
||||
|
||||
43
docs/docs/providers/united-effects.md
Normal file
43
docs/docs/providers/united-effects.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
id: united-effects
|
||||
title: United Effects
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
https://docs.unitedeffects.com/integrations/nextauthjs
|
||||
|
||||
## Configuration
|
||||
|
||||
https://core.unitedeffects.com
|
||||
|
||||
## Options
|
||||
|
||||
The **United Effects Provider** comes with a set of default options:
|
||||
|
||||
- [United Effects Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/united-effects.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import UnitedEffectsProvider from "next-auth/providers/united-effects";
|
||||
...
|
||||
providers: [
|
||||
UnitedEffectsProvider({
|
||||
clientId: process.env.UNITED_EFFECTS_CLIENT_ID,
|
||||
clientSecret: process.env.UNITED_EFFECTS_CLIENT_SECRET,
|
||||
issuer: process.env.UNITED_EFFECTS_ISSUER
|
||||
})
|
||||
]
|
||||
...
|
||||
```
|
||||
|
||||
:::note
|
||||
`issuer` should be the fully qualified URL including your Auth Group ID – e.g. `https://auth.unitedeffects.com/YQpbQV5dbW-224dCovz-3`
|
||||
:::
|
||||
|
||||
:::warning
|
||||
The United Effects API does not return the user name or image by design, so this provider will return null for both. United Effects prioritizes user personal information security above all and has built a secured profile access request system separate from the provider API.
|
||||
:::
|
||||
@@ -94,20 +94,10 @@ export default function SignIn({ providers }) {
|
||||
)
|
||||
}
|
||||
|
||||
// This is the recommended way for Next.js 9.3 or newer
|
||||
export async function getServerSideProps(context) {
|
||||
const providers = await getProviders()
|
||||
return {
|
||||
props: { providers },
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// If older than Next.js 9.3
|
||||
SignIn.getInitialProps = async () => {
|
||||
return {
|
||||
providers: await getProviders()
|
||||
}
|
||||
}
|
||||
*/
|
||||
```
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { CustomSandpack } from "../src/components/Sandpack"
|
||||
|
||||
<CustomSandpack />
|
||||
@@ -13,7 +13,7 @@ title: Tutorials and Explainers
|
||||
|
||||
- This is an introductory video to NextAuth.js for beginners. In this video, it is explained how to set up authentication in a few easy steps and add different configurations to make it more robust and secure.
|
||||
|
||||
#### [Authentication patterns for Next.js](https://leerob.io/blog/nextjs-authentication) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
#### [Authentication patterns for Next.js](https://nextjs.org/docs/authentication) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
- Next.js supports multiple patterns for authentication, each designed for different use cases. This guide will allow you to choose your adventure based on your constraints. By Lee Robinson.
|
||||
|
||||
@@ -21,14 +21,6 @@ title: Tutorials and Explainers
|
||||
|
||||
- This tutorial walks one through adding NextAuth.js to an existing project. Including setting up the OAuth client id and secret, adding the API routes for authentication, protecting pages and API routes behind that authentication, etc.
|
||||
|
||||
#### [Securing pages and API routes](tutorials/securing-pages-and-api-routes)
|
||||
|
||||
- How to restrict access to pages and API routes.
|
||||
|
||||
#### [Usage with class components](tutorials/usage-with-class-components)
|
||||
|
||||
- How to use `useSession()` hook with class components.
|
||||
|
||||
#### [Adding social authentication support to a Next.js app](https://getstarted.sh/bulletproof-next/add-social-authentication) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
- A tutorial by Arunoda Susirpiala. Checkout [GetStarted](https://getstarted.sh/) for more examples.
|
||||
@@ -49,8 +41,26 @@ title: Tutorials and Explainers
|
||||
|
||||
- A video tutorial by Xiaoru Li from Prisma.
|
||||
|
||||
#### [How to authenticate Next.js Apps with Sign-In With Ethereum (SIWE) & NextAuth.js](https://docs.login.xyz/integrations/nextauth.js) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
- Learn how to use Sign-In With Ethereum to authenticate your users with their existing Ethereum wallets - identifiers they personally control.
|
||||
- Example application: [spruceid/siwe-next-auth-example](https://github.com/spruceid/siwe-next-auth-example)
|
||||
|
||||
## Fullstack
|
||||
|
||||
#### [Build a FullStack App with Next.js, NextAuth.js, Supabase & Prisma](https://themodern.dev/courses/build-a-fullstack-app-with-nextjs-supabase-and-prisma-322389284337222224) <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>
|
||||
|
||||
In this [free course](https://themodern.dev/courses/build-a-fullstack-app-with-nextjs-supabase-and-prisma-322389284337222224), you'll learn how to build a full-stack app using the following technologies:
|
||||
|
||||
- **Next.js** - The React framework for building the UI of the app and the REST API
|
||||
- **NextAuth.js** - For implementing passwordless and OAuth authentication
|
||||
- **Supabase** - For persisting the app data into a PostgreSQL database and storing media files
|
||||
- **Prisma** - For making it easy to read and write data from our app from and to the database
|
||||
|
||||
The app that we'll work on in this course is called **_SupaVacation_**. It is an online marketplace for vacation rentals where users can browse through all the properties for rent, bookmark their favorite ones, and even rent their own properties.
|
||||
|
||||
> Here's [a live demo](https://supa-vacation.vercel.app/) of the app's final version. It is what your app should look likes after completing this course. Feel free to play with it to get an overview of all the features you'll be working on.
|
||||
|
||||
#### [Magic Link Authentication in Next.js with NextAuth and Fauna](https://alterclass.io/tutorials/magic-link-authentication-in-nextjs-with-nextauth-and-fauna) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
Learn how to implement passwordless/magic link authentication with database storage in your Next.js projects using NextAuth and Fauna DB.
|
||||
@@ -75,22 +85,8 @@ This tutorial covers:
|
||||
|
||||
- This example shows how to implement a full-stack app in TypeScript with Next.js using Prisma Client as a backend. It also demonstrates how to implement authentication using NextAuth.js. By Nikolas Burk at Prisma.
|
||||
|
||||
## Testing
|
||||
|
||||
#### [Testing with Cypress](tutorials/testing-with-cypress)
|
||||
|
||||
- How to write tests using Cypress.
|
||||
|
||||
## Advanced
|
||||
|
||||
#### [Refresh Token Rotation](tutorials/refresh-token-rotation)
|
||||
|
||||
- How to implement refresh token rotation.
|
||||
|
||||
#### [LDAP Authentication](tutorials/ldap-auth-example)
|
||||
|
||||
- How to use the Credentials Provider to authenticate against an LDAP database. This approach can be used to authenticate existing user accounts against any backend.
|
||||
|
||||
#### [Add auth support to a Next.js app with a custom backend](https://arunoda.me/blog/add-auth-support-to-a-next-js-app-with-a-custom-backend) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
- A tutorial by Arunoda Susirpiala.
|
||||
@@ -109,14 +105,6 @@ This tutorial covers:
|
||||
|
||||
## Database
|
||||
|
||||
#### [Custom models with TypeORM](adapters/typeorm#custom-models)
|
||||
|
||||
- How to use models with custom properties using the TypeORM adapter.
|
||||
|
||||
#### [Creating a database adapter](tutorials/creating-a-database-adapter)
|
||||
|
||||
- How to create a custom adapter, to use any database to fetch and store user / account data.
|
||||
|
||||
#### [Using NextAuth.js with Prisma and PlanetScale serverless databases](https://github.com/planetscale/nextjs-planetscale-starter)
|
||||
#### [Using NextAuth.js with Prisma and PlanetScale serverless databases](https://github.com/planetscale/nextjs-planetscale-starter) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
- How to set up a PlanetScale database to fetch and store user / account data with the Prisma adapter.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
id: avoid-corporate-link-checking-email-provider
|
||||
title: Allow Email Signups Behind Corporate Link Checker
|
||||
---
|
||||
|
||||
If you use Office 365 or Outlook, or potentially other Email systems, you may notice your Email invitation Links not working.
|
||||
|
||||
This is because the invitation Email your User is receiving is being scanned by the Email provider. In the specific case of Outlook and their "SafeLink" feature, they send a HEAD request to each link in the Email. This request will trigger the NextAuth.js catch-all API Route with the users invitation token, in effect using it up.
|
||||
|
||||
Therefore, when the user wants to use it themselves, and clicks on the invitation link they will be greeted with an error message that the invitation is invalid.
|
||||
|
||||
## Workarounds
|
||||
|
||||
### Disable "SafeLink"
|
||||
|
||||
The first potential workaround is to simply disable this "SafeLink" feature for your organisation. Microsoft has more details on this [here](https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/safe-links?view=o365-worldwide#do-not-rewrite-the-following-urls-lists-in-safe-links-policies). Obviously this won't be an option for everyone as this is usually a part of corporate IT policy.
|
||||
|
||||
### Update NextAuth.js for 'HEAD' requests
|
||||
|
||||
The second option is to modify your `[...nextauth].js` catch-all API route a bit to gracefully handle these initial `HEAD` requests from the email service, without accidentally using up the invitation link.
|
||||
|
||||
This can be done by simply returning a `200` response on `HEAD` requests at the very top of the API route, before any other logic is executed.
|
||||
|
||||
For example
|
||||
|
||||
```jsx title="/pages/api/auth/[...nextauth].js"
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
if(req.method === "HEAD") {
|
||||
return res.status(200)
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This should allow you to successfully use NextAuth.js's Email provider behind strict corporate IT settings.
|
||||
83
docs/docs/tutorials/corporate-proxy.md
Normal file
83
docs/docs/tutorials/corporate-proxy.md
Normal file
@@ -0,0 +1,83 @@
|
||||
--
|
||||
id: corporate-proxy
|
||||
title: Add support for HTTP Proxy
|
||||
--
|
||||
|
||||
Using NextAuth.js behind a corporate proxy is not supported out of the box. This is due to the fact that the underlying library we use, [`openid-client`](https://npm.im/openid-client), uses the built-in Node.js `http` / `https` libraries, which do not support proxys by default. (See: [`http` docs](https://nodejs.org/dist/latest-v16.x/docs/api/http.html), [`https` docs](https://nodejs.org/dist/latest-v16.x/docs/api/https.html)).
|
||||
|
||||
Therefore, we'll need to an additional proxy agent to the http client, such as `https-proxy-agent`. `openid-client` allows the user to set an `agent` for requests ([Source](https://github.com/panva/node-openid-client/blob/main/docs/README.md#customizing-individual-http-requests).
|
||||
|
||||
Thanks to [raphaelpc](https://github.com/raphaelpc) for the below diff, which when applied to `v4.2.1`, adds this agent support to the `client.js` file.
|
||||
|
||||
```diff
|
||||
diff --git a/node_modules/next-auth/core/lib/oauth/client.js b/node_modules/next-auth/core/lib/oauth/client.js
|
||||
index 77161bd..1082fba 100644
|
||||
--- a/node_modules/next-auth/core/lib/oauth/client.js
|
||||
+++ b/node_modules/next-auth/core/lib/oauth/client.js
|
||||
@@ -7,11 +7,19 @@ exports.openidClient = openidClient;
|
||||
|
||||
var _openidClient = require("openid-client");
|
||||
|
||||
+var HttpsProxyAgent = require("https-proxy-agent");
|
||||
+
|
||||
async function openidClient(options) {
|
||||
const provider = options.provider;
|
||||
- if (provider.httpOptions) _openidClient.custom.setHttpOptionsDefaults(provider.httpOptions);
|
||||
- let issuer;
|
||||
+ let httpOptions = {};
|
||||
+ if (provider.httpOptions) httpOptions = { ...provider.httpOptions };
|
||||
+ if (process.env.http_proxy) {
|
||||
+ let agent = new HttpsProxyAgent(process.env.http_proxy);
|
||||
+ httpOptions.agent = agent;
|
||||
+ }
|
||||
+ _openidClient.custom.setHttpOptionsDefaults(httpOptions);
|
||||
|
||||
+ let issuer;
|
||||
if (provider.wellKnown) {
|
||||
issuer = await _openidClient.Issuer.discover(provider.wellKnown);
|
||||
} else {
|
||||
```
|
||||
|
||||
> For more details, see [this issue](https://github.com/nextauthjs/next-auth/issues/2509#issuecomment-1035410802)
|
||||
|
||||
After applying this patch, we can add the the proxy connecting string via the `http_proxy` environment variable.
|
||||
|
||||
### Provider
|
||||
|
||||
If you're having trouble with your provider when using the `https-proxy-agent`, you may be using a provider which requires an extra request to, for example, fetch the users profile picture. In cases like these, you'll have to add the proxy workaround to your provider config as well. Below is an example of how to do that with the `AzureAD` provider.
|
||||
|
||||
```diff
|
||||
diff --git a/node_modules/next-auth/providers/azure-ad.js b/node_modules/next-auth/providers/azure-ad.js
|
||||
index 73d96d3..536cd81 100644
|
||||
--- a/node_modules/next-auth/providers/azure-ad.js
|
||||
+++ b/node_modules/next-auth/providers/azure-ad.js
|
||||
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
||||
});
|
||||
exports.default = AzureAD;
|
||||
|
||||
+const HttpsProxyAgent = require('https-proxy-agent');
|
||||
+
|
||||
function AzureAD(options) {
|
||||
var _options$tenantId, _options$profilePhoto;
|
||||
|
||||
@@ -22,11 +24,15 @@ function AzureAD(options) {
|
||||
},
|
||||
|
||||
async profile(profile, tokens) {
|
||||
- const profilePicture = await fetch(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, {
|
||||
+ let fetchOptions = {
|
||||
headers: {
|
||||
- Authorization: `Bearer ${tokens.access_token}`
|
||||
- }
|
||||
- });
|
||||
+ Authorization: `Bearer ${tokens.access_token}`,
|
||||
+ },
|
||||
+ };
|
||||
+ if (process.env.http_proxy) {
|
||||
+ fetchOptions.agent = new HttpsProxyAgent(process.env.http_proxy);
|
||||
+ }
|
||||
+ const profilePicture = await fetch(`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`, fetchOptions);
|
||||
|
||||
if (profilePicture.ok) {
|
||||
const pictureBuffer = await profilePicture.arrayBuffer();
|
||||
```
|
||||
@@ -7,6 +7,8 @@ Using a custom adapter you can connect to any database back-end or even several
|
||||
|
||||
## How to create an adapter
|
||||
|
||||
For more information about the data these methods need to manage see [models](/adapters/models).
|
||||
|
||||
_See the code below for practical example._
|
||||
|
||||
### Example code
|
||||
|
||||
@@ -61,7 +61,7 @@ async function refreshAccessToken(token) {
|
||||
return {
|
||||
...token,
|
||||
accessToken: refreshedTokens.access_token,
|
||||
accessTokenExpires: Date.now() + refreshedTokens.expires_in * 1000,
|
||||
accessTokenExpires: Date.now() + refreshedTokens.expires_at * 1000,
|
||||
refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fall back to old refresh token
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -88,7 +88,7 @@ export default NextAuth({
|
||||
if (account && user) {
|
||||
return {
|
||||
accessToken: account.access_token,
|
||||
accessTokenExpires: Date.now() + account.expires_in * 1000,
|
||||
accessTokenExpires: Date.now() + account.expires_at * 1000,
|
||||
refreshToken: account.refresh_token,
|
||||
user,
|
||||
}
|
||||
|
||||
60
docs/docs/tutorials/role-based-login-strategy.md
Normal file
60
docs/docs/tutorials/role-based-login-strategy.md
Normal file
@@ -0,0 +1,60 @@
|
||||
To add role based authentication to your application, you must do three things.
|
||||
|
||||
1. Update your database schema
|
||||
2. Add the `role` to the session object
|
||||
3. Check for `role` in your pages/components
|
||||
|
||||
First modify the `user` table and add a `role` column with the type of `String?`.
|
||||
|
||||
Below is an example Prisma schema file.
|
||||
|
||||
```javascript title="/prisma/schema.prisma"
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
name String?
|
||||
email String? @unique
|
||||
emailVerified DateTime?
|
||||
image String?
|
||||
role String? // New Column
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Next, implement a custom session callback in the `[...nextauth].js` file, as shown below.
|
||||
|
||||
```javascript title="/pages/api/auth/[...nextauth].js"
|
||||
callbacks: {
|
||||
async session({ session, token, user }) {
|
||||
session.user.role = user.role; // Add role value to user object so it is passed along with session
|
||||
return session;
|
||||
},
|
||||
```
|
||||
|
||||
Going forward, when using the `getSession` hook, check that `session.user.role` matches the required role. The example below assumes the role `'admin'` is required.
|
||||
|
||||
```javascript title="/pages/admin.js"
|
||||
import { getSession } from "next-auth/react"
|
||||
|
||||
export default function Page() {
|
||||
const session = await getSession({ req })
|
||||
|
||||
if (session && session.user.role === "admin") {
|
||||
return (
|
||||
<div>
|
||||
<h1>Admin</h1>
|
||||
<p>Welcome to the Admin Portal!</p>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<h1>You are not authorized to view this page!</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then it is up to you how you manage your roles, either through direct database access or building your own role update API.
|
||||
@@ -9,6 +9,13 @@ module.exports = {
|
||||
themeConfig: {
|
||||
prism: {
|
||||
theme: require("prism-react-renderer/themes/vsDark"),
|
||||
magicComments: [
|
||||
{
|
||||
className: "theme-code-block-highlighted-line",
|
||||
line: "highlight-next-line",
|
||||
block: { start: "highlight-start", end: "highlight-end" },
|
||||
},
|
||||
],
|
||||
},
|
||||
algolia: {
|
||||
appId: "OUEDA16KPG",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"url": "git://github.com/nextauthjs/docs.git"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run generate-providers && docusaurus start --port 8000",
|
||||
"start": "npm run generate-providers && docusaurus start --no-open --port 8000",
|
||||
"dev": "npm run start",
|
||||
"build": "npm run generate-providers && docusaurus build",
|
||||
"docusaurus": "docusaurus",
|
||||
@@ -18,26 +18,32 @@
|
||||
"lint:fix": "prettier --write .",
|
||||
"generate-providers": "node ./scripts/generate-providers.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codesandbox/sandpack-react": "^0.13.12",
|
||||
"@docusaurus/core": "^2.0.0-beta.17",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.17",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "^2.0.0-beta.17",
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^2.0.0-beta.20",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.20",
|
||||
"@docusaurus/remark-plugin-npm2yarn": "^2.0.0-beta.20",
|
||||
"@docusaurus/theme-common": "2.0.0-beta.20",
|
||||
"@mdx-js/react": "1.6.22",
|
||||
"classnames": "^2.3.1",
|
||||
"lodash.times": "^4.3.2",
|
||||
"mdx-mermaid": "^1.2.1",
|
||||
"mermaid": "^8.13.10",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"mdx-mermaid": "^1.2.2",
|
||||
"mermaid": "^9.0.1",
|
||||
"prism-react-renderer": "1.3.1",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-marquee-slider": "^1.1.5",
|
||||
"remark-github": "^10.1.0",
|
||||
"styled-components": "^5.3.3"
|
||||
"styled-components": "5.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.0"
|
||||
"@docusaurus/module-type-aliases": "2.0.0-beta.20",
|
||||
"prettier": "^2.6.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [">0.2%", "not dead", "not op_mini all"],
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
|
||||
@@ -40,10 +40,9 @@ module.exports = {
|
||||
{
|
||||
type: "category",
|
||||
label: "Providers",
|
||||
link: { type: "doc", id: "providers/overview" },
|
||||
collapsed: true,
|
||||
items: [
|
||||
"providers/overview",
|
||||
// TODO: Overview included twice due to autogeneration
|
||||
{
|
||||
type: "autogenerated",
|
||||
dirName: "providers",
|
||||
@@ -53,9 +52,9 @@ module.exports = {
|
||||
{
|
||||
type: "category",
|
||||
label: "Adapters",
|
||||
link: { type: "doc", id: "adapters/overview" },
|
||||
collapsed: true,
|
||||
items: [
|
||||
"adapters/overview",
|
||||
"adapters/models",
|
||||
"adapters/prisma",
|
||||
"adapters/fauna",
|
||||
@@ -74,5 +73,18 @@ module.exports = {
|
||||
"warnings",
|
||||
"errors",
|
||||
"deployment",
|
||||
{
|
||||
type: "category",
|
||||
label: "Guides",
|
||||
link: { type: "doc", id: "guides/guides" },
|
||||
collapsed: true,
|
||||
items: ["guides/basics", "guides/fullstack", "guides/testing"],
|
||||
},
|
||||
{
|
||||
type: "html",
|
||||
value:
|
||||
'<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CEAI6K3N&placement=next-authjsorg" id="_carbonads_js"></script>',
|
||||
defaultStyle: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from "react"
|
||||
import Marquee, { Motion, randomIntFromInterval } from "react-marquee-slider"
|
||||
import * as S from "./ProviderMarqueeStyle"
|
||||
import times from "lodash.times"
|
||||
import styles from "./ProviderMarqueeStyle.module.css"
|
||||
|
||||
const icons = [
|
||||
"/img/providers/apple-black.svg",
|
||||
@@ -20,7 +19,7 @@ const icons = [
|
||||
"/img/providers/twitter.svg",
|
||||
]
|
||||
|
||||
const ProviderMarquee = React.memo(({ size }) => {
|
||||
const ProviderMarquee = React.memo(() => {
|
||||
let scale = 0.4
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
@@ -39,8 +38,8 @@ const ProviderMarquee = React.memo(({ size }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<S.FullWidth>
|
||||
<S.Height height={500}>
|
||||
<div className={styles.fullWidth}>
|
||||
<div className={styles.height}>
|
||||
<Marquee
|
||||
key="1"
|
||||
velocity={5}
|
||||
@@ -48,24 +47,33 @@ const ProviderMarquee = React.memo(({ size }) => {
|
||||
minScale={0.5}
|
||||
resetAfterTries={200}
|
||||
>
|
||||
{times(icons.length, Number).map((id) => (
|
||||
{icons.map((icon) => (
|
||||
<Motion
|
||||
key={`marquee-example-company-${id}`}
|
||||
key={`marquee-example-company-${icon}`}
|
||||
initDeg={randomIntFromInterval(0, 360)}
|
||||
direction={Math.random() > 0.5 ? "clockwise" : "counterclockwise"}
|
||||
velocity={10}
|
||||
radius={scale * 70}
|
||||
>
|
||||
<S.Company scale={scale}>
|
||||
<S.Circle scale={scale}>
|
||||
<S.Logo src={icons[id]} alt="" />
|
||||
</S.Circle>
|
||||
</S.Company>
|
||||
<div
|
||||
className={styles.company}
|
||||
style={{ height: `${scale * 75}px`, width: `${scale * 75}px` }}
|
||||
>
|
||||
<div
|
||||
className={styles.circle}
|
||||
style={{
|
||||
height: `${scale * 150}px`,
|
||||
width: `${scale * 150}px`,
|
||||
}}
|
||||
>
|
||||
<img className={styles.logo} src={icon} alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</Motion>
|
||||
))}
|
||||
</Marquee>
|
||||
</S.Height>
|
||||
</S.FullWidth>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import styled from "styled-components"
|
||||
|
||||
export const Circle = styled.div`
|
||||
.circle {
|
||||
position: absolute;
|
||||
object-position: center center;
|
||||
will-change: transform, opacity;
|
||||
width: ${(props) => props.scale * 150}px;
|
||||
height: ${(props) => props.scale * 150}px;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
border-radius: 50%;
|
||||
@@ -13,33 +9,31 @@ export const Circle = styled.div`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 1rem;
|
||||
`
|
||||
}
|
||||
|
||||
export const Logo = styled.img`
|
||||
.logo {
|
||||
display: block;
|
||||
width: 65%;
|
||||
height: 65%;
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.1;
|
||||
`
|
||||
}
|
||||
|
||||
export const FullWidth = styled.div`
|
||||
.fullWidth {
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
right: 50%;
|
||||
margin-left: -50vw;
|
||||
margin-right: -50vw;
|
||||
`
|
||||
}
|
||||
|
||||
export const Height = styled.div`
|
||||
.height {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: ${(props) => (props.height ? props.height + "px" : "auto")};
|
||||
`
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
export const Company = styled.div`
|
||||
.company {
|
||||
position: relative;
|
||||
width: ${(props) => props.scale * 75}px;
|
||||
height: ${(props) => props.scale * 75}px;
|
||||
`
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import React from "react"
|
||||
import {
|
||||
SandpackProvider,
|
||||
SandpackLayout,
|
||||
SandpackCodeEditor,
|
||||
SandpackPreview,
|
||||
} from "@codesandbox/sandpack-react"
|
||||
|
||||
export const CustomSandpack = () => (
|
||||
<SandpackProvider template="react">
|
||||
<SandpackLayout>
|
||||
<SandpackCodeEditor />
|
||||
<SandpackPreview />
|
||||
</SandpackLayout>
|
||||
</SandpackProvider>
|
||||
)
|
||||
@@ -7,11 +7,6 @@
|
||||
|
||||
/* @TODO Move as many styles for the homepage as possible into styles.module.css */
|
||||
|
||||
/**
|
||||
* Sandpack integration
|
||||
*/
|
||||
@import "@codesandbox/sandpack-react/dist/index.css";
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-link: #289ef9;
|
||||
@@ -26,9 +21,10 @@
|
||||
--ifm-color-info: #1eb1fc;
|
||||
--ifm-color-success: #1eb1fc;
|
||||
--ifm-color-warning: #c94b4b;
|
||||
--ifm-font-family-base: -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";
|
||||
--ifm-font-family-base: ui-sans-serif, system-ui, -apple-system,
|
||||
BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans",
|
||||
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||||
"Noto Color Emoji";
|
||||
--ifm-background-color: #fff;
|
||||
--ifm-footer-background-color: #f9f9f9;
|
||||
--ifm-hero-background-color: #f5f5f5;
|
||||
@@ -61,12 +57,6 @@ html[data-theme="dark"] svg[id^="mermaid-svg"] text[id*="-attr"] {
|
||||
@import "navbar.css";
|
||||
@import "search.css";
|
||||
|
||||
@media screen and (max-width: 360px) {
|
||||
html {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -194,3 +184,92 @@ html[data-theme="dark"] hr {
|
||||
.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* CarbonAds */
|
||||
|
||||
#carbonads * {
|
||||
margin: initial;
|
||||
padding: initial;
|
||||
}
|
||||
|
||||
#carbonads {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
#carbonads {
|
||||
display: flex;
|
||||
max-width: 330px;
|
||||
background-color: hsl(0, 0%, 98%);
|
||||
box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, 0.1);
|
||||
z-index: 100;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
#carbonads a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#carbonads a:hover {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#carbonads span {
|
||||
position: relative;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#carbonads .carbon-wrap {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#carbonads .carbon-img {
|
||||
display: block;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#carbonads .carbon-img img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#carbonads .carbon-text {
|
||||
font-size: 11px;
|
||||
padding: 8px;
|
||||
margin-bottom: 16px;
|
||||
line-height: 1.5;
|
||||
text-align: left;
|
||||
}
|
||||
#carbonads .carbon-poweredby {
|
||||
display: block;
|
||||
padding: 6px 8px;
|
||||
background: #f1f1f2;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
font-weight: 600;
|
||||
font-size: 8px;
|
||||
line-height: 1;
|
||||
border-top-left-radius: 3px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] #carbonads .carbon-text {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] #carbonads > span {
|
||||
background: #1a1a1a;
|
||||
box-shadow: 0 0 1px hsl(0deg 0% 0% / 9%), 0 0 2px hsl(0deg 0% 0% / 9%),
|
||||
0 0 4px hsl(0deg 0% 0% / 9%), 0 0 8px hsl(0deg 0% 0% / 9%);
|
||||
}
|
||||
|
||||
html[data-theme="dark"] #carbonads .carbon-poweredby {
|
||||
color: #aaa;
|
||||
background: #1e2021;
|
||||
}
|
||||
|
||||
29
package.json
29
package.json
@@ -2,30 +2,24 @@
|
||||
"name": "root",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*",
|
||||
"apps/dev",
|
||||
"docs"
|
||||
]
|
||||
},
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
"scripts": {
|
||||
"build:app": "turbo run build --scope=next-auth-app --include-dependencies",
|
||||
"build": "turbo run build --scope=next-auth --scope=@next-auth/* --no-deps",
|
||||
"lint": "turbo run lint --scope=!next-auth-docs",
|
||||
"build:app": "turbo run build --filter=next-auth-app --include-dependencies",
|
||||
"build": "turbo run build --filter=next-auth --filter=@next-auth/* --no-deps",
|
||||
"lint": "turbo run lint --filter=!next-auth-docs",
|
||||
"lint:fix": "turbo run lint -- --fix",
|
||||
"test": "turbo run test --concurrency=1 --scope=!@next-auth/pouchdb-adapter --scope=!next-auth-*",
|
||||
"test": "turbo run test --concurrency=1 --filter=!@next-auth/pouchdb-adapter --filter=!next-auth-* --filter=[HEAD^1]",
|
||||
"setup": "turbo run setup",
|
||||
"dev": "yarn dev:app",
|
||||
"dev:app": "turbo run dev --parallel --no-deps --no-cache --scope=next-auth-app",
|
||||
"dev:docs": "turbo run dev --parallel --no-deps --no-cache --scope=next-auth-docs",
|
||||
"dev": "pnpm dev:app",
|
||||
"dev:app": "turbo run dev --parallel --no-deps --no-cache --filter=next-auth-app",
|
||||
"dev:docs": "turbo run dev --parallel --no-deps --no-cache --filter=next-auth-docs",
|
||||
"version:pr": "node ./config/version-pr",
|
||||
"release": "ts-node scripts/release"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@commitlint/parse": "16.0.0",
|
||||
"@types/node": "^17.0.25",
|
||||
"@types/semver": "7.3.9",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
@@ -43,11 +37,12 @@
|
||||
"semver": "7.3.5",
|
||||
"stream-to-array": "2.3.0",
|
||||
"ts-node": "10.5.0",
|
||||
"turbo": "^1.1.4",
|
||||
"turbo": "^1.2.5",
|
||||
"typescript": "^4.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.19.0 || ^14.15.0 || ^16.13.0"
|
||||
"node": "^12.19.0 || ^14.15.0 || ^16.13.0",
|
||||
"pnpm": ">=6.32.3"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
@@ -102,7 +97,7 @@
|
||||
"**/tests",
|
||||
"**/__tests__"
|
||||
],
|
||||
"packageManager": "yarn@1.22.17",
|
||||
"packageManager": "pnpm@6.32.8",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/dgraph-adapter",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"description": "Dgraph adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -31,13 +31,16 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/node-fetch": "^2.5.11",
|
||||
"jest": "^27.0.6",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*",
|
||||
"ts-jest": "^27.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -45,6 +48,6 @@
|
||||
"node-fetch": "^2.6.1"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DgraphAdapter, format } from "../src"
|
||||
import { client as dgraphClient } from "../src/client"
|
||||
import * as fragments from "../src/graphql/fragments"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
module.exports = {
|
||||
...require("adapter-test/jest/jest-preset"),
|
||||
...require("@next-auth/adapter-test/jest/jest-preset"),
|
||||
// // Indicates whether the coverage information should be collected while executing the test
|
||||
// collectCoverage: true,
|
||||
// // Indicates which provider should be used to instrument code for coverage
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@next-auth/dynamodb-adapter",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"description": "AWS DynamoDB adapter for next-auth.",
|
||||
"keywords": [
|
||||
"next-auth",
|
||||
@@ -21,7 +21,7 @@
|
||||
"scripts": {
|
||||
"test:default": "jest",
|
||||
"test:custom": "CUSTOM_MODEL=1 jest",
|
||||
"test": "yarn test:default && yarn test:custom",
|
||||
"test": "pnpm test:default && pnpm test:custom",
|
||||
"build": "tsc"
|
||||
},
|
||||
"files": [
|
||||
@@ -32,11 +32,15 @@
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/lib-dynamodb": "^3.36.1",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-dynamodb": "^3.36.1",
|
||||
"@aws-sdk/lib-dynamodb": "^3.36.1",
|
||||
"@shelf/jest-dynamodb": "^2.1.0"
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@shelf/jest-dynamodb": "^2.1.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DynamoDB } from "@aws-sdk/client-dynamodb"
|
||||
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"
|
||||
import { DynamoDBAdapter } from "../src"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { format } from "../src/"
|
||||
const config = {
|
||||
endpoint: "http://127.0.0.1:8000",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"name": "@next-auth/fauna-adapter",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"description": "Fauna Adapter for NextAuth",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
"bugs": {
|
||||
"url": "https://github.com/nextauthjs/next-auth/issues"
|
||||
},
|
||||
"files": ["dist", "README.md"],
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"author": "Bhanu Teja P",
|
||||
"contributors": [
|
||||
{
|
||||
@@ -21,7 +24,12 @@
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"license": "ISC",
|
||||
"keywords": ["next-auth", "next.js", "fauna", "faunadb"],
|
||||
"keywords": [
|
||||
"next-auth",
|
||||
"next.js",
|
||||
"fauna",
|
||||
"faunadb"
|
||||
],
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -33,13 +41,17 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"faunadb": "^4.3.0",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fauna-labs/fauna-schema-migrate": "^2.1.3",
|
||||
"faunadb": "^4.3.0"
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"faunadb": "^4.3.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { collections, FaunaAdapter, format, indexes, query } from "../src"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { Client as FaunaClient, Get, Match, Ref } from "faunadb"
|
||||
|
||||
const client = new FaunaClient({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = require("../adapter-test/jest.config")
|
||||
module.exports = require("@next-auth/adapter-test/jest.config")
|
||||
|
||||
@@ -28,15 +28,19 @@
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build:wip": "tsc",
|
||||
"test:wip": "FIRESTORE_EMULATOR_HOST=localhost:8080 firebase emulators:exec --only firestore --project next-auth-test jest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"firebase": "^8.6.2",
|
||||
"next-auth": "latest"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"firebase": "^8.6.2",
|
||||
"firebase-tools": "^9.11.0"
|
||||
"firebase-tools": "^9.11.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { FirebaseAdapter } from "../src"
|
||||
import { docSnapshotToObject, querySnapshotToObject } from "../src/utils"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/mikro-orm-adapter",
|
||||
"version": "1.0.1",
|
||||
"version": "2.0.1",
|
||||
"description": "MikroORM adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -33,13 +33,17 @@
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@mikro-orm/core": "^5.0.2",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mikro-orm/core": "^5.0.2",
|
||||
"@mikro-orm/sqlite": "^5.0.2"
|
||||
"@mikro-orm/sqlite": "^5.0.2",
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Options } from "@mikro-orm/core"
|
||||
import type { SqliteDriver } from "@mikro-orm/sqlite"
|
||||
|
||||
import { MikroORM, wrap } from "@mikro-orm/core"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { MikroOrmAdapter, defaultEntities } from "../src"
|
||||
import { User, VeryImportantEntity } from "./testEntities"
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
Property,
|
||||
Unique,
|
||||
} from "@mikro-orm/core"
|
||||
import { randomUUID } from "adapter-test"
|
||||
import { randomUUID } from "@next-auth/adapter-test"
|
||||
import type { defaultEntities } from "../src"
|
||||
import { Account, Session } from "../src/entities"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/mongodb-adapter",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.3",
|
||||
"description": "mongoDB adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -10,7 +10,13 @@
|
||||
"author": "Balázs Orbán <info@balazsorban.com>",
|
||||
"main": "dist/index.js",
|
||||
"license": "ISC",
|
||||
"keywords": ["next-auth", "next.js", "oauth", "mongodb", "adapter"],
|
||||
"keywords": [
|
||||
"next-auth",
|
||||
"next.js",
|
||||
"oauth",
|
||||
"mongodb",
|
||||
"adapter"
|
||||
],
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -20,15 +26,22 @@
|
||||
"test:watch": "./tests/test.sh -w",
|
||||
"build": "tsc"
|
||||
},
|
||||
"files": ["README.md", "dist"],
|
||||
"files": [
|
||||
"README.md",
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"mongodb": "^4.1.1",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mongodb": "^4.4.0"
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"jest": "^27.4.3",
|
||||
"mongodb": "^4.4.0",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
|
||||
import { MongoClient } from "mongodb"
|
||||
const name = "custom-test"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
|
||||
import { MongoClient } from "mongodb"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/neo4j-adapter",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"description": "neo4j adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -34,16 +34,20 @@
|
||||
],
|
||||
"peerDependencies": {
|
||||
"neo4j-driver": "^4.0.0",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"neo4j-driver": "^4.4.0"
|
||||
"jest": "^27.4.3",
|
||||
"neo4j-driver": "^4.4.0",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as neo4j from "neo4j-driver"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import statements from "./resources/statements"
|
||||
|
||||
import { Neo4jAdapter, format } from "../src"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -10,7 +10,12 @@
|
||||
"author": "jpbourgeon <jeanphilippe.bourgeon@gmail.com> (https://github.com/jpbourgeon)",
|
||||
"main": "dist/index.js",
|
||||
"license": "ISC",
|
||||
"keywords": ["next-auth", "next.js", "oauth", "pouchdb"],
|
||||
"keywords": [
|
||||
"next-auth",
|
||||
"next.js",
|
||||
"oauth",
|
||||
"pouchdb"
|
||||
],
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -20,9 +25,12 @@
|
||||
"tdd": "jest --watch",
|
||||
"test:wip": "jest"
|
||||
},
|
||||
"files": ["README.md", "dist"],
|
||||
"files": [
|
||||
"README.md",
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"next-auth": "^3.23.3",
|
||||
"next-auth": "workspace:*",
|
||||
"pouchdb": "^7.2.2",
|
||||
"pouchdb-find": "^7.2.2"
|
||||
},
|
||||
@@ -31,12 +39,16 @@
|
||||
"ulid": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@types/pouchdb": "^6.4.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*",
|
||||
"pouchdb": "^7.2.2",
|
||||
"pouchdb-adapter-memory": "^7.2.2",
|
||||
"pouchdb-find": "^7.2.2"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import find from "pouchdb-find"
|
||||
import { ulid } from "ulid"
|
||||
import Providers from "next-auth/providers"
|
||||
import { PouchDBAdapter } from "../src"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
|
||||
// pouchdb setup
|
||||
PouchDB.plugin(memoryAdapter).plugin(find)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/prisma-adapter",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.3",
|
||||
"description": "Prisma adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -10,7 +10,12 @@
|
||||
"author": "William Luke",
|
||||
"main": "dist/index.js",
|
||||
"license": "ISC",
|
||||
"keywords": ["next-auth", "next.js", "oauth", "prisma"],
|
||||
"keywords": [
|
||||
"next-auth",
|
||||
"next.js",
|
||||
"oauth",
|
||||
"prisma"
|
||||
],
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -19,23 +24,31 @@
|
||||
"clean": "rm -rf ./prisma/migrations && rm ./prisma/dev.db*",
|
||||
"init:default": "prisma migrate dev --name init --skip-seed",
|
||||
"init:custom": "prisma migrate dev --name init-custom --schema ./prisma/custom.prisma",
|
||||
"test:default": "yarn init:default && jest",
|
||||
"test:custom": "yarn init:custom && CUSTOM_MODEL=1 jest",
|
||||
"test:default": "pnpm init:default && jest",
|
||||
"test:custom": "pnpm init:custom && CUSTOM_MODEL=1 jest",
|
||||
"test:mongodb": "./tests/mongodb.test.sh",
|
||||
"test": "yarn test:default && yarn test:custom && yarn test:mongodb",
|
||||
"test": "pnpm test:default && pnpm test:custom && pnpm test:mongodb",
|
||||
"build": "prisma generate && tsc",
|
||||
"studio": "prisma studio"
|
||||
},
|
||||
"files": ["README.md", "dist"],
|
||||
"files": [
|
||||
"README.md",
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@prisma/client": ">=2.26.0 || >=3",
|
||||
"next-auth": "^4.0.1"
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@prisma/client": "^3.10.0",
|
||||
"jest": "^27.4.3",
|
||||
"mongodb": "^4.4.0",
|
||||
"next-auth": "workspace:*",
|
||||
"prisma": "^3.10.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { randomUUID, runBasicTests } from "adapter-test"
|
||||
import { randomUUID, runBasicTests } from "@next-auth/adapter-test"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { PrismaAdapter } from "../src"
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
@@ -16,7 +16,7 @@ done
|
||||
# Start db
|
||||
docker run -d --rm -p 27017:27017 --name ${CONTAINER_NAME} "prismagraphql/mongo-single-replica:4.4.3-bionic"
|
||||
|
||||
yarn prisma generate --schema ./prisma/mongodb.prisma
|
||||
pnpm prisma generate --schema ./prisma/mongodb.prisma
|
||||
|
||||
if $JEST_WATCH; then
|
||||
# Run jest in watch mode
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/sequelize-adapter",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.3",
|
||||
"description": "Sequelize adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -29,13 +29,17 @@
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"next-auth": "^4.0.1",
|
||||
"next-auth": "workspace:*",
|
||||
"sequelize": "^6.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*",
|
||||
"sequelize": "^6.6.5"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Account as ApadterAccount } from "next-auth"
|
||||
import type { Account as AdapterAccount } from "next-auth"
|
||||
import type {
|
||||
Adapter,
|
||||
AdapterUser,
|
||||
@@ -12,8 +12,8 @@ export { defaultModels as models }
|
||||
|
||||
// @see https://sequelize.org/master/manual/typescript.html
|
||||
interface AccountInstance
|
||||
extends Model<ApadterAccount, Partial<ApadterAccount>>,
|
||||
ApadterAccount {}
|
||||
extends Model<AdapterAccount, Partial<AdapterAccount>>,
|
||||
AdapterAccount {}
|
||||
interface UserInstance
|
||||
extends Model<AdapterUser, Partial<AdapterUser>>,
|
||||
AdapterUser {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Sequelize, DataTypes } from "sequelize"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import SequelizeAdapter, { models } from "../src"
|
||||
|
||||
const sequelize = new Sequelize({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "adapter-test",
|
||||
"name": "@next-auth/adapter-test",
|
||||
"version": "0.0.0",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
"contributors": [
|
||||
@@ -19,6 +19,7 @@
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.24.0",
|
||||
"@typescript-eslint/parser": "^4.24.0",
|
||||
"babel-jest": "^27.4.2",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-config-standard-with-typescript": "^20.0.0",
|
||||
@@ -26,7 +27,7 @@
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"jest": "^27.0.3",
|
||||
"next-auth": "latest",
|
||||
"next-auth": "workspace:*",
|
||||
"prettier": "^2.3.0",
|
||||
"ts-jest": "^27.0.3",
|
||||
"typescript": "^4.2.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/typeorm-legacy-adapter",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.3",
|
||||
"description": "TypeORM (legacy) adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -32,13 +32,17 @@
|
||||
"init:db": "tests/init.sh",
|
||||
"test:containers": "tests/test.sh",
|
||||
"test": "tests/test.sh",
|
||||
"mysql": "yarn init:db && tests/mysql/test.sh",
|
||||
"postgres": "yarn init:db && tests/postgresql/test.sh",
|
||||
"mysql": "pnpm init:db && tests/mysql/test.sh",
|
||||
"postgres": "pnpm init:db && tests/postgresql/test.sh",
|
||||
"sqlite": "tests/sqlite/test.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"jest": "^27.4.3",
|
||||
"mssql": "^7.2.1",
|
||||
"mysql": "^2.18.1",
|
||||
"next-auth": "workspace:*",
|
||||
"pg": "^8.7.1",
|
||||
"sqlite3": "^5.0.2",
|
||||
"typeorm": "^0.2.37",
|
||||
@@ -47,7 +51,7 @@
|
||||
"peerDependencies": {
|
||||
"mssql": "^6.2.1 || 7",
|
||||
"mysql": "^2.18.1",
|
||||
"next-auth": "^4.0.1",
|
||||
"next-auth": "workspace:*",
|
||||
"pg": "^8.2.1",
|
||||
"sqlite3": "^5.0.2",
|
||||
"typeorm": "^0.2.31"
|
||||
@@ -67,6 +71,6 @@
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ConnectionManager, ConnectionOptions } from "typeorm"
|
||||
import { TestOptions } from "adapter-test"
|
||||
import { TestOptions } from "@next-auth/adapter-test"
|
||||
import * as defaultEntities from "../src/entities"
|
||||
import { parseConnectionConfig } from "../src/utils"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
|
||||
@@ -29,9 +29,12 @@ npm install next-auth @next-auth/upstash-redis-adapter @upstash/redis
|
||||
```js
|
||||
import NextAuth from "next-auth"
|
||||
import { UpstashRedisAdapter } from "@next-auth/upstash-adapter"
|
||||
import upstashRedisClient from "@upstash/redis"
|
||||
import { Redis } from "@upstash/redis"
|
||||
|
||||
const redis = upstashRedisClient("UPSTASH_REDIS_REST_URL", "UPSTASH_REDIS_REST_TOKEN")
|
||||
const redis = new Redis({
|
||||
url:"UPSTASH_REDIS_REST_URL",
|
||||
token:"UPSTASH_REDIS_REST_TOKEN",
|
||||
})
|
||||
|
||||
// For more information on each option (and a full list of options) go to
|
||||
// https://next-auth.js.org/configuration/options
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/upstash-redis-adapter",
|
||||
"version": "1.1.0",
|
||||
"version": "3.0.0",
|
||||
"description": "Upstash adapter for next-auth. It uses Upstash's connectionless (HTTP based) Redis client.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/adapters",
|
||||
@@ -30,17 +30,21 @@
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@upstash/redis": "^0.2.1",
|
||||
"next-auth": "^4.0.1"
|
||||
"@upstash/redis": "^1.0.1",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@upstash/redis": "^0.2.1",
|
||||
"dotenv": "^10.0.0"
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@upstash/redis": "^1.0.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { Account as AdapterAccount } from "next-auth"
|
||||
import type { Adapter, AdapterUser, AdapterSession } from "next-auth/adapters"
|
||||
import type { Upstash } from "@upstash/redis/src/types"
|
||||
import type {
|
||||
Adapter,
|
||||
AdapterUser,
|
||||
AdapterSession,
|
||||
VerificationToken,
|
||||
} from "next-auth/adapters"
|
||||
import type { Redis } from "@upstash/redis"
|
||||
|
||||
import { v4 as uuid } from "uuid"
|
||||
|
||||
@@ -32,14 +37,15 @@ function isDate(value: any) {
|
||||
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
|
||||
}
|
||||
|
||||
export function reviveFromJson(json: string) {
|
||||
return JSON.parse(json, (_, value) =>
|
||||
isDate(value) ? new Date(value) : value
|
||||
)
|
||||
export function hydrateDates(json: object) {
|
||||
return Object.entries(json).reduce((acc, [key, val]) => {
|
||||
acc[key] = isDate(val) ? new Date(val as string) : val
|
||||
return acc
|
||||
}, {} as any)
|
||||
}
|
||||
|
||||
export function UpstashRedisAdapter(
|
||||
client: Upstash,
|
||||
client: Redis,
|
||||
options: UpstashRedisAdapterOptions = {}
|
||||
): Adapter {
|
||||
const mergedOptions = {
|
||||
@@ -70,12 +76,15 @@ export function UpstashRedisAdapter(
|
||||
}
|
||||
|
||||
const getAccount = async (id: string) => {
|
||||
const response = await client.get(accountKeyPrefix + id)
|
||||
if (!response.data) return null
|
||||
return reviveFromJson(response.data)
|
||||
const account = await client.get<AdapterAccount>(accountKeyPrefix + id)
|
||||
if (!account) return null
|
||||
return hydrateDates(account)
|
||||
}
|
||||
|
||||
const setSession = async (id: string, session: AdapterSession) => {
|
||||
const setSession = async (
|
||||
id: string,
|
||||
session: AdapterSession
|
||||
): Promise<AdapterSession> => {
|
||||
const sessionKey = sessionKeyPrefix + id
|
||||
await setObjectAsJson(sessionKey, session)
|
||||
await client.set(sessionByUserIdKeyPrefix + session.userId, sessionKey)
|
||||
@@ -83,21 +92,24 @@ export function UpstashRedisAdapter(
|
||||
}
|
||||
|
||||
const getSession = async (id: string) => {
|
||||
const response = await client.get(sessionKeyPrefix + id)
|
||||
if (!response.data) return null
|
||||
return reviveFromJson(response.data)
|
||||
const session = await client.get<AdapterSession>(sessionKeyPrefix + id)
|
||||
if (!session) return null
|
||||
return hydrateDates(session)
|
||||
}
|
||||
|
||||
const setUser = async (id: string, user: AdapterUser) => {
|
||||
const setUser = async (
|
||||
id: string,
|
||||
user: AdapterUser
|
||||
): Promise<AdapterUser> => {
|
||||
await setObjectAsJson(userKeyPrefix + id, user)
|
||||
await client.set(`${emailKeyPrefix}${user.email as string}`, id)
|
||||
return user
|
||||
}
|
||||
|
||||
const getUser = async (id: string) => {
|
||||
const response = await client.get(userKeyPrefix + id)
|
||||
if (!response.data) return null
|
||||
return reviveFromJson(response.data)
|
||||
const user = await client.get<AdapterUser>(userKeyPrefix + id)
|
||||
if (!user) return null
|
||||
return hydrateDates(user)
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -110,9 +122,11 @@ export function UpstashRedisAdapter(
|
||||
},
|
||||
getUser,
|
||||
async getUserByEmail(email) {
|
||||
const emailResponse = await client.get(emailKeyPrefix + email)
|
||||
if (!emailResponse.data) return null
|
||||
return await getUser(emailResponse.data)
|
||||
const userId = await client.get<string>(emailKeyPrefix + email)
|
||||
if (!userId) {
|
||||
return null
|
||||
}
|
||||
return await getUser(userId)
|
||||
},
|
||||
async getUserByAccount(account) {
|
||||
const dbAccount = await getAccount(
|
||||
@@ -124,7 +138,7 @@ export function UpstashRedisAdapter(
|
||||
async updateUser(updates) {
|
||||
const userId = updates.id as string
|
||||
const user = await getUser(userId)
|
||||
return await setUser(userId, { ...user, ...updates })
|
||||
return await setUser(userId, { ...(user as AdapterUser), ...updates })
|
||||
},
|
||||
async linkAccount(account) {
|
||||
const id = `${account.provider}:${account.providerAccountId}`
|
||||
@@ -158,10 +172,13 @@ export function UpstashRedisAdapter(
|
||||
},
|
||||
async useVerificationToken(verificationToken) {
|
||||
const tokenKey = verificationTokenKeyPrefix + verificationToken.identifier
|
||||
const tokenResponse = await client.get(tokenKey)
|
||||
if (!tokenResponse.data) return null
|
||||
|
||||
const token = await client.get<VerificationToken>(tokenKey)
|
||||
if (!token) return null
|
||||
|
||||
await client.del(tokenKey)
|
||||
return reviveFromJson(tokenResponse.data)
|
||||
return hydrateDates(token)
|
||||
// return reviveFromJson(token)
|
||||
},
|
||||
async unlinkAccount(account) {
|
||||
const id = `${account.provider}:${account.providerAccountId}`
|
||||
@@ -177,17 +194,15 @@ export function UpstashRedisAdapter(
|
||||
const user = await getUser(userId)
|
||||
if (!user) return
|
||||
const accountByUserKey = accountByUserIdPrefix + userId
|
||||
const accountRequest = await client.get(accountByUserKey)
|
||||
const accountKey = accountRequest.data
|
||||
const accountKey = await client.get<string>(accountByUserKey)
|
||||
const sessionByUserIdKey = sessionByUserIdKeyPrefix + userId
|
||||
const sessionRequest = await client.get(sessionByUserIdKey)
|
||||
const sessionKey = sessionRequest.data
|
||||
const sessionKey = await client.get<string>(sessionByUserIdKey)
|
||||
await client.del(
|
||||
userKeyPrefix + userId,
|
||||
`${emailKeyPrefix}${user.email as string}`,
|
||||
accountKey,
|
||||
accountKey as string,
|
||||
accountByUserKey,
|
||||
sessionKey,
|
||||
sessionKey as string,
|
||||
sessionByUserIdKey
|
||||
)
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import upstashRedisClient from "@upstash/redis"
|
||||
import { runBasicTests } from "adapter-test"
|
||||
import { reviveFromJson, UpstashRedisAdapter } from "../src"
|
||||
import { Redis } from "@upstash/redis"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { hydrateDates, UpstashRedisAdapter } from "../src"
|
||||
import "dotenv/config"
|
||||
|
||||
if (!process.env.UPSTASH_REDIS_URL || !process.env.UPSTASH_REDIS_KEY) {
|
||||
@@ -8,35 +8,39 @@ if (!process.env.UPSTASH_REDIS_URL || !process.env.UPSTASH_REDIS_KEY) {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
} else {
|
||||
const client = upstashRedisClient(
|
||||
process.env.UPSTASH_REDIS_URL,
|
||||
process.env.UPSTASH_REDIS_KEY
|
||||
)
|
||||
const client = new Redis({
|
||||
url: process.env.UPSTASH_REDIS_URL,
|
||||
token: process.env.UPSTASH_REDIS_KEY,
|
||||
})
|
||||
|
||||
runBasicTests({
|
||||
adapter: UpstashRedisAdapter(client, { baseKeyPrefix: "testApp:" }),
|
||||
db: {
|
||||
async user(id: string) {
|
||||
const { data } = await client.get(`testApp:user:${id}`)
|
||||
return reviveFromJson(data)
|
||||
const data = await client.get<object>(`testApp:user:${id}`)
|
||||
if (!data) return null
|
||||
return hydrateDates(data)
|
||||
},
|
||||
async account({ provider, providerAccountId }) {
|
||||
const { data } = await client.get(
|
||||
const data = await client.get<object>(
|
||||
`testApp:user:account:${provider}:${providerAccountId}`
|
||||
)
|
||||
return reviveFromJson(data)
|
||||
if (!data) return null
|
||||
return hydrateDates(data)
|
||||
},
|
||||
async session(sessionToken) {
|
||||
const { data } = await client.get(
|
||||
const data = await client.get<object>(
|
||||
`testApp:user:session:${sessionToken}`
|
||||
)
|
||||
return reviveFromJson(data)
|
||||
if (!data) return null
|
||||
return hydrateDates(data)
|
||||
},
|
||||
async verificationToken(where) {
|
||||
const { data } = await client.get(
|
||||
const data = await client.get<object>(
|
||||
`testApp:user:token:${where.identifier}`
|
||||
)
|
||||
return reviveFromJson(data)
|
||||
if (!data) return null
|
||||
return hydrateDates(data)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "tsconfig/base.json",
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -77,8 +77,7 @@ NextAuth.js can be used with or without a database.
|
||||
- Designed to be secure by default and encourage best practices for safeguarding user data
|
||||
- Uses Cross-Site Request Forgery (CSRF) Tokens on POST routes (sign in, sign out)
|
||||
- Default cookie policy aims for the most restrictive policy appropriate for each cookie
|
||||
- When JSON Web Tokens are enabled, they are signed by default (JWS) with HS512
|
||||
- Use JWT encryption (JWE) by setting the option `encryption: true` (defaults to A256GCM)
|
||||
- When JSON Web Tokens are enabled, they are encrypted by default (JWE) with A256GCM
|
||||
- Auto-generates symmetric signing and encryption keys for developer convenience
|
||||
- Features tab/window syncing and session polling to support short lived sessions
|
||||
- Attempts to implement the latest guidance published by [Open Web Application Security Project](https://owasp.org)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-auth",
|
||||
"version": "4.2.1",
|
||||
"version": "4.4.0",
|
||||
"description": "Authentication for Next.js",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
@@ -36,15 +36,15 @@
|
||||
"./providers/*": "./providers/*.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn clean && yarn run build:js && yarn run build:css",
|
||||
"build": "pnpm clean && pnpm build:js && pnpm build:css",
|
||||
"clean": "rm -rf client css lib providers core jwt react next index.d.ts index.js adapters.d.ts middleware.d.ts middleware.js",
|
||||
"build:js": "yarn run clean && yarn run generate-providers && tsc && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
|
||||
"build:js": "pnpm clean && pnpm generate-providers && tsc && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
|
||||
"build:css": "postcss --config config/postcss.config.js src/**/*.css --base src --dir . && node config/wrap-css.js",
|
||||
"watch:css": "postcss --config config/postcss.config.js --watch src/**/*.css --base src --dir .",
|
||||
"test": "jest --config ./config/jest.config.js",
|
||||
"prepublishOnly": "yarn run build",
|
||||
"prepublishOnly": "pnpm build",
|
||||
"generate-providers": "node ./config/generate-providers.js",
|
||||
"setup": "yarn run generate-providers",
|
||||
"setup": "pnpm generate-providers",
|
||||
"lint": "eslint src config"
|
||||
},
|
||||
"files": [
|
||||
@@ -76,8 +76,8 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"nodemailer": "^6.6.5",
|
||||
"react": "^17.0.2 || ^18.0.0-0",
|
||||
"react-dom": "^17.0.2 || ^18.0.0-0"
|
||||
"react": "^17.0.2 || ^18",
|
||||
"react-dom": "^17.0.2 || ^18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"nodemailer": {
|
||||
@@ -92,6 +92,7 @@
|
||||
"@babel/preset-env": "^7.16.4",
|
||||
"@babel/preset-react": "^7.16.0",
|
||||
"@babel/preset-typescript": "^7.16.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@testing-library/dom": "^8.11.3",
|
||||
"@testing-library/jest-dom": "^5.16.1",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
@@ -106,13 +107,12 @@
|
||||
"babel-jest": "^27.4.2",
|
||||
"babel-plugin-jsx-pragmatic": "^1.0.2",
|
||||
"babel-preset-preact": "^2.0.0",
|
||||
"cpx": "^1.5.0",
|
||||
"cssnano": "^5.0.12",
|
||||
"jest": "^27.4.3",
|
||||
"jest-watch-typeahead": "^1.0.0",
|
||||
"msw": "^0.36.3",
|
||||
"next": "12.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.12",
|
||||
"postcss-cli": "^9.0.2",
|
||||
"postcss-nested": "^5.0.6",
|
||||
"react": "^17.0.2",
|
||||
@@ -132,4 +132,4 @@
|
||||
"**/tests",
|
||||
"**/__tests__"
|
||||
]
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user