Compare commits

..

1 Commits

Author SHA1 Message Date
Balázs Orbán
430aa48557 chore(release): bump version 2022-04-14 09:07:07 +00:00
136 changed files with 20124 additions and 27888 deletions

View File

@@ -1,28 +1,48 @@
<!--
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!
-->
## ☕️ 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?
## Reasoning 💡
## 🧢 Checklist
<!-- 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`. -->
- [ ] Documentation
- [ ] Tests
- [ ] Ready to be merged
## 🎫 Affected issues
<!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
## Affected issues 🎟
<!--
Please [scout and link issues](https://github.com/nextauthjs/next-auth/issues) that might be solved by this PR.
Fixes: INSERT_ISSUE_LINK_HERE
If you write `"Fixes"` or `"Closes"` before the issue link like so:
## 📌 Resources
```
Fixes #359
```
- [Contributing guidelines](./CONTRIBUTING.md)
- [Code of conduct](./CODE_OF_CONDUCT.md)
- [Contributing to Open Source](https://kcd.im/pull-request)
the connected issue will be automatically closed once the PR is merged and hence help with maintenance of the library 😊
-->

View File

@@ -16,23 +16,26 @@ 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@v3
uses: actions/setup-node@v2
with:
node-version: 16
cache: "pnpm"
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') }}-
- name: Install dependencies
run: pnpm install
run: yarn --prefer-offline --frozen-lockfile
- name: Build
run: pnpm build
run: yarn build
- name: Run tests
run: pnpm test
run: yarn test
env:
UPSTASH_REDIS_URL: ${{ secrets.UPSTASH_REDIS_URL }}
UPSTASH_REDIS_KEY: ${{ secrets.UPSTASH_REDIS_KEY }}
@@ -52,22 +55,27 @@ 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@v3
uses: actions/setup-node@v2
with:
node-version: 16
cache: "pnpm"
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') }}-
- name: Install dependencies
run: pnpm install
run: yarn --prefer-offline --frozen-lockfile
- 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"
pnpm release
yarn release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN_PKG }}
@@ -81,17 +89,22 @@ 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@v3
uses: actions/setup-node@v2
with:
node-version: 16
cache: "pnpm"
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') }}-
- name: Install dependencies
run: pnpm install
run: yarn --prefer-offline --frozen-lockfile
- name: Determine version
uses: ./.github/version-pr
id: determine-version
@@ -101,7 +114,7 @@ jobs:
run: |
cd packages/next-auth
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
pnpm publish --no-git-checks --access public --tag experimental
npm publish --access public --tag experimental
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Comment version on PR

1
.gitignore vendored
View File

@@ -12,7 +12,6 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log
.pnpm-debug.log
# Dependencies

View File

@@ -6,20 +6,19 @@
"scripts": {
"clean": "rm -rf .next",
"copy:css": "cpx \"../../packages/next-auth/css/**/*\" src/css --watch",
"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",
"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",
"start": "next start",
"email": "fake-smtp-server",
"start:email": "pnpm email"
"email": "npx fake-smtp-server",
"start:email": "npm run 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",
@@ -30,7 +29,6 @@
"devDependencies": {
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"concurrently": "^7.1.0",
"prisma": "^3.10.0"
}
}
}

View File

@@ -30,7 +30,7 @@
"type": "module",
"dependencies": {
"cookie": "0.4.1",
"next-auth": "^4.3.3"
"next-auth": "^4.2.1"
},
"prettier": {
"semi": false,

View File

@@ -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.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==
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==
dependencies:
"@babel/runtime" "^7.16.3"
"@panva/hkdf" "^1.0.1"

View File

@@ -89,7 +89,7 @@ The default redirect callback looks like this:
callbacks: {
async redirect({ url, baseUrl }) {
// Allows relative callback URLs
if (url.startsWith("/")) return `${baseUrl}${url}`
if (url.startsWith("/")) return new URL(url, baseUrl).toString()
// Allows callback URLs on the same origin
else if (new URL(url).origin === baseUrl) return url
return baseUrl

View File

@@ -16,53 +16,16 @@ 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

View File

@@ -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 variable must be set.
If you are using [Middleware](/configuration/nextjs#prerequisites) this environment variables must be set.
### NEXTAUTH_URL_INTERNAL
@@ -226,10 +226,6 @@ 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.
---
@@ -289,6 +285,7 @@ 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 */ }
}
```
@@ -485,8 +482,6 @@ 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: {

View File

@@ -21,10 +21,6 @@ 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.
@@ -55,7 +51,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/signin?error=Default`
Example: `/auth/error?error=Default`
## Theming
@@ -94,15 +90,23 @@ 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 },
}
}
```
There is another, more fully styled example signin page available [here](https://github.com/ndom91/next-auth-example-sign-in-page).
/*
// If older than Next.js 9.3
SignIn.getInitialProps = async () => {
return {
providers: await getProviders()
}
}
*/
```
### Email Sign in
@@ -124,12 +128,22 @@ 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:
@@ -162,6 +176,7 @@ export default function SignIn({ csrfToken }) {
)
}
// This is the recommended way for Next.js 9.3 or newer
export async function getServerSideProps(context) {
return {
props: {
@@ -169,6 +184,15 @@ 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:

View File

@@ -85,8 +85,6 @@ 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` 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.
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.
After this, just make sure you either have your OAuth provider setup correctly with `clientId` / `clientSecret`'s and callback URLs.

View File

@@ -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](/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](https://next-auth.js.org/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,17 +111,9 @@ 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).
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 `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 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.
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.
---
@@ -129,7 +121,7 @@ The `callbackUrl` provided was either invalid or not defined. See [specifying a
#### JWT_SESSION_ERROR
JWKKeySupport: the key does not support HS512 verify algorithm
https://next-auth.js.org/errors#jwt_session_error 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
@@ -165,7 +157,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](/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](https://next-auth.js.org/configuration/options#secret)
#### oauth_callback_error expected 200 OK with body but no body was returned

View File

@@ -134,7 +134,7 @@ function Auth({ children }) {
}
```
It can be easily extended/modified to support something like an options object for role based authentication on pages. An example:
It can be easily be extended/modified to support something like an options object for role based authentication on pages. An example:
```jsx title="pages/admin.jsx"
AdminDashboard.auth = {

View File

@@ -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" showLineNumbers
```javascript title="pages/api/auth/[...nextauth].js"
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"
@@ -42,7 +42,8 @@ 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:
```jsx title="pages/_app.jsx" showLineNumbers
```javascript
// pages/_app.js
import { SessionProvider } from "next-auth/react"
export default function App({
@@ -67,7 +68,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.
```jsx title="components/login-btn.jsx" showLineNumbers
```javascript
import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
@@ -95,7 +96,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 title="pages/api/restricted.js" showLineNumbers
```javascript
import { getSession } from "next-auth/react"
export default async (req, res) => {
@@ -122,20 +123,18 @@ 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 title="pages/api/auth/[...nextauth].js"
```javascript
...
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
}
@@ -145,11 +144,10 @@ callbacks: {
Now whenever you call `getSession` or `useSession`, the data object which is returned will include the `accessToken` value.
```jsx title="components/accessToken.jsx" showLineNumbers
```js
import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
// highlight-next-line
const { data } = useSession()
const { accessToken } = data
@@ -160,7 +158,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.

View File

@@ -28,7 +28,3 @@ title: Fullstack
### [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.

View File

@@ -1,17 +0,0 @@
---
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.

View File

@@ -31,5 +31,5 @@ providers: [
```
:::note
`issuer` should include the slug without a trailing slash  e.g., `https://my-authentik-domain.com/application/o/My_Slug`
`issuer` should include the slug  e.g. `https://my-authentik-domain.com/application/o/My_Slug/`
:::

View File

@@ -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 - Username / Password
## Example
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,19 +73,9 @@ 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
### Example code
You can specify more than one credentials provider by specifying a unique `id` for each one.

View File

@@ -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.ts)
- [Discord Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/discord.js)
You can override any of the options to suit your own use case.

View File

@@ -37,5 +37,5 @@ providers: [
```
:::note
`issuer` should include the realm  e.g. `https://my-keycloak-domain.com/realms/My_Realm`
`issuer` should include the realm  e.g. `https://my-keycloak-domain.com/auth/realms/My_Realm`
:::

View File

@@ -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.
:::
![twitter](https://user-images.githubusercontent.com/55143799/168702338-a95912a7-b689-4680-aa2c-6306fe3c2ec7.jpeg)
![twitter](https://user-images.githubusercontent.com/7902980/83944068-1640ca80-a801-11ea-959c-0e744e2144f7.PNG)
## OAuth 2.0
## OAuth 2
Twitter supports OAuth 2, which is currently opt-in. To enable it, simply add `version: "2.0"` to your Provider configuration:
@@ -56,7 +56,3 @@ 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.
:::

View File

@@ -1,43 +0,0 @@
---
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.
:::

View File

@@ -94,10 +94,20 @@ 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()
}
}
*/
```

3
docs/docs/sandpack.md Normal file
View File

@@ -0,0 +1,3 @@
import { CustomSandpack } from "../src/components/Sandpack"
<CustomSandpack />

View File

@@ -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://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>
#### [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>
- 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.
@@ -44,20 +44,19 @@ title: Tutorials and Explainers
#### [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:
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
- **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.
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.

View File

@@ -61,7 +61,7 @@ async function refreshAccessToken(token) {
return {
...token,
accessToken: refreshedTokens.access_token,
accessTokenExpires: Date.now() + refreshedTokens.expires_at * 1000,
accessTokenExpires: Date.now() + refreshedTokens.expires_in * 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_at * 1000,
accessTokenExpires: Date.now() + account.expires_in * 1000,
refreshToken: account.refresh_token,
user,
}

View File

@@ -1,60 +0,0 @@
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.

View File

@@ -9,13 +9,6 @@ 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",

View File

@@ -6,7 +6,7 @@
"url": "git://github.com/nextauthjs/docs.git"
},
"scripts": {
"start": "npm run generate-providers && docusaurus start --no-open --port 8000",
"start": "npm run generate-providers && docusaurus start --port 8000",
"dev": "npm run start",
"build": "npm run generate-providers && docusaurus build",
"docusaurus": "docusaurus",
@@ -19,31 +19,25 @@
"generate-providers": "node ./scripts/generate-providers.js"
},
"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",
"@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",
"classnames": "^2.3.1",
"mdx-mermaid": "^1.2.2",
"mermaid": "^9.0.1",
"prism-react-renderer": "1.3.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"lodash.times": "^4.3.2",
"mdx-mermaid": "^1.2.1",
"mermaid": "^8.13.10",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-marquee-slider": "^1.1.5",
"remark-github": "^10.1.0",
"styled-components": "5.3.3"
"styled-components": "^5.3.3"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-beta.20",
"prettier": "^2.6.2"
"prettier": "^2.5.0"
},
"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",

View File

@@ -40,9 +40,10 @@ 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",
@@ -52,9 +53,9 @@ module.exports = {
{
type: "category",
label: "Adapters",
link: { type: "doc", id: "adapters/overview" },
collapsed: true,
items: [
"adapters/overview",
"adapters/models",
"adapters/prisma",
"adapters/fauna",
@@ -76,15 +77,17 @@ module.exports = {
{
type: "category",
label: "Guides",
link: { type: "doc", id: "guides/guides" },
collapsed: true,
items: ["guides/basics", "guides/fullstack", "guides/testing"],
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,
value: '<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CEAI6K3N&placement=next-authjsorg" id="_carbonads_js"></script>',
defaultStyle: true
},
],
}

View File

@@ -1,6 +1,7 @@
import React from "react"
import Marquee, { Motion, randomIntFromInterval } from "react-marquee-slider"
import styles from "./ProviderMarqueeStyle.module.css"
import * as S from "./ProviderMarqueeStyle"
import times from "lodash.times"
const icons = [
"/img/providers/apple-black.svg",
@@ -19,7 +20,7 @@ const icons = [
"/img/providers/twitter.svg",
]
const ProviderMarquee = React.memo(() => {
const ProviderMarquee = React.memo(({ size }) => {
let scale = 0.4
if (typeof window !== "undefined") {
@@ -38,8 +39,8 @@ const ProviderMarquee = React.memo(() => {
}
return (
<div className={styles.fullWidth}>
<div className={styles.height}>
<S.FullWidth>
<S.Height height={500}>
<Marquee
key="1"
velocity={5}
@@ -47,33 +48,24 @@ const ProviderMarquee = React.memo(() => {
minScale={0.5}
resetAfterTries={200}
>
{icons.map((icon) => (
{times(icons.length, Number).map((id) => (
<Motion
key={`marquee-example-company-${icon}`}
key={`marquee-example-company-${id}`}
initDeg={randomIntFromInterval(0, 360)}
direction={Math.random() > 0.5 ? "clockwise" : "counterclockwise"}
velocity={10}
radius={scale * 70}
>
<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>
<S.Company scale={scale}>
<S.Circle scale={scale}>
<S.Logo src={icons[id]} alt="" />
</S.Circle>
</S.Company>
</Motion>
))}
</Marquee>
</div>
</div>
</S.Height>
</S.FullWidth>
)
})

View File

@@ -1,7 +1,11 @@
.circle {
import styled from "styled-components"
export const Circle = styled.div`
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%;
@@ -9,31 +13,33 @@
justify-content: center;
align-items: center;
margin-top: 1rem;
}
`
.logo {
export const Logo = styled.img`
display: block;
width: 65%;
height: 65%;
filter: grayscale(100%);
opacity: 0.1;
}
`
.fullWidth {
export const FullWidth = styled.div`
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
`
.height {
export const Height = styled.div`
position: relative;
width: 100%;
height: 500px;
}
height: ${(props) => (props.height ? props.height + "px" : "auto")};
`
.company {
export const Company = styled.div`
position: relative;
}
width: ${(props) => props.scale * 75}px;
height: ${(props) => props.scale * 75}px;
`

View File

@@ -0,0 +1,16 @@
import React from "react"
import {
SandpackProvider,
SandpackLayout,
SandpackCodeEditor,
SandpackPreview,
} from "@codesandbox/sandpack-react"
export const CustomSandpack = () => (
<SandpackProvider template="react">
<SandpackLayout>
<SandpackCodeEditor />
<SandpackPreview />
</SandpackLayout>
</SandpackProvider>
)

View File

@@ -7,6 +7,11 @@
/* @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;
@@ -57,6 +62,12 @@ 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;
}

View File

@@ -2,24 +2,30 @@
"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 --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",
"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",
"lint:fix": "turbo run lint -- --fix",
"test": "turbo run test --concurrency=1 --filter=!@next-auth/pouchdb-adapter --filter=!next-auth-* --filter=[HEAD^1]",
"test": "turbo run test --concurrency=1 --scope=!@next-auth/pouchdb-adapter --scope=!next-auth-*",
"setup": "turbo run setup",
"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",
"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",
"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",
@@ -37,12 +43,11 @@
"semver": "7.3.5",
"stream-to-array": "2.3.0",
"ts-node": "10.5.0",
"turbo": "^1.2.5",
"turbo": "^1.1.6",
"typescript": "^4.5.2"
},
"engines": {
"node": "^12.19.0 || ^14.15.0 || ^16.13.0",
"pnpm": ">=6.32.3"
"node": "^12.19.0 || ^14.15.0 || ^16.13.0"
},
"prettier": {
"semi": false,
@@ -97,7 +102,7 @@
"**/tests",
"**/__tests__"
],
"packageManager": "pnpm@6.32.8",
"packageManager": "yarn@1.22.17",
"funding": [
{
"type": "github",

View File

@@ -31,16 +31,14 @@
},
"peerDependencies": {
"jsonwebtoken": "^8.5.1",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"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.4.3",
"next-auth": "workspace:*",
"jest": "^27.0.6",
"next-auth": "^4.0.1",
"ts-jest": "^27.0.3"
},
"dependencies": {
@@ -48,6 +46,6 @@
"node-fetch": "^2.6.1"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -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 "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import fs from "fs"
import path from "path"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -3,7 +3,7 @@
* https://jestjs.io/docs/en/configuration.html
*/
module.exports = {
...require("@next-auth/adapter-test/jest/jest-preset"),
...require("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

View File

@@ -21,7 +21,7 @@
"scripts": {
"test:default": "jest",
"test:custom": "CUSTOM_MODEL=1 jest",
"test": "pnpm test:default && pnpm test:custom",
"test": "yarn test:default && yarn test:custom",
"build": "tsc"
},
"files": [
@@ -32,15 +32,12 @@
"license": "ISC",
"peerDependencies": {
"@aws-sdk/lib-dynamodb": "^3.36.1",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"devDependencies": {
"@aws-sdk/client-dynamodb": "^3.36.1",
"@aws-sdk/lib-dynamodb": "^3.36.1",
"@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:*"
"next-auth": "^4.0.1"
}
}

View File

@@ -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 "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { format } from "../src/"
const config = {
endpoint: "http://127.0.0.1:8000",

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -7,10 +7,7 @@
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},
"files": [
"dist",
"README.md"
],
"files": ["dist", "README.md"],
"author": "Bhanu Teja P",
"contributors": [
{
@@ -24,12 +21,7 @@
],
"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"
@@ -41,17 +33,14 @@
},
"peerDependencies": {
"faunadb": "^4.3.0",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"devDependencies": {
"@fauna-labs/fauna-schema-migrate": "^2.1.3",
"@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:*"
"next-auth": "^4.0.1"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -1,5 +1,5 @@
import { collections, FaunaAdapter, format, indexes, query } from "../src"
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { Client as FaunaClient, Get, Match, Ref } from "faunadb"
const client = new FaunaClient({

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -1 +1 @@
module.exports = require("@next-auth/adapter-test/jest.config")
module.exports = require("../adapter-test/jest.config")

View File

@@ -33,14 +33,11 @@
},
"peerDependencies": {
"firebase": "^8.6.2",
"next-auth": "workspace:*"
"next-auth": "latest"
},
"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",
"jest": "^27.4.3",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
}
}

View File

@@ -1,4 +1,4 @@
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { FirebaseAdapter } from "../src"
import { docSnapshotToObject, querySnapshotToObject } from "../src/utils"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/base.json",
"extends": "tsconfig/base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -33,17 +33,14 @@
],
"peerDependencies": {
"@mikro-orm/core": "^5.0.2",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"devDependencies": {
"@mikro-orm/core": "^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:*"
"next-auth": "^4.0.1"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -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 "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { MikroOrmAdapter, defaultEntities } from "../src"
import { User, VeryImportantEntity } from "./testEntities"

View File

@@ -7,7 +7,7 @@ import {
Property,
Unique,
} from "@mikro-orm/core"
import { randomUUID } from "@next-auth/adapter-test"
import { randomUUID } from "adapter-test"
import type { defaultEntities } from "../src"
import { Account, Session } from "../src/entities"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,

View File

@@ -10,13 +10,7 @@
"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"
@@ -26,22 +20,16 @@
"test:watch": "./tests/test.sh -w",
"build": "tsc"
},
"files": [
"README.md",
"dist"
],
"files": ["README.md", "dist"],
"peerDependencies": {
"mongodb": "^4.1.1",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"devDependencies": {
"@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:*"
"next-auth": "^4.0.1"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -1,4 +1,4 @@
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
import { MongoClient } from "mongodb"
const name = "custom-test"

View File

@@ -1,4 +1,4 @@
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
import { MongoClient } from "mongodb"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -34,20 +34,17 @@
],
"peerDependencies": {
"neo4j-driver": "^4.0.0",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"devDependencies": {
"@next-auth/adapter-test": "workspace:^0.0.0",
"@next-auth/tsconfig": "workspace:^0.0.0",
"@types/uuid": "^8.3.3",
"jest": "^27.4.3",
"neo4j-driver": "^4.4.0",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"dependencies": {
"uuid": "^8.3.2"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -1,5 +1,5 @@
import * as neo4j from "neo4j-driver"
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import statements from "./resources/statements"
import { Neo4jAdapter, format } from "../src"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -10,12 +10,7 @@
"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"
@@ -25,12 +20,9 @@
"tdd": "jest --watch",
"test:wip": "jest"
},
"files": [
"README.md",
"dist"
],
"files": ["README.md", "dist"],
"peerDependencies": {
"next-auth": "workspace:*",
"next-auth": "^3.23.3",
"pouchdb": "^7.2.2",
"pouchdb-find": "^7.2.2"
},
@@ -39,16 +31,13 @@
"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:*",
"next-auth": "^4.0.1",
"pouchdb": "^7.2.2",
"pouchdb-adapter-memory": "^7.2.2",
"pouchdb-find": "^7.2.2"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -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 "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
// pouchdb setup
PouchDB.plugin(memoryAdapter).plugin(find)

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/base.json",
"extends": "tsconfig/base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",

View File

@@ -10,12 +10,7 @@
"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"
@@ -24,31 +19,24 @@
"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": "pnpm init:default && jest",
"test:custom": "pnpm init:custom && CUSTOM_MODEL=1 jest",
"test:default": "yarn init:default && jest",
"test:custom": "yarn init:custom && CUSTOM_MODEL=1 jest",
"test:mongodb": "./tests/mongodb.test.sh",
"test": "pnpm test:default && pnpm test:custom && pnpm test:mongodb",
"test": "yarn test:default && yarn test:custom && yarn 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": "workspace:*"
"next-auth": "^4.0.1"
},
"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:*",
"next-auth": "^4.0.1",
"prisma": "^3.10.0"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -1,4 +1,4 @@
import { randomUUID, runBasicTests } from "@next-auth/adapter-test"
import { randomUUID, runBasicTests } from "adapter-test"
import { PrismaClient } from "@prisma/client"
import { PrismaAdapter } from "../src"
const prisma = new PrismaClient()

View File

@@ -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"
pnpm prisma generate --schema ./prisma/mongodb.prisma
yarn prisma generate --schema ./prisma/mongodb.prisma
if $JEST_WATCH; then
# Run jest in watch mode

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -1,6 +1,6 @@
{
"name": "@next-auth/sequelize-adapter",
"version": "1.0.3",
"version": "1.0.2",
"description": "Sequelize adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/adapters",
@@ -29,17 +29,14 @@
"dist"
],
"peerDependencies": {
"next-auth": "workspace:*",
"next-auth": "^4.0.1",
"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:*",
"next-auth": "^4.0.1",
"sequelize": "^6.6.5"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}
}

View File

@@ -1,4 +1,4 @@
import type { Account as AdapterAccount } from "next-auth"
import type { Account as ApadterAccount } 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<AdapterAccount, Partial<AdapterAccount>>,
AdapterAccount {}
extends Model<ApadterAccount, Partial<ApadterAccount>>,
ApadterAccount {}
interface UserInstance
extends Model<AdapterUser, Partial<AdapterUser>>,
AdapterUser {}

View File

@@ -1,5 +1,5 @@
import { Sequelize, DataTypes } from "sequelize"
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import SequelizeAdapter, { models } from "../src"
const sequelize = new Sequelize({

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -1,5 +1,5 @@
{
"name": "@next-auth/adapter-test",
"name": "adapter-test",
"version": "0.0.0",
"repository": "https://github.com/nextauthjs/next-auth.git",
"contributors": [
@@ -19,7 +19,6 @@
"@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",
@@ -27,7 +26,7 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"jest": "^27.0.3",
"next-auth": "workspace:*",
"next-auth": "latest",
"prettier": "^2.3.0",
"ts-jest": "^27.0.3",
"typescript": "^4.2.4"

View File

@@ -32,17 +32,14 @@
"init:db": "tests/init.sh",
"test:containers": "tests/test.sh",
"test": "tests/test.sh",
"mysql": "pnpm init:db && tests/mysql/test.sh",
"postgres": "pnpm init:db && tests/postgresql/test.sh",
"mysql": "yarn init:db && tests/mysql/test.sh",
"postgres": "yarn 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",
"next-auth": "^4.0.1",
"mssql": "^7.2.1",
"mysql": "^2.18.1",
"next-auth": "workspace:*",
"pg": "^8.7.1",
"sqlite3": "^5.0.2",
"typeorm": "^0.2.37",
@@ -51,7 +48,7 @@
"peerDependencies": {
"mssql": "^6.2.1 || 7",
"mysql": "^2.18.1",
"next-auth": "workspace:*",
"next-auth": "^4.0.1",
"pg": "^8.2.1",
"sqlite3": "^5.0.2",
"typeorm": "^0.2.31"
@@ -71,6 +68,6 @@
}
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}

View File

@@ -1,5 +1,5 @@
import { ConnectionManager, ConnectionOptions } from "typeorm"
import { TestOptions } from "@next-auth/adapter-test"
import { TestOptions } from "adapter-test"
import * as defaultEntities from "../src/entities"
import { parseConnectionConfig } from "../src/utils"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",

View File

@@ -1,6 +1,6 @@
{
"name": "@next-auth/upstash-redis-adapter",
"version": "3.0.0",
"version": "2.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",
@@ -31,20 +31,17 @@
],
"peerDependencies": {
"@upstash/redis": "^1.0.1",
"next-auth": "workspace:*"
"next-auth": "^4.0.1"
},
"devDependencies": {
"@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:*"
"next-auth": "^4.0.1"
},
"dependencies": {
"uuid": "^8.3.2"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"preset": "adapter-test/jest"
}
}
}

View File

@@ -1,5 +1,5 @@
import { Redis } from "@upstash/redis"
import { runBasicTests } from "@next-auth/adapter-test"
import { runBasicTests } from "adapter-test"
import { hydrateDates, UpstashRedisAdapter } from "../src"
import "dotenv/config"

View File

@@ -1,5 +1,5 @@
{
"extends": "@next-auth/tsconfig/adapters.json",
"extends": "tsconfig/adapters.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"

View File

@@ -1,6 +1,6 @@
{
"name": "next-auth",
"version": "4.4.0",
"version": "4.3.2",
"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": "pnpm clean && pnpm build:js && pnpm build:css",
"build": "yarn clean && yarn run build:js && yarn run 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": "pnpm clean && pnpm generate-providers && tsc && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
"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: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": "pnpm build",
"prepublishOnly": "yarn run build",
"generate-providers": "node ./config/generate-providers.js",
"setup": "pnpm generate-providers",
"setup": "yarn run generate-providers",
"lint": "eslint src config"
},
"files": [
@@ -76,8 +76,8 @@
},
"peerDependencies": {
"nodemailer": "^6.6.5",
"react": "^17.0.2 || ^18",
"react-dom": "^17.0.2 || ^18"
"react": "^17.0.2 || ^18.0.0-0",
"react-dom": "^17.0.2 || ^18.0.0-0"
},
"peerDependenciesMeta": {
"nodemailer": {
@@ -92,7 +92,6 @@
"@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",
@@ -107,12 +106,13 @@
"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",
"postcss": "^8.4.12",
"npm-run-all": "^4.1.5",
"postcss-cli": "^9.0.2",
"postcss-nested": "^5.0.6",
"react": "^17.0.2",

View File

@@ -45,7 +45,7 @@ test("returns the Cross Site Request Forgery Token (CSRF Token) required to make
test("when there's no CSRF token returned, it'll reflect that", async () => {
server.use(
rest.get("*/api/auth/csrf", (req, res, ctx) =>
rest.get("/api/auth/csrf", (req, res, ctx) =>
res(
ctx.status(200),
ctx.json({
@@ -67,7 +67,7 @@ test("when there's no CSRF token returned, it'll reflect that", async () => {
test("when the fetch fails it'll throw a client fetch error", async () => {
server.use(
rest.get("*/api/auth/csrf", (req, res, ctx) =>
rest.get("/api/auth/csrf", (req, res, ctx) =>
res(ctx.status(500), ctx.text("some error happened"))
)
)

View File

@@ -65,26 +65,28 @@ export const mockSignOutResponse = {
}
export const server = setupServer(
rest.post("*/api/auth/signout", (req, res, ctx) =>
rest.post("http://localhost/api/auth/signout", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockSignOutResponse))
),
rest.get("*/api/auth/session", (req, res, ctx) =>
rest.get("http://localhost/api/auth/session", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockSession))
),
rest.get("*/api/auth/csrf", (req, res, ctx) =>
rest.get("http://localhost/api/auth/csrf", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockCSRFToken))
),
rest.get("*/api/auth/providers", (req, res, ctx) =>
rest.get("http://localhost/api/auth/providers", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockProviders))
),
rest.post("*/api/auth/signin/github", (req, res, ctx) =>
rest.post("http://localhost/api/auth/signin/github", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockGithubResponse))
),
rest.post("*/api/auth/callback/credentials", (req, res, ctx) =>
rest.post("http://localhost/api/auth/callback/credentials", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockCredentialsResponse))
),
rest.post("*/api/auth/signin/email", (req, res, ctx) =>
rest.post("http://localhost/api/auth/signin/email", (req, res, ctx) =>
res(ctx.status(200), ctx.json(mockEmailResponse))
),
rest.post("*/api/auth/_log", (req, res, ctx) => res(ctx.status(200)))
rest.post("http://localhost/api/auth/_log", (req, res, ctx) =>
res(ctx.status(200))
)
)

View File

@@ -45,7 +45,7 @@ test("when called it'll return the currently configured providers for sign in",
test("when failing to fetch the providers, it'll log the error", async () => {
server.use(
rest.get("*/api/auth/providers", (req, res, ctx) =>
rest.get("/api/auth/providers", (req, res, ctx) =>
res(ctx.status(500), ctx.text("some error happened"))
)
)

View File

@@ -61,7 +61,7 @@ test("if it can fetch the session, it should store it in `localStorage`", async
test("if there's an error fetching the session, it should log it", async () => {
server.use(
rest.get("*/api/auth/session", (req, res, ctx) => {
rest.get("/api/auth/session", (req, res, ctx) => {
return res(ctx.status(500), ctx.body("Server error"))
})
)

View File

@@ -195,7 +195,7 @@ test("if callback URL contains a hash we force a window reload when re-directing
const mockUrlWithHash = "https://path/to/email/url#foo-bar-baz"
server.use(
rest.post("*/api/auth/signin/email", (req, res, ctx) => {
rest.post("http://localhost/api/auth/signin/email", (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
@@ -222,7 +222,7 @@ test("params are propagated to the signin URL when supplied", async () => {
const authParams = "foo=bar&bar=foo"
server.use(
rest.post("*/auth/signin/github", (req, res, ctx) => {
rest.post("http://localhost/api/auth/signin/github", (req, res, ctx) => {
matchedParams = req.url.search
return res(ctx.status(200), ctx.json(mockGithubResponse))
})
@@ -241,7 +241,7 @@ test("when it fails to fetch the providers, it redirected back to signin page",
const errorMsg = "Error when retrieving providers"
server.use(
rest.get("*/api/auth/providers", (req, res, ctx) =>
rest.get("http://localhost/api/auth/providers", (req, res, ctx) =>
res(ctx.status(500), ctx.json(errorMsg))
)
)

View File

@@ -37,7 +37,7 @@ const callbackUrl = "https://redirects/to"
test("by default it redirects to the current URL if the server did not provide one", async () => {
server.use(
rest.post("*/api/auth/signout", (req, res, ctx) =>
rest.post("http://localhost/api/auth/signout", (req, res, ctx) =>
res(ctx.status(200), ctx.json({ ...mockSignOutResponse, url: undefined }))
)
)
@@ -65,7 +65,7 @@ test("if url contains a hash during redirection a page reload happens", async ()
const mockUrlWithHash = "https://path/to/email/url#foo-bar-baz"
server.use(
rest.post("*/api/auth/signout", (req, res, ctx) => {
rest.post("http://localhost/api/auth/signout", (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({

View File

@@ -63,11 +63,6 @@ export class UnsupportedStrategy extends UnknownError {
code = "CALLBACK_CREDENTIALS_JWT_ERROR"
}
export class InvalidCallbackUrl extends UnknownError {
name = "InvalidCallbackUrl"
code = "INVALID_CALLBACK_URL_ERROR"
}
type Method = (...args: any[]) => Promise<any>
export function upperSnake(s: string) {

View File

@@ -108,8 +108,7 @@ export async function NextAuthHandler<
let signinUrl = `${pages.signIn}${
pages.signIn.includes("?") ? "&" : "?"
}callbackUrl=${encodeURIComponent(options.callbackUrl)}`
if (error)
signinUrl = `${signinUrl}&error=${encodeURIComponent(error)}`
if (error) signinUrl = `${signinUrl}&error=${encodeURIComponent(error)}`
return { redirect: signinUrl, cookies }
}

View File

@@ -4,10 +4,7 @@ import {
MissingAuthorize,
MissingSecret,
UnsupportedStrategy,
InvalidCallbackUrl,
} from "../errors"
import parseUrl from "../../lib/parse-url"
import { defaultCookies } from "./cookie"
import type { NextAuthHandlerParams } from ".."
import type { WarningCode } from "../../lib/logger"
@@ -21,14 +18,6 @@ type ConfigError =
let twitterWarned = false
function isValidHttpUrl(url: string) {
try {
return /^https?:/.test(new URL(url).protocol)
} catch {
return false
}
}
/**
* Verify that the user configured `next-auth` correctly.
* Good place to mention deprecations as well.
@@ -55,30 +44,8 @@ export function assertConfig(
}
}
const callbackUrlParam = req.query?.callbackUrl as string | undefined
if (callbackUrlParam && !isValidHttpUrl(callbackUrlParam)) {
return new InvalidCallbackUrl(
`Invalid callback URL. Received: ${callbackUrlParam}`
)
}
if (!req.host) return "NEXTAUTH_URL"
const url = parseUrl(req.host)
const { callbackUrl: defaultCallbackUrl } = defaultCookies(
options.useSecureCookies ?? url.base.startsWith("https://")
)
const callbackUrlCookie =
req.cookies?.[options.cookies?.callbackUrl?.name ?? defaultCallbackUrl.name]
if (callbackUrlCookie && !isValidHttpUrl(callbackUrlCookie)) {
return new InvalidCallbackUrl(
`Invalid callback URL. Received: ${callbackUrlCookie}`
)
}
let hasCredentials, hasEmail
let hasTwitterOAuth2

View File

@@ -68,7 +68,6 @@ export function defaultCookies(useSecureCookies: boolean): CookiesOptions {
callbackUrl: {
name: `${cookiePrefix}next-auth.callback-url`,
options: {
httpOnly: true,
sameSite: "lax",
path: "/",
secure: useSecureCookies,
@@ -121,7 +120,7 @@ export class SessionStore {
option: CookieOption,
req: {
cookies?: Record<string, string>
headers?: Headers | IncomingHttpHeaders | Record<string, string>
headers?: Record<string, string> | IncomingHttpHeaders
},
logger: LoggerInstance | Console
) {

View File

@@ -5,7 +5,7 @@ export const defaultCallbacks: CallbacksOptions = {
return true
},
redirect({ url, baseUrl }) {
if (url.startsWith("/")) return `${baseUrl}${url}`
if (url.startsWith("/")) return new URL(url, baseUrl).toString()
else if (new URL(url).origin === baseUrl) return url
return baseUrl
},

View File

@@ -123,11 +123,10 @@ export default function SigninPage(props: SignInServerPageParams) {
<input
id={`input-email-for-${provider.id}-provider`}
autoFocus
type="email"
type="text"
name="email"
value={email}
placeholder="email@example.com"
required
/>
<button type="submit">Sign in with {provider.name}</button>
</form>

View File

@@ -349,7 +349,6 @@ export default async function callback(params: {
}
} catch (error) {
return {
status: 401,
redirect: `${url}/error?error=${encodeURIComponent(
(error as Error).message
)}`,

View File

@@ -47,6 +47,7 @@ export interface NextAuthOptions {
*/
session?: Partial<SessionOptions>
/**
* JSON Web Tokens can be used for session tokens if enabled with the `session: { jwt: true }` option.
* JSON Web Tokens are enabled by default if you have not specified a database.
* By default JSON Web Tokens are signed (JWS) but not encrypted (JWE),
* as JWT encryption adds additional overhead and comes with some caveats.

View File

@@ -2,8 +2,7 @@ import { EncryptJWT, jwtDecrypt } from "jose"
import hkdf from "@panva/hkdf"
import { v4 as uuid } from "uuid"
import { SessionStore } from "../core/lib/cookie"
import type { GetServerSidePropsContext, NextApiRequest } from "next"
import type { NextRequest } from "next/server"
import type { NextApiRequest } from "next"
import type { JWT, JWTDecodeParams, JWTEncodeParams, JWTOptions } from "./types"
import type { LoggerInstance } from ".."
@@ -38,7 +37,7 @@ export async function decode(params: JWTDecodeParams): Promise<JWT | null> {
export interface GetTokenParams<R extends boolean = false> {
/** The request containing the JWT either in the cookies or in the `Authorization` header. */
req: GetServerSidePropsContext["req"] | NextRequest | NextApiRequest
req: NextApiRequest | Pick<NextApiRequest, "cookies" | "headers">
/**
* Use secure prefix for cookie name, unless URL in `NEXTAUTH_URL` is http://
* or not set (e.g. development or test instance) case use unprefixed name
@@ -91,13 +90,8 @@ export async function getToken<R extends boolean = false>(
let token = sessionStore.value
const authorizationHeader =
req.headers instanceof Headers
? req.headers.get("authorization")
: req.headers.authorization
if (!token && authorizationHeader?.split(" ")[0] === "Bearer") {
const urlEncodedToken = authorizationHeader.split(" ")[1]
if (!token && req.headers.authorization?.split(" ")[0] === "Bearer") {
const urlEncodedToken = req.headers.authorization.split(" ")[1]
token = decodeURIComponent(urlEncodedToken)
}

View File

@@ -1,6 +1,6 @@
import type { NextMiddleware, NextFetchEvent } from "next/server"
import type { Awaitable, CookieOption, NextAuthOptions } from ".."
import type { JWT, JWTOptions } from "../jwt"
import type { Awaitable, NextAuthOptions } from ".."
import type { JWT } from "../jwt"
import { NextResponse, NextRequest } from "next/server"
@@ -21,31 +21,6 @@ export interface NextAuthMiddlewareOptions {
* [Documentation](https://next-auth.js.org/configuration/pages)
*/
pages?: NextAuthOptions["pages"]
/**
* You can override the default cookie names and options for any of the cookies
* by this middleware. Similar to `cookies` in `NextAuth`.
*
* Useful if the token is stored in not a default cookie.
*
* ---
* [Documentation](https://next-auth.js.org/configuration/options#cookies)
*
* - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options,
* but **may have complex implications** or side effects.
* You should **try to avoid using advanced options** unless you are very comfortable using them.
*
*/
cookies?: Partial<Record<keyof Pick<keyof NextAuthOptions["cookies"], "sessionToken">, Omit<CookieOption, "options">>>
/**
* If a custom jwt `decode` method is set in `[...nextauth].ts`, the same method should be set here also.
*
* ---
* [Documentation](https://next-auth.js.org/configuration/nextjs#custom-jwt-decode-method)
*/
jwt?: Partial<Pick<JWTOptions, "decode">>
callbacks?: {
/**
* Callback that receives the user's JWT payload
@@ -106,11 +81,7 @@ async function handleMiddleware(
return NextResponse.redirect(errorUrl)
}
const token = await getToken({
req,
decode: options?.jwt?.decode,
cookieName: options?.cookies?.sessionToken?.name
})
const token = await getToken({ req: req as any })
const isAuthorized =
(await options?.callbacks?.authorized?.({ req, token })) ?? !!token
@@ -120,7 +91,7 @@ async function handleMiddleware(
// the user is not logged in, redirect to the sign-in page
const signInUrl = new URL(signInPage, req.nextUrl.origin)
signInUrl.searchParams.append("callbackUrl", `${req.nextUrl.pathname}${req.nextUrl.search}`)
signInUrl.searchParams.append("callbackUrl", req.url)
return NextResponse.redirect(signInUrl)
}

View File

@@ -134,7 +134,8 @@ export interface CampusUser {
created_at: string
updated_at: string | null
}
export interface FortyTwoProfile extends UserData, Record<string, any> {
export interface FortyTwoProfile extends UserData {
groups: Array<{ id: string; name: string }>
cursus_users: CursusUser[]
projects_users: ProjectUser[]
@@ -152,9 +153,9 @@ export interface FortyTwoProfile extends UserData, Record<string, any> {
user: any | null
}
export default function FortyTwo<P extends FortyTwoProfile>(
options: OAuthUserConfig<P>
): OAuthConfig<P> {
export default function FortyTwo<
P extends Record<string, any> = FortyTwoProfile
>(options: OAuthUserConfig<P>): OAuthConfig<P> {
return {
id: "42-school",
name: "42 School",

View File

@@ -5,7 +5,7 @@ import { OAuthConfig, OAuthUserConfig } from "."
* [Retrieve the User's Information from Apple ID Servers
](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773)
*/
export interface AppleProfile extends Record<string, any> {
export interface AppleProfile {
/**
* The issuer registered claim identifies the principal that issued the identity token.
* Since Apple generates the token, the value is `https://appleid.apple.com`.
@@ -87,7 +87,7 @@ export interface AppleProfile extends Record<string, any> {
auth_time: number
}
export default function Apple<P extends AppleProfile>(
export default function Apple<P extends Record<string, any> = AppleProfile>(
options: Omit<OAuthUserConfig<P>, "clientSecret"> & {
/**
* Apple requires the client secret to be a JWT. You can generate one using the following script:

View File

@@ -1,6 +1,6 @@
import type { OAuthConfig, OAuthUserConfig } from "."
interface AtlassianProfile extends Record<string, any> {
interface AtlassianProfile {
account_id: string
name: string
email: string

View File

@@ -1,13 +1,13 @@
import type { OAuthConfig, OAuthUserConfig } from "."
export interface Auth0Profile extends Record<string, any> {
export interface Auth0Profile {
sub: string
nickname: string
email: string
picture: string
}
export default function Auth0<P extends Auth0Profile>(
export default function Auth0<P extends Record<string, any> = Auth0Profile>(
options: OAuthUserConfig<P>
): OAuthConfig<P> {
return {

View File

@@ -1,29 +1,29 @@
import type { OAuthConfig, OAuthUserConfig } from "."
export interface AuthentikProfile extends Record<string, any> {
iss: string
sub: string
aud: string
exp: number
iat: number
auth_time: number
acr: string
c_hash: string
nonce: string
at_hash: string
email: string
email_verified: boolean
name: string
given_name: string
family_name: string
preferred_username: string
nickname: string
export interface AuthentikProfile {
iss: string,
sub: string,
aud: string,
exp: number,
iat: number,
auth_time: number,
acr: string,
c_hash: string,
nonce: string,
at_hash: string,
email: string,
email_verified: boolean,
name: string,
given_name: string,
family_name: string,
preferred_username: string,
nickname: string,
groups: string[]
}
export default function Authentik<P extends AuthentikProfile>(
options: OAuthUserConfig<P>
): OAuthConfig<P> {
export default function Authentik<
P extends Record<string, any> = AuthentikProfile
>(options: OAuthUserConfig<P>): OAuthConfig<P> {
return {
id: "authentik",
name: "Authentik",

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