Compare commits

..

45 Commits

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

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

* Update example.md

* Update example.md

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

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

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

---------

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

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

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

---------

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

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

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

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

7
.github/sync.yml vendored
View File

@@ -1,7 +0,0 @@
# This is a legacy example pushed from the v4 branch
nextauthjs/next-auth-example:
- source: apps/example-nextjs
dest: .
deleteOrphaned: true
- .github/FUNDING.yml
- LICENSE

View File

@@ -32,11 +32,16 @@ jobs:
run: pnpm install
- name: Build
run: pnpm build
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
- name: Run tests
run: pnpm test
env:
UPSTASH_REDIS_URL: ${{ secrets.UPSTASH_REDIS_URL }}
UPSTASH_REDIS_KEY: ${{ secrets.UPSTASH_REDIS_KEY }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
# - name: Coverage
# uses: codecov/codecov-action@v1
# with:

View File

@@ -1,18 +0,0 @@
name: Sync Example Repositories
on:
push:
branches:
- v4
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Run GitHub File Sync
# Can update to v1 when https://github.com/BetaHuhn/repo-file-sync-action/issues/168 is resolved
uses: BetaHuhn/repo-file-sync-action@v1.16.5
with:
GH_PAT: ${{ secrets.GH_PAT_CLASSIC }}
SKIP_PR: true

View File

@@ -1,14 +1,25 @@
import NextAuth, { type NextAuthOptions } from "next-auth"
import GitHub from "next-auth/providers/github"
// import { NextRequest } from "next/server"
export const authOptions: NextAuthOptions = {
providers: [
GitHub({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
clientId: process.env.GITHUB_ID as string,
clientSecret: process.env.GITHUB_SECRET as string,
}),
],
}
/**
* Advanced Initialization - route handler
*/
// const handler = async (
// req: NextRequest,
// routeContext: { params: { nextauth: string[] } }
// ): Promise<any> => {
// return NextAuth(req, routeContext, authOptions)
// }
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

View File

@@ -21,7 +21,7 @@
"@prisma/client": "^3",
"@supabase/supabase-js": "^2.0.5",
"faunadb": "^4",
"next": "13.3.0",
"next": "13.4.12",
"next-auth": "workspace:*",
"nodemailer": "^6",
"react": "^18",

View File

@@ -6,16 +6,18 @@ title: Adapters
Visit the [authjs.dev](https://authjs.dev/reference/adapters) page for the up-to-date documentation.
- [Dgraph](https://authjs.dev/reference/adapter/dgraph)
- [Drizzle](https://authjs.dev/reference/adapter/drizzle)
- [DynamoDB](https://authjs.dev/reference/adapter/dynamodb)
- [Fauna](https://authjs.dev/reference/adapter/fauna)
- [Firebase](https://authjs.dev/reference/adapter/firebase)
- [MongoDB](https://authjs.dev/reference/adapter/mongodb)
- [Prisma](https://authjs.dev/reference/adapter/prisma)
- [TypeORM](https://authjs.dev/reference/adapter/typeorm)
- [kysely](https://authjs.dev/reference/adapter/kysely)
- [MikroORM](https://authjs.dev/reference/adapter/mikro-orm)
- [MongoDB](https://authjs.dev/reference/adapter/mongodb)
- [neo4j](https://authjs.dev/reference/adapter/neo4j)
- [Prisma](https://authjs.dev/reference/adapter/prisma)
- [PouchDB](https://authjs.dev/reference/adapter/pouchdb)
- [Sequelize](https://authjs.dev/reference/adapter/sequelize)
- [Supabase](https://authjs.dev/reference/adapter/supabase)
- [TypeORM](https://authjs.dev/reference/adapter/typeorm)
- [Upstash Redis](https://authjs.dev/reference/adapter/upstash-redis)
- [Xata](https://authjs.dev/reference/adapter/xata)

View File

@@ -1,14 +1,29 @@
# Next.js
## `unstable_getServerSession`
This method was renamed to `getServerSession`. See the documentation below.
## `getServerSession`
When calling from server-side i.e. in API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` on server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
:::tip
You can create a helper function so you don't need to pass `authOptions` around:
Otherwise, if you only want to get the session token, see [`getToken`](/tutorials/securing-pages-and-api-routes#using-gettoken).
```ts title=auth.ts
import type { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from "next"
import type { NextAuthOptions } from "next-auth"
import { getServerSession } from "next-auth"
// You'll need to import and pass this
// to `NextAuth` in `app/api/auth/[...nextauth]/route.ts`
export const config = {
providers: [], // rest of your config
} satisfies NextAuthOptions
// Use it in server contexts
export function auth(...args: [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]] | [NextApiRequest, NextApiResponse] | []) {
return getServerSession(...args, config)
}
```
:::
When calling from the server-side i.e. in Route Handlers, React Server Components, API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` on server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
`getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way:
@@ -69,7 +84,7 @@ export default async function handler(req, res) {
}
```
### In `app/` directory:
### In App Router:
You can also use `getServerSession` in Next.js' server components:
@@ -91,6 +106,11 @@ Currently, the underlying Next.js `cookies()` method [only provides read access]
Note that using this function implies personalized data and that you should not store pages or APIs using this in a [public cache](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control). For example a host like [Vercel](https://vercel.com/docs/concepts/functions/serverless-functions/edge-caching) will implicitly prevent you from caching publicly due to the `set-cookie` header set by this function.
## `unstable_getServerSession`
This method was renamed to `getServerSession`. See the documentation above.
## Middleware
You can use a Next.js Middleware with NextAuth.js to protect your site.
@@ -158,22 +178,27 @@ Callbacks are asynchronous functions you can use to control what happens when an
#### Description
Specify URLs to be used if you want to create custom sign in, and error pages. Pages specified will override the corresponding built-in page.
Specify URLs to be used if you want to create custom sign-in and error pages. The pages specified will override the corresponding built-in page.
:::note
This should match the `pages` configuration that's found in `[...nextauth].ts`.
:::info
The `pages` configuration should match the same configuration in `[...nextauth].ts`. This is so that the `next-auth` Middleware is aware of your custom pages, so it won't end up redirecting to itself when an unauthenticated condition is met.
:::
#### Example (default value)
```js
pages: {
signIn: '/api/auth/signin',
error: '/api/auth/error',
}
import { withAuth } from "next-auth/middleware"
export default withAuth({
// Matches the pages config in `[...nextauth]`
pages: {
signIn: '/login',
error: '/error',
}
})
```
See the documentation for the [pages option](/configuration/pages) for more information.
For more information, see the documentation for the [pages option](/configuration/pages).
---
@@ -183,7 +208,7 @@ See the documentation for the [pages option](/configuration/pages) for more info
#### Description
The same `secret` used in the [NextAuth.js config](/configuration/options#options).
The same `secret` is used in the [NextAuth.js config](/configuration/options#options).
#### Example (default value)
@@ -229,7 +254,6 @@ The `middleware` function will only be invoked if the `authorized` callback retu
If you have a custom jwt decode method set in `[...nextauth].ts`, you must also pass the same `decode` method to `withAuth` in order to read the custom-signed JWT correctly. You may want to extract the encode/decode logic to a separate function for consistency.
``
```ts title="/api/auth/[...nextauth].ts"
import type { NextAuthOptions } from "next-auth"
import NextAuth from "next-auth"
@@ -257,7 +281,7 @@ import withAuth from "next-auth/middleware"
import { authOptions } from "pages/api/auth/[...nextauth]";
export default withAuth({
jwt: { decode: authOptions.jwt },
jwt: { decode: authOptions.jwt?.decode },
callbacks: {
authorized: ({ token }) => !!token,
},

View File

@@ -21,7 +21,7 @@ This error occurs when the `SessionProvider` Context has a problem fetching sess
#### CLIENT_FETCH_ERROR
If you see `CLIENT_FETCH_ERROR` make sure you have configured the `NEXTAUTH_URL` environment variable.
This can happen for multiple reasons. Make sure that you [configured](/configuration/initialization) NextAuth.js correctly, and if you used [`NEXTAUTH_URL`](https://next-auth.js.org/configuration/options#nextauth_url) that it's correctly set.
---

View File

@@ -203,7 +203,7 @@ export default NextAuth({
jwt({ token, trigger, session }) {
if (trigger === "update" && session?.name) {
// Note, that `session` can be any arbitrary object, remember to validate it!
token.name = session
token.name = session.name
}
return token
}
@@ -519,6 +519,10 @@ where `data.url` is the validated URL you can redirect the user to without any f
## SessionProvider
:::note
If you are using the App Router, we encourage you to use [`getServerSession`](/configuration/nextjs#getserversession) in server contexts instead. (`SessionProvider` *can* be used in the App Router, which might be the easier choice if you are migrating from pages.)
:::
Using the supplied `<SessionProvider>` allows instances of `useSession()` to share the session object across components, by using [React Context](https://react.dev/learn/passing-data-deeply-with-context) under the hood. It also takes care of keeping the session updated and synced between tabs/windows.
```jsx title="pages/_app.js"

View File

@@ -76,6 +76,7 @@ Instances of `useSession` will then have access to the session data and status.
:::tip
Check out the [client documentation](/getting-started/client) to see how you can improve the user experience and page performance by using the NextAuth.js client.
If you are using the Next.js App Router, please note that `<SessionProvider />` requires a client component and therefore cannot be put inside the root layout. For more details, check out the [Next.js documentation](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts).
:::
### Frontend - Add React Hook

View File

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

View File

@@ -125,7 +125,7 @@ providers: [
return user
},
credentials: {
email: { label: "Username", type: "text ", placeholder: "jsmith" },
username: { label: "Username", type: "text ", placeholder: "jsmith" },
"2fa-key": { label: "2FA Key" },
},
}),

View File

@@ -32,6 +32,14 @@ You can override any of the options to suit your own use case.
## Configuration
NextAuth.js lets you send emails either via HTTP or SMTP.
### HTTP
Check out our [HTTP-based Email Provider](https://authjs.dev/guides/providers/email-http) guide.
### SMTP
1. NextAuth.js does not include `nodemailer` as a dependency, so you'll need to install it yourself if you want to use the Email Provider. Run `npm install nodemailer` or `yarn add nodemailer`.
2. You will need an SMTP account; ideally for one of the [services known to work with `nodemailer`](https://community.nodemailer.com/2-0-0-beta/setup-smtp/well-known-services/).
3. There are two ways to configure the SMTP server connection.
@@ -252,3 +260,27 @@ By default, NextAuth.js will normalize the email address. It treats values as ca
:::warning
Always make sure this returns a single e-mail address, even if multiple ones were passed in.
:::
## Sending Magic Links To Existing Users
You can ensure that only existing users are sent a magic login link. You will need to grab the email the user entered and check your database to see if the email already exists in the "User" collection in your database. If it exists, it will send the user a magic link but otherwise, you can send the user to another page, such as "/register".
```js title="pages/api/auth/[...nextauth].js"
import User from "../../../models/User";
import db from "../../../utils/db";
...
callbacks: {
async signIn({ user, account, email }) {
await db.connect();
const userExists = await User.findOne({
email: user.email, //the user object has an email property, which contains the email the user entered.
});
if (userExists) {
return true; //if the email exists in the User collection, email them a magic login link
} else {
return "/register";
}
},
...
```

View File

@@ -3,6 +3,10 @@ id: gitlab
title: GitLab
---
:::note
GitLab returns a field on `Account` called `created_at` which is a number. See their [docs](https://docs.gitlab.com/ee/api/oauth2.html). Remember to add this field as optional to your database schema, in case if you are using an [Adapter](https://authjs.dev/reference/adapters).
:::
## Documentation
https://docs.gitlab.com/ee/api/oauth2.html

View File

@@ -11,7 +11,7 @@ https://help.salesforce.com/articleView?id=remoteaccess_authenticate.htm&type=5
The **Salesforce Provider** comes with a set of default options:
- [Salesforce Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/salesforce.js)
- [Salesforce Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/salesforce.ts)
You can override any of the options to suit your own use case.

View File

@@ -3,6 +3,10 @@ id: zoho
title: Zoho
---
:::note
Zoho returns a field on `Account` called `api_domain` which is a string. See their [docs](https://www.zoho.com/accounts/protocol/oauth/web-apps/access-token.html). Remember to add this field to your database schema, in case if you are using an [Adapter](https://authjs.dev/reference/adapters).
:::
## Documentation
https://www.zoho.com/accounts/protocol/oauth/web-server-applications.html

View File

@@ -118,7 +118,7 @@ Once you have saved your schema, use the Prisma CLI to generate the Prisma Clien
npx prisma generate
```
To configure you database to use the new schema (i.e. create tables and columns) use the `prisma migrate` command:
To configure your database to use the new schema (i.e. create tables and columns) use the `prisma migrate` command:
```
npx prisma migrate dev

View File

@@ -121,7 +121,7 @@ The `RefreshAccessTokenError` error that is caught in the `refreshAccessToken()`
We can handle this functionality as a side effect:
```js title="pages/api/auth/[...nextauth].js"
```js title="pages/index.js"
import { signIn, useSession } from "next-auth/client";
import { useEffect } from "react";

View File

@@ -168,7 +168,7 @@ export default function App({
## Security
If you think you have found a vulnerability (or not sure) in NextAuth.js or any of the related packages (i.e. Adapters), we ask you to have a read of our [Security Policy](https://github.com/nextauthjs/next-auth/blob/main/SECURITY.md) to reach out responsibly. Please do not open Pull Requests/Issues/Discussions before consulting with us.
If you think you have found a vulnerability (or not sure) in NextAuth.js or any of the related packages (i.e. Adapters), we ask you to have a read of our [Security Policy](https://github.com/nextauthjs/next-auth/security/policy) to reach out responsibly. Please do not open Pull Requests/Issues/Discussions before consulting with us.
## Acknowledgments

View File

@@ -1,6 +1,6 @@
{
"name": "next-auth",
"version": "4.22.3",
"version": "4.23.2",
"description": "Authentication for Next.js",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth.git",
@@ -9,7 +9,7 @@
"Balázs Orbán <info@balazsorban.com>",
"Nico Domino <yo@ndo.dev>",
"Lluis Agusti <hi@llu.lu>",
"Thang Huu Vu <thvu@hey.com>"
"Thang Huu Vu <hi@thvu.dev>"
],
"main": "index.js",
"module": "index.js",
@@ -27,19 +27,42 @@
"nextauth"
],
"exports": {
".": "./index.js",
"./jwt": "./jwt/index.js",
"./react": "./react/index.js",
"./core": "./core/index.js",
"./next": "./next/index.js",
"./middleware": "./middleware.js",
"./client/_utils": "./client/_utils.js",
"./providers/*": "./providers/*.js"
".": {
"types": "./index.d.ts",
"default": "./index.js"
},
"./adapters": {
"types": "./adapters.d.ts"
},
"./jwt": {
"types": "./jwt/index.d.ts",
"default": "./jwt/index.js"
},
"./react": {
"types": "./react/index.d.ts",
"default": "./react/index.js"
},
"./next": {
"types": "./next/index.d.ts",
"default": "./next/index.js"
},
"./middleware": {
"types": "./middleware.d.ts",
"default": "./middleware.js"
},
"./client/_utils": {
"types": "./client/_utils.d.ts",
"default": "./client/_utils.js"
},
"./providers/*": {
"types": "./providers/*.d.ts",
"default": "./providers/*.js"
}
},
"scripts": {
"build": "pnpm clean && pnpm build:js && pnpm build:css",
"build:js": "pnpm clean && pnpm generate-providers && pnpm tsc --project tsconfig.json && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
"clean": "rm -rf coverage client css utils providers core jwt react next index.d.ts index.js adapters.d.ts middleware.d.ts middleware.js",
"clean": "rm -rf coverage client css utils providers core jwt react next lib ./*.js ./*.ts*",
"build:css": "postcss --config config/postcss.config.js src/**/*.css --base src --dir . && node config/wrap-css.js",
"dev": "pnpm clean && pnpm generate-providers && concurrently \"pnpm watch:css\" \"pnpm watch:ts\"",
"watch:ts": "pnpm tsc --project tsconfig.dev.json",

View File

@@ -60,19 +60,21 @@ export interface VerificationToken {
* [Create a custom adapter](https://next-auth.js.org/tutorials/creating-a-database-adapter)
*/
export interface Adapter {
createUser: (user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>
getUser: (id: string) => Awaitable<AdapterUser | null>
getUserByEmail: (email: string) => Awaitable<AdapterUser | null>
createUser?: (user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>
getUser?: (id: string) => Awaitable<AdapterUser | null>
getUserByEmail?: (email: string) => Awaitable<AdapterUser | null>
/** Using the provider id and the id of the user for a specific account, get the user. */
getUserByAccount: (
getUserByAccount?: (
providerAccountId: Pick<AdapterAccount, "provider" | "providerAccountId">
) => Awaitable<AdapterUser | null>
updateUser: (user: Partial<AdapterUser> & Pick<AdapterUser, 'id'>) => Awaitable<AdapterUser>
updateUser?: (
user: Partial<AdapterUser> & Pick<AdapterUser, "id">
) => Awaitable<AdapterUser>
/** @todo Implement */
deleteUser?: (
userId: string
) => Promise<void> | Awaitable<AdapterUser | null | undefined>
linkAccount: (
linkAccount?: (
account: AdapterAccount
) => Promise<void> | Awaitable<AdapterAccount | null | undefined>
/** @todo Implement */
@@ -80,15 +82,15 @@ export interface Adapter {
providerAccountId: Pick<AdapterAccount, "provider" | "providerAccountId">
) => Promise<void> | Awaitable<AdapterAccount | undefined>
/** Creates a session for the user and returns it. */
createSession: (session: {
createSession?: (session: {
sessionToken: string
userId: string
expires: Date
}) => Awaitable<AdapterSession>
getSessionAndUser: (
getSessionAndUser?: (
sessionToken: string
) => Awaitable<{ session: AdapterSession; user: AdapterUser } | null>
updateSession: (
updateSession?: (
session: Partial<AdapterSession> & Pick<AdapterSession, "sessionToken">
) => Awaitable<AdapterSession | null | undefined>
/**
@@ -96,7 +98,7 @@ export interface Adapter {
* It is preferred that this method also returns the session
* that is being deleted for logging purposes.
*/
deleteSession: (
deleteSession?: (
sessionToken: string
) => Promise<void> | Awaitable<AdapterSession | null | undefined>
createVerificationToken?: (

View File

@@ -1,4 +1,4 @@
import type { EventCallbacks, LoggerInstance } from ".."
import type { EventCallbacks, InternalOptions, LoggerInstance } from ".."
/**
* Same as the default `Error`, but it is JSON serializable.
@@ -106,7 +106,7 @@ export function eventsErrorHandler(
export function adapterErrorHandler<TAdapter>(
adapter: TAdapter | undefined,
logger: LoggerInstance
): TAdapter | undefined {
): InternalOptions["adapter"] | undefined {
if (!adapter) return
return Object.keys(adapter).reduce<any>((acc, name) => {

View File

@@ -114,7 +114,7 @@ export function defaultCookies(useSecureCookies: boolean): CookiesOptions {
path: "/",
secure: useSecureCookies,
},
}
},
}
}
@@ -161,8 +161,21 @@ export class SessionStore {
}
}
/**
* The JWT Session or database Session ID
* constructed from the cookie chunks.
*/
get value() {
return Object.values(this.#chunks)?.join("")
// Sort the chunks by their keys before joining
const sortedKeys = Object.keys(this.#chunks).sort((a, b) => {
const aSuffix = parseInt(a.split(".").pop() ?? "0")
const bSuffix = parseInt(b.split(".").pop() ?? "0")
return aSuffix - bSuffix
})
// Use the sorted keys to join the chunks in the correct order
return sortedKeys.map((key) => this.#chunks[key]).join("")
}
/** Given a cookie, return a list of cookies, chunked to fit the allowed cookie size. */

View File

@@ -580,10 +580,12 @@ export type AuthAction =
| "error"
| "_log"
type NonNullableFields<T> = {
[P in keyof T]-?: NonNullable<T[P]>
}
/** @internal */
export interface InternalOptions<
TProviderType = ProviderType,
> {
export interface InternalOptions<TProviderType = ProviderType> {
providers: InternalProvider[]
/**
* Parsed from `NEXTAUTH_URL` or `x-forwarded-host` and `x-forwarded-proto` if the host is trusted.
@@ -602,7 +604,7 @@ export interface InternalOptions<
pages: Partial<PagesOptions>
jwt: JWTOptions
events: Partial<EventCallbacks>
adapter?: Adapter
adapter?: NonNullableFields<Adapter>
callbacks: CallbacksOptions
cookies: CookiesOptions
callbackUrl: string

View File

@@ -36,7 +36,7 @@ export interface JWTDecodeParams {
export interface JWTOptions {
/**
* The secret used to encode/decode the NextAuth.js issued JWT.
* @deprecated Set the `NEXTAUTH_SECRET` environment vairable or
* @deprecated Set the `NEXTAUTH_SECRET` environment variable or
* use the top-level `secret` option instead
*/
secret: string

View File

@@ -55,7 +55,8 @@ async function NextAuthApiHandler(
// Could chain. .end() when lowest target is Node 14
// https://github.com/nodejs/node/issues/33148
res.status(302).setHeader("Location", handler.redirect)
return res.end()
res.end()
return
}
return res.json({ url: handler.redirect })
}
@@ -66,7 +67,7 @@ async function NextAuthApiHandler(
// @see https://beta.nextjs.org/docs/routing/route-handlers
async function NextAuthRouteHandler(
req: NextRequest,
context: { params: { nextauth: string[] } },
context: RouteHandlerContext,
options: AuthOptions
) {
options.secret ??= process.env.NEXTAUTH_SECRET
@@ -100,6 +101,7 @@ async function NextAuthRouteHandler(
response.headers.delete("Location")
response.headers.set("Content-Type", "application/json")
return new Response(JSON.stringify({ url: redirect }), {
status: internalResponse.status,
headers: response.headers,
})
}
@@ -114,18 +116,27 @@ function NextAuth(
options: AuthOptions
): any
function NextAuth(
req: NextRequest,
res: RouteHandlerContext,
options: AuthOptions
): any
/** The main entry point to next-auth */
function NextAuth(
...args: [AuthOptions] | [NextApiRequest, NextApiResponse, AuthOptions]
...args:
| [AuthOptions]
| Parameters<typeof NextAuthRouteHandler>
| Parameters<typeof NextAuthApiHandler>
) {
if (args.length === 1) {
return async (
req: NextAuthRequest | NextRequest,
res: NextAuthResponse | RouteHandlerContext
) => {
if ((res as unknown as any)?.params) {
if ((res as any)?.params) {
return await NextAuthRouteHandler(
req as unknown as NextRequest,
req as NextRequest,
res as RouteHandlerContext,
args[0]
)
@@ -140,17 +151,15 @@ function NextAuth(
if ((args[1] as any)?.params) {
return NextAuthRouteHandler(
...(args as unknown as Parameters<typeof NextAuthRouteHandler>)
...(args as Parameters<typeof NextAuthRouteHandler>)
)
}
return NextAuthApiHandler(...args)
return NextAuthApiHandler(...(args as Parameters<typeof NextAuthApiHandler>))
}
export default NextAuth
let experimentalRSCWarningShown = false
type GetServerSessionOptions = Partial<Omit<AuthOptions, "callbacks">> & {
callbacks?: Omit<AuthOptions["callbacks"], "session"> & {
session?: (...args: Parameters<CallbacksOptions["session"]>) => any
@@ -170,19 +179,6 @@ export async function getServerSession<
: Session
>(...args: GetServerSessionParams<O>): Promise<R | null> {
const isRSC = args.length === 0 || args.length === 1
if (
!experimentalRSCWarningShown &&
isRSC &&
process.env.NODE_ENV !== "production"
) {
console.warn(
"[next-auth][warn][EXPERIMENTAL_API]",
"\n`getServerSession` is used in a React Server Component.",
`\nhttps://next-auth.js.org/configuration/nextjs#getServerSession}`,
`\nhttps://next-auth.js.org/warnings#EXPERIMENTAL_API`
)
experimentalRSCWarningShown = true
}
let req, res, options: AuthOptions
if (isRSC) {

View File

@@ -0,0 +1,56 @@
import type { OAuthConfig, OAuthUserConfig } from "."
/** @see [Supported Scopes](https://docs.passage.id/hosted-login/oidc-client-configuration#supported-scopes) */
export interface PassageProfile {
iss: string
/** Unique identifer in Passage for the user */
sub: string
aud: string[]
exp: number
iat: number
auth_time: number
azp: string
client_id: string
at_hash: string
c_hash: string
/** The user's email address */
email: string
/** Whether the user has verified their email address */
email_verified: boolean
/** The user's phone number */
phone: string
/** Whether the user has verified their phone number */
phone_number_verified: boolean
}
export default function Passage(
config: OAuthUserConfig<PassageProfile>
): OAuthConfig<PassageProfile> {
config.issuer = config.issuer?.replace(/\/$/, "")
return {
id: "passage",
name: "Passage",
type: "oauth",
wellKnown: `${config.issuer}/.well-known/openid-configuration`,
authorization: { params: { scope: "openid email" } },
client: { token_endpoint_auth_method: "client_secret_basic" },
checks: ["pkce", "state"],
profile(profile) {
return {
id: profile.sub,
name: null,
email: profile.email,
image: null,
}
},
style: {
logo: "/passage.svg",
logoDark: "/passage.svg",
bg: "#fff",
bgDark: "#fff",
text: "#000",
textDark: "#000",
},
options: config,
}
}

View File

@@ -247,7 +247,7 @@ export async function signIn<
isCredentials ? "callback" : "signin"
}/${provider}`
const _signInUrl = `${signInUrl}?${new URLSearchParams(authorizationParams)}`
const _signInUrl = `${signInUrl}${authorizationParams ? `?${new URLSearchParams(authorizationParams)}` : ""}`
const res = await fetch(_signInUrl, {
method: "post",

View File

@@ -35,7 +35,7 @@ export interface SignInOptions extends Record<string, unknown> {
}
export interface SignInResponse {
error: string | undefined
error: string | null
status: number
ok: boolean
url: string | null

146
pnpm-lock.yaml generated
View File

@@ -64,7 +64,7 @@ importers:
'@types/react-dom': ^18.0.6
fake-smtp-server: ^0.8.0
faunadb: ^4
next: 13.3.0
next: 13.4.12
next-auth: workspace:*
nodemailer: ^6
pg: ^8.7.3
@@ -81,7 +81,7 @@ importers:
'@prisma/client': 3.15.2_prisma@3.15.2
'@supabase/supabase-js': 2.0.5
faunadb: 4.6.0
next: 13.3.0_biqbaboplfbrettd7655fr4n2y
next: 13.4.12_biqbaboplfbrettd7655fr4n2y
next-auth: link:../../packages/next-auth
nodemailer: 6.7.5
react: 18.2.0
@@ -7541,6 +7541,11 @@ packages:
/@next/env/13.3.0:
resolution: {integrity: sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==}
dev: true
/@next/env/13.4.12:
resolution: {integrity: sha512-RmHanbV21saP/6OEPBJ7yJMuys68cIf8OBBWd7+uj40LdpmswVAwe1uzeuFyUsd6SfeITWT3XnQfn6wULeKwDQ==}
dev: false
/@next/swc-darwin-arm64/13.3.0:
resolution: {integrity: sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==}
@@ -7548,6 +7553,16 @@ packages:
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@next/swc-darwin-arm64/13.4.12:
resolution: {integrity: sha512-deUrbCXTMZ6ZhbOoloqecnUeNpUOupi8SE2tx4jPfNS9uyUR9zK4iXBvH65opVcA/9F5I/p8vDXSYbUlbmBjZg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@next/swc-darwin-x64/13.3.0:
@@ -7556,6 +7571,16 @@ packages:
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@next/swc-darwin-x64/13.4.12:
resolution: {integrity: sha512-WRvH7RxgRHlC1yb5oG0ZLx8F7uci9AivM5/HGGv9ZyG2Als8Ij64GC3d+mQ5sJhWjusyU6T6V1WKTUoTmOB0zQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/@next/swc-linux-arm64-gnu/13.3.0:
@@ -7564,6 +7589,16 @@ packages:
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@next/swc-linux-arm64-gnu/13.4.12:
resolution: {integrity: sha512-YEKracAWuxp54tKiAvvq73PUs9lok57cc8meYRibTWe/VdPB2vLgkTVWFcw31YDuRXdEhdX0fWS6Q+ESBhnEig==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@next/swc-linux-arm64-musl/13.3.0:
@@ -7572,6 +7607,16 @@ packages:
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@next/swc-linux-arm64-musl/13.4.12:
resolution: {integrity: sha512-LhJR7/RAjdHJ2Isl2pgc/JaoxNk0KtBgkVpiDJPVExVWA1c6gzY57+3zWuxuyWzTG+fhLZo2Y80pLXgIJv7g3g==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@next/swc-linux-x64-gnu/13.3.0:
@@ -7580,6 +7625,16 @@ packages:
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@next/swc-linux-x64-gnu/13.4.12:
resolution: {integrity: sha512-1DWLL/B9nBNiQRng+1aqs3OaZcxC16Nf+mOnpcrZZSdyKHek3WQh6j/fkbukObgNGwmCoVevLUa/p3UFTTqgqg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@next/swc-linux-x64-musl/13.3.0:
@@ -7588,6 +7643,16 @@ packages:
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@next/swc-linux-x64-musl/13.4.12:
resolution: {integrity: sha512-kEAJmgYFhp0VL+eRWmUkVxLVunn7oL9Mdue/FS8yzRBVj7Z0AnIrHpTIeIUl1bbdQq1VaoOztnKicAjfkLTRCQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/@next/swc-win32-arm64-msvc/13.3.0:
@@ -7596,6 +7661,16 @@ packages:
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@next/swc-win32-arm64-msvc/13.4.12:
resolution: {integrity: sha512-GMLuL/loR6yIIRTnPRY6UGbLL9MBdw2anxkOnANxvLvsml4F0HNIgvnU3Ej4BjbqMTNjD4hcPFdlEow4XHPdZA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/@next/swc-win32-ia32-msvc/13.3.0:
@@ -7604,6 +7679,16 @@ packages:
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@next/swc-win32-ia32-msvc/13.4.12:
resolution: {integrity: sha512-PhgNqN2Vnkm7XaMdRmmX0ZSwZXQAtamBVSa9A/V1dfKQCV1rjIZeiy/dbBnVYGdj63ANfsOR/30XpxP71W0eww==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: false
optional: true
/@next/swc-win32-x64-msvc/13.3.0:
@@ -7612,6 +7697,16 @@ packages:
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@next/swc-win32-x64-msvc/13.4.12:
resolution: {integrity: sha512-Z+56e/Ljt0bUs+T+jPjhFyxYBcdY2RIq9ELFU+qAMQMteHo7ymbV7CKmlcX59RI9C4YzN8PgMgLyAoi916b5HA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/@nicolo-ribaudo/chokidar-2/2.1.8-no-fsevents.3:
@@ -8186,6 +8281,13 @@ packages:
resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==}
dependencies:
tslib: 2.4.1
dev: true
/@swc/helpers/0.5.1:
resolution: {integrity: sha512-sJ902EfIzn1Fa+qYmjdQqh8tPsoxyBz+8yBKC2HKUxyezKJFwPGOn7pv4WY6QuQW//ySQi5lJjA/ZT9sNWWNTg==}
dependencies:
tslib: 2.4.1
dev: false
/@swc/jest/0.2.21_@swc+core@1.2.204:
resolution: {integrity: sha512-/+NcExiZbxXANNhNPnIdFuGq62CeumulLS1bngwqIXd8H7d96LFUfrYzdt8tlTwLMel8tFtQ5aRjzVkyOTyPDw==}
@@ -14770,7 +14872,6 @@ packages:
/glob-to-regexp/0.4.1:
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
dev: true
/glob/7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
@@ -14997,7 +15098,6 @@ packages:
/graceful-fs/4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
dev: true
/graphlib/2.1.8:
resolution: {integrity: sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==}
@@ -19242,14 +19342,13 @@ packages:
- babel-plugin-macros
dev: true
/next/13.3.0_biqbaboplfbrettd7655fr4n2y:
resolution: {integrity: sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==}
engines: {node: '>=14.6.0'}
/next/13.4.12_biqbaboplfbrettd7655fr4n2y:
resolution: {integrity: sha512-eHfnru9x6NRmTMcjQp6Nz0J4XH9OubmzOa7CkWL+AUrUxpibub3vWwttjduu9No16dug1kq04hiUUpo7J3m3Xw==}
engines: {node: '>=16.8.0'}
hasBin: true
peerDependencies:
'@opentelemetry/api': ^1.1.0
fibers: '>= 3.1.0'
node-sass: ^6.0.0 || ^7.0.0
react: ^18.2.0
react-dom: ^18.2.0
sass: ^1.3.0
@@ -19258,29 +19357,29 @@ packages:
optional: true
fibers:
optional: true
node-sass:
optional: true
sass:
optional: true
dependencies:
'@next/env': 13.3.0
'@swc/helpers': 0.4.14
'@next/env': 13.4.12
'@swc/helpers': 0.5.1
busboy: 1.6.0
caniuse-lite: 1.0.30001431
postcss: 8.4.14
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
styled-jsx: 5.1.1_react@18.2.0
watchpack: 2.4.0
zod: 3.21.4
optionalDependencies:
'@next/swc-darwin-arm64': 13.3.0
'@next/swc-darwin-x64': 13.3.0
'@next/swc-linux-arm64-gnu': 13.3.0
'@next/swc-linux-arm64-musl': 13.3.0
'@next/swc-linux-x64-gnu': 13.3.0
'@next/swc-linux-x64-musl': 13.3.0
'@next/swc-win32-arm64-msvc': 13.3.0
'@next/swc-win32-ia32-msvc': 13.3.0
'@next/swc-win32-x64-msvc': 13.3.0
'@next/swc-darwin-arm64': 13.4.12
'@next/swc-darwin-x64': 13.4.12
'@next/swc-linux-arm64-gnu': 13.4.12
'@next/swc-linux-arm64-musl': 13.4.12
'@next/swc-linux-x64-gnu': 13.4.12
'@next/swc-linux-x64-musl': 13.4.12
'@next/swc-win32-arm64-msvc': 13.4.12
'@next/swc-win32-ia32-msvc': 13.4.12
'@next/swc-win32-x64-msvc': 13.4.12
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@@ -24743,7 +24842,6 @@ packages:
dependencies:
glob-to-regexp: 0.4.1
graceful-fs: 4.2.10
dev: true
/wbuf/1.7.3:
resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==}
@@ -25321,6 +25419,10 @@ packages:
readable-stream: 3.6.0
dev: true
/zod/3.21.4:
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
dev: false
/zwitch/1.0.5:
resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==}
dev: true