Compare commits

..

1 Commits

Author SHA1 Message Date
Balázs Orbán
46304838af chore(release): bump version 2022-06-10 12:48:25 +00:00
117 changed files with 18472 additions and 14146 deletions

View File

@@ -69,7 +69,7 @@ jobs:
git config --global user.name "Balázs Orbán" git config --global user.name "Balázs Orbán"
pnpm release pnpm release
env: env:
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN_PKG }} NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN_PKG }}
NPM_TOKEN_ORG: ${{ secrets.NPM_TOKEN_ORG }} NPM_TOKEN_ORG: ${{ secrets.NPM_TOKEN_ORG }}
release-pr: release-pr:
@@ -103,7 +103,7 @@ jobs:
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
pnpm publish --no-git-checks --access public --tag experimental pnpm publish --no-git-checks --access public --tag experimental
env: env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN_PKG }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Comment version on PR - name: Comment version on PR
uses: NejcZdovc/comment-pr@v1 uses: NejcZdovc/comment-pr@v1
with: with:

2
.gitignore vendored
View File

@@ -30,7 +30,7 @@ packages/next-auth/providers
packages/next-auth/src/providers/oauth-types.ts packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/client packages/next-auth/client
packages/next-auth/css packages/next-auth/css
packages/next-auth/utils packages/next-auth/lib
packages/next-auth/core packages/next-auth/core
packages/next-auth/jwt packages/next-auth/jwt
packages/next-auth/react packages/next-auth/react

View File

@@ -16,21 +16,21 @@
}, },
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@next-auth/fauna-adapter": "^1", "@next-auth/fauna-adapter": "^1.0.1",
"@next-auth/prisma-adapter": "^1", "@next-auth/prisma-adapter": "^1.0.1",
"@prisma/client": "^3", "@prisma/client": "^3.10.0",
"faunadb": "^4",
"next": "12.1.7-canary.51",
"nodemailer": "^6",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/react": "^18",
"@types/react-dom": "^18",
"concurrently": "^7",
"cpx": "^1.5.0", "cpx": "^1.5.0",
"fake-smtp-server": "^0.8.0", "fake-smtp-server": "^0.8.0",
"prisma": "^3" "faunadb": "^4.4.1",
"next": "^12.1.0",
"nodemailer": "^6.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"concurrently": "^7.1.0",
"prisma": "^3.10.0"
} }
} }

View File

@@ -1,8 +1,8 @@
// This is an example of to protect an API route // This is an example of to protect an API route
import { unstable_getServerSession } from "next-auth/next" import { getSession } from "next-auth/react"
export default async (req, res) => { export default async (req, res) => {
const session = await unstable_getServerSession(req, res, options) const session = await getSession({ req })
if (session) { if (session) {
res.send({ res.send({

View File

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

View File

@@ -1,7 +1,5 @@
export { default } from "next-auth/middleware" export { default } from "next-auth/middleware"
export const config = { matcher: ["/middleware-protected"] }
// Other ways to use this middleware // Other ways to use this middleware
// import withAuth from "next-auth/middleware" // import withAuth from "next-auth/middleware"

View File

@@ -1,5 +1,5 @@
// This is an example of how to protect content using server rendering // This is an example of how to protect content using server rendering
import { unstable_getServerSession } from "next-auth/next" import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]" import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout" import Layout from "../components/layout"
import AccessDenied from "../components/access-denied" import AccessDenied from "../components/access-denied"
@@ -26,11 +26,7 @@ export default function Page({ content, session }) {
} }
export async function getServerSideProps(context) { export async function getServerSideProps(context) {
const session = await unstable_getServerSession( const session = await getServerSession(context, authOptions)
context.req,
context.res,
authOptions
)
let content = null let content = null
if (session) { if (session) {

View File

@@ -1,4 +1,4 @@
import { unstable_getServerSession } from "next-auth/next" import { getSession } from "next-auth/react"
import Layout from "../components/layout" import Layout from "../components/layout"
export default function Page() { export default function Page() {
@@ -11,17 +11,13 @@ export default function Page() {
<Layout> <Layout>
<h1>Server Side Rendering</h1> <h1>Server Side Rendering</h1>
<p> <p>
This page uses the <strong>unstable_getServerSession()</strong> method This page uses the universal <strong>getSession()</strong> method in{" "}
in <strong>getServerSideProps()</strong>. <strong>getServerSideProps()</strong>.
</p> </p>
<p> <p>
Using <strong>unstable_getServerSession()</strong> in{" "} Using <strong>getSession()</strong> in{" "}
<strong>getServerSideProps()</strong> is currently the recommended <strong>getServerSideProps()</strong> is the recommended approach if you
approach, although the API may still change, if you need to support need to support Server Side Rendering with authentication.
Server Side Rendering with authentication.
</p>
<p>
Using <strong>getSession()</strong> is still recommended on the client.
</p> </p>
<p> <p>
The advantage of Server Side Rendering is this page does not require The advantage of Server Side Rendering is this page does not require
@@ -39,11 +35,7 @@ export default function Page() {
export async function getServerSideProps(context) { export async function getServerSideProps(context) {
return { return {
props: { props: {
session: await unstable_getServerSession( session: await getSession(context),
contex.req,
contex.res,
authOptions
),
}, },
} }
} }

View File

@@ -65,6 +65,7 @@ You **can** skip configuring a database and come back to it later if you want.
For more information about setting up a database, please check out the following links: For more information about setting up a database, please check out the following links:
* Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview) * Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview)
* Adapters Repo: [nextauthjs/adapters](https://github.com/nextauthjs/adapters)
### 3. Configure Authentication Providers ### 3. Configure Authentication Providers

View File

@@ -12,9 +12,9 @@
"dependencies": { "dependencies": {
"dotenv": "^16.0.0", "dotenv": "^16.0.0",
"gatsby": "next", "gatsby": "next",
"next-auth": "latest", "next-auth": "^4.2.1",
"react": "^18", "react": "^17.0.2",
"react-dom": "^18" "react-dom": "^17.0.2"
}, },
"devDependencies": { "devDependencies": {
"vercel": "^23.1.2" "vercel": "^23.1.2"

View File

@@ -68,6 +68,7 @@ You **can** skip configuring a database and come back to it later if you want.
For more information about setting up a database, please check out the following links: For more information about setting up a database, please check out the following links:
* Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview) * Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview)
* Adapters Repo: [nextauthjs/adapters](https://github.com/nextauthjs/adapters)
### 3. Configure Authentication Providers ### 3. Configure Authentication Providers

View File

@@ -1,12 +0,0 @@
import { withAuth } from "next-auth/middleware"
// More on how NextAuth.js middleware works: https://next-auth.js.org/configuration/nextjs#middleware
export default withAuth({
callbacks: {
authorized: ({ req, token }) =>
// /admin requires admin role, but /me only requires the user to be logged in.
req.nextUrl.pathname !== "/admin" || token?.userRole === "admin",
},
})
export const config = { matcher: ["/admin", "/me"] }

View File

@@ -23,16 +23,16 @@
], ],
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"next": "12.1.7-canary.51", "next": "^12.0.11-canary.4",
"next-auth": "latest", "next-auth": "latest",
"nodemailer": "^6", "nodemailer": "^6.6.3",
"react": "^18", "react": "^17.0.2",
"react-dom": "^18" "react-dom": "^17.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^17", "@types/node": "^17.0.14",
"@types/react": "^18", "@types/react": "^17.0.39",
"typescript": "^4" "typescript": "^4.5.5"
}, },
"prettier": { "prettier": {
"semi": false "semi": false

View File

@@ -0,0 +1,8 @@
import { withAuth } from "next-auth/middleware"
// More on how NextAuth.js middleware works: https://next-auth.js.org/configuration/nextjs#middleware
export default withAuth({
callbacks: {
authorized: ({ token }) => token?.userRole === "admin",
},
})

View File

@@ -1,4 +1,4 @@
import Layout from "../components/layout" import Layout from "../../components/layout"
export default function Page() { export default function Page() {
return ( return (

View File

@@ -1,4 +1,4 @@
import NextAuth, { NextAuthOptions } from "next-auth" import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google" import GoogleProvider from "next-auth/providers/google"
import FacebookProvider from "next-auth/providers/facebook" import FacebookProvider from "next-auth/providers/facebook"
import GithubProvider from "next-auth/providers/github" import GithubProvider from "next-auth/providers/github"
@@ -9,7 +9,7 @@ import Auth0Provider from "next-auth/providers/auth0"
// For more information on each option (and a full list of options) go to // For more information on each option (and a full list of options) go to
// https://next-auth.js.org/configuration/options // https://next-auth.js.org/configuration/options
export const authOptions: NextAuthOptions = { export default NextAuth({
// https://next-auth.js.org/configuration/providers/oauth // https://next-auth.js.org/configuration/providers/oauth
providers: [ providers: [
/* EmailProvider({ /* EmailProvider({
@@ -18,7 +18,7 @@ export const authOptions: NextAuthOptions = {
}), }),
// Temporarily removing the Apple provider from the demo site as the // Temporarily removing the Apple provider from the demo site as the
// callback URL for it needs updating due to Vercel changing domains // callback URL for it needs updating due to Vercel changing domains
Providers.Apple({ Providers.Apple({
clientId: process.env.APPLE_ID, clientId: process.env.APPLE_ID,
clientSecret: { clientSecret: {
@@ -60,6 +60,4 @@ export const authOptions: NextAuthOptions = {
return token return token
}, },
}, },
} })
export default NextAuth(authOptions)

View File

@@ -1,9 +1,9 @@
// This is an example of to protect an API route // This is an example of to protect an API route
import { unstable_getServerSession } from "next-auth/next" import { getSession } from "next-auth/react"
import type { NextApiRequest, NextApiResponse } from "next" import type { NextApiRequest, NextApiResponse } from "next"
export default async (req: NextApiRequest, res: NextApiResponse) => { export default async (req: NextApiRequest, res: NextApiResponse) => {
const session = await unstable_getServerSession(req, res, authOptions) const session = await getSession({ req })
if (session) { if (session) {
res.send({ res.send({
@@ -12,8 +12,7 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
}) })
} else { } else {
res.send({ res.send({
error: error: "You must be signed in to view the protected content on this page.",
"You must be signed in to view the protected content on this page.",
}) })
} }
} }

View File

@@ -0,0 +1,2 @@
// More on how NextAuth.js middleware works: https://next-auth.js.org/configuration/nextjs#middleware
export { default } from "next-auth/middleware"

View File

@@ -1,5 +1,5 @@
import { useSession } from "next-auth/react" import { useSession } from "next-auth/react"
import Layout from "../components/layout" import Layout from "../../components/layout"
export default function MePage() { export default function MePage() {
const { data } = useSession() const { data } = useSession()

View File

@@ -1,24 +1,26 @@
import { unstable_getServerSession } from "next-auth/next" import { useSession, getSession } from "next-auth/react"
import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout" import Layout from "../components/layout"
import type { NextPageContext } from "next" import type { NextPageContext } from "next"
export default function ServerSidePage({ session }) { export default function ServerSidePage() {
// As this page uses Server Side Rendering, the `session` will be already // As this page uses Server Side Rendering, the `session` will be already
// populated on render without needing to go through a loading stage. // populated on render without needing to go through a loading stage.
// This is possible because of the shared context configured in `_app.js` that
// is used by `useSession()`.
const { data: session, status } = useSession()
const loading = status === "loading"
return ( return (
<Layout> <Layout>
<h1>Server Side Rendering</h1> <h1>Server Side Rendering</h1>
<p> <p>
This page uses the <strong>unstable_getServerSession()</strong> method This page uses the universal <strong>getSession()</strong> method in{" "}
in <strong>unstable_getServerSideProps()</strong>. <strong>getServerSideProps()</strong>.
</p> </p>
<p> <p>
Using <strong>unstable_getServerSession()</strong> in{" "} Using <strong>getSession()</strong> in{" "}
<strong>unstable_getServerSideProps()</strong> is the recommended <strong>getServerSideProps()</strong> is the recommended approach if you
approach if you need to support Server Side Rendering with need to support Server Side Rendering with authentication.
authentication.
</p> </p>
<p> <p>
The advantage of Server Side Rendering is this page does not require The advantage of Server Side Rendering is this page does not require
@@ -36,7 +38,7 @@ export default function ServerSidePage({ session }) {
export async function getServerSideProps(context: NextPageContext) { export async function getServerSideProps(context: NextPageContext) {
return { return {
props: { props: {
session: await unstable_getServerSession(context.req, context.res, authOptions), session: await getSession(context),
}, },
} }
} }

View File

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

View File

@@ -65,7 +65,7 @@ async function SKNextAuthHandler(
query: Object.fromEntries(url.searchParams), query: Object.fromEntries(url.searchParams),
headers: request.headers, headers: request.headers,
method: request.method, method: request.method,
cookies: cookie.parse(request.headers.get("cookie") ?? ""), cookies: cookie.parse(request.headers.get("cookie")),
action: nextauth[0] as NextAuthAction, action: nextauth[0] as NextAuthAction,
providerId: nextauth[1], providerId: nextauth[1],
error: nextauth[1], error: nextauth[1],
@@ -91,7 +91,7 @@ export async function getServerSession(
host: import.meta.env.VITE_NEXTAUTH_URL, host: import.meta.env.VITE_NEXTAUTH_URL,
action: "session", action: "session",
method: "GET", method: "GET",
cookies: cookie.parse(request.headers.get("cookie") ?? ""), cookies: cookie.parse(request.headers.get("cookie")),
headers: request.headers, headers: request.headers,
}, },
options, options,

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" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
next-auth@^4.5.0: next-auth@^4.3.3:
version "4.5.0" version "4.3.3"
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.5.0.tgz#2df57287fddc705b8971c88c60bad44a89ac6dd1" resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.3.3.tgz#5ff892e73648a0f33c2af0e9d7cafda729f63ae7"
integrity sha512-B6gYRIbqtj8nlDsx3y2Ruwp/mvZnItPs7VUULY43QYw+M9xtDPIM9EBZ3ryd/wNYA3MDteBJlzGm/ivseXcmJA== integrity sha512-bUs+oOOPT18Pq/+4v9q4PA/DGoVoAX6jwY7RTfE/akFXwlny+y/mNS6lPSUwpqcHjljqBaq34PQA3+01SdOOPw==
dependencies: dependencies:
"@babel/runtime" "^7.16.3" "@babel/runtime" "^7.16.3"
"@panva/hkdf" "^1.0.1" "@panva/hkdf" "^1.0.1"

View File

@@ -236,7 +236,7 @@ export default NextAuth({
encode: async ({ secret, token }) => { encode: async ({ secret, token }) => {
return jwt.sign({...token, userId: token.id}, secret, { return jwt.sign({...token, userId: token.id}, secret, {
algorithm: "HS256", algorithm: "HS256",
expiresIn: 30 * 24 * 60 * 60, // 30 days expiresIn: 30 * 24 * 60 * 60; // 30 days
}); });
}, },
decode: async ({ secret, token }) => { decode: async ({ secret, token }) => {

View File

@@ -107,7 +107,7 @@ The redirect callback may be invoked more than once in the same flow.
This callback is called whenever a JSON Web Token is created (i.e. at sign This callback is called whenever a JSON Web Token is created (i.e. at sign
in) or updated (i.e whenever a session is accessed in the client). The returned value will be [encrypted](/configuration/options#jwt), and it is stored in a cookie. in) or updated (i.e whenever a session is accessed in the client). The returned value will be [encrypted](/configuration/options#jwt), and it is stored in a cookie.
Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`, `unstable_getServerSession()`, `useSession()` will invoke this function, but only if you are using a [JWT session](/configuration/options#session). This method is not invoked when you persist sessions in a database. Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`, `useSession()` will invoke this function, but only if you are using a [JWT session](/configuration/options#session). This method is not invoked when you persist sessions in a database.
- As with database persisted session expiry times, token expiry time is extended whenever a session is active. - As with database persisted session expiry times, token expiry time is extended whenever a session is active.
- The arguments _user_, _account_, _profile_ and _isNewUser_ are only passed the first time this callback is called on a new session, after the user signs in. In subsequent calls, only `token` will be available. - The arguments _user_, _account_, _profile_ and _isNewUser_ are only passed the first time this callback is called on a new session, after the user signs in. In subsequent calls, only `token` will be available.

View File

@@ -53,7 +53,6 @@ The message object will contain:
- `user`: The user object from your adapter. - `user`: The user object from your adapter.
- `account`: The object returned from the provider. - `account`: The object returned from the provider.
- `profile`: The object returned from the `profile` callback of the OAuth provider.
### session ### session

View File

@@ -1,73 +1,5 @@
# Next.js # Next.js
## `unstable_getServerSession`
:::warning
This feature is experimental and may be removed or changed in the future.
:::
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` 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, `unstable_getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
Otherwise, if you only want to get the session token, see [`getToken`](tutorials/securing-pages-and-api-routes#using-gettoken).
`unstable_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:
In `[...nextauth.js]`:
```ts
import { NextAuth } from 'next-auth'
import type { NextAuthOptions } from 'next-auth'
export const authOptions: NextAuthOptions = {
// your configs
}
export default NextAuth(authOptions);
```
In `getServerSideProps`:
```js
import { authOptions } from 'pages/api/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(context.req, context.res, authOptions)
if (!session) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}
return {
props: {
session,
},
}
}
```
In API routes:
```js
import { authOptions } from 'pages/api/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
export async function handler(req, res) {
const session = await unstable_getServerSession(req, res, authOptions)
if (!session) {
res.status(401).json({ message: "You must be logged in." });
return;
}
return res.json({
message: 'Success',
})
}
```
## Middleware ## Middleware
You can use a Next.js Middleware with NextAuth.js to protect your site. You can use a Next.js Middleware with NextAuth.js to protect your site.
@@ -86,27 +18,50 @@ You must set the [`NEXTAUTH_SECRET`](/configuration/options#nextauth_secret) env
### Basic usage ### Basic usage
The most simple usage is when you want to require authentication for your entire site. You can add a `middleware.js` file with the following:
```js ```js
export { default } from "next-auth/middleware" import withAuth from "next-auth/middleware"
// or
import { withAuth } from "next-auth/middleware"
``` ```
That's it! Your application is not secured. 🎉 ### Custom JWT decode method
If you only want to secure certain pages, export a `config` object with a `matcher`: 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.
```js `[...nextauth].ts`
export { default } from "next-auth/middleware" ```ts
import jwt from "jsonwebtoken";
export const config = { matcher: ["/dashboard"] } 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;
},
},
})
``` ```
Now you will still be able to visit every page, but only `/dashboard` will require authentication. Any `_middleware.ts`
```ts
If a user is not logged in, the default behavior is to redirect them to the sign-in page. 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` ### `callbacks`
@@ -149,24 +104,46 @@ See the documentation for the [pages option](/configuration/pages) for more info
--- ---
### Advanced usage ### Examples
NextAuth.js Middleware is very flexible, there are multiple ways to use it. `withAuth` is very flexible, there are multiple ways to use it.
:::note :::note
If you do not define the options, NextAuth.js will use the default values for the omitted options. If you do not define the options, NextAuth.js will use the default values for the omitted options.
::: :::
#### default re-export
```js title="pages/_middleware.js"
export { default } from "next-auth/middleware"
```
With this one line, when someone tries to load any of your pages, they will have to be logged-in first. Otherwise, they are redirected to the login page. It will assume that you are using the `NEXTAUTH_SECRET` environment variable.
#### default `withAuth` export
```js title="pages/admin/_middleware.js"
import { withAuth } from "next-auth/middleware"
export default withAuth({
callbacks: {
authorized: ({ token }) => token?.role === "admin",
},
})
```
With the above code, you just made sure that only user's with the `admin` role can access any of the pages under the `/admin` route. (Including nested routes as well, like `/admin/settings` etc.).
#### wrap middleware #### wrap middleware
```ts title="middleware.ts" ```ts title="pages/admin/_middleware.ts"
import type { NextRequest } from "next/server" import type { NextRequest } from "next/server"
import type { JWT } from "next-auth/jwt" import type { JWT } from "next-auth/jwt"
import { withAuth } from "next-auth/middleware" import { withAuth } from "next-auth/middleware"
export default withAuth( export default withAuth(
// `withAuth` can augment your Request with the user's token. function middleware(req: NextRequest & { nextauth: { token: JWT } }) {
function middleware(req: NextRequest & { nextauth: { token: JWT | null } }) {
console.log(req.nextauth.token) console.log(req.nextauth.token)
}, },
{ {
@@ -175,53 +152,12 @@ export default withAuth(
}, },
} }
) )
export const config = { matcher: ["/admin"] }
``` ```
The `middleware` function will only be invoked if the `authorized` callback returns `true`. The `middleware` function will only be invoked if the `authorized` callback returns `true`.
--- ---
#### Custom JWT decode method
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"
import jwt from "jsonwebtoken"
export const authOptions: NextAuthOptions = {
providers: [...],
jwt: {
async encode({ secret, token }) {
return jwt.sign(token, secret)
},
async decode({ secret, token }) {
return jwt.verify(token, secret)
},
},
}
export default NextAuth(authOptions)
```
And:
```ts title="middleware.ts"
import withAuth from "next-auth/middleware"
import { authOptions } from "pages/api/auth/[...nextauth]";
export default withAuth({
jwt: { decode: authOptions.jwt },
callbacks: {
authorized: ({ token }) => !!token,
},
})
```
### Caveats ### Caveats
- Currently only supports session verification, as parts of the sign-in code need to run in a Node.js environment. In the future, we would like to make sure that NextAuth.js can fully run at the [Edge](https://nextjs.org/docs/api-reference/edge-runtime) - Currently only supports session verification, as parts of the sign-in code need to run in a Node.js environment. In the future, we would like to make sure that NextAuth.js can fully run at the [Edge](https://nextjs.org/docs/api-reference/edge-runtime)

View File

@@ -126,10 +126,10 @@ function Auth({ children }) {
// if `{ required: true }` is supplied, `status` can only be "loading" or "authenticated" // if `{ required: true }` is supplied, `status` can only be "loading" or "authenticated"
const { status } = useSession({ required: true }) const { status } = useSession({ required: true })
if (status === "loading") { if (status === 'loading') {
return <div>Loading...</div> return <div>Loading...</div>
} }
return children return children
} }
``` ```
@@ -161,13 +161,13 @@ See repository [`README`](https://github.com/nextauthjs/react-query) for more de
## getSession() ## getSession()
- Client Side: **Yes** - Client Side: **Yes**
- Server Side: **No** (See: [`unstable_getServerSession()`](/configuration/nextjs#unstable_getserversession) - Server Side: **Yes**
NextAuth.js provides a `getSession()` helper which should be called **client side only** to return the current active session. NextAuth.js provides a `getSession()` method which can be called client or server side to return a session.
This helper is helpful in case you want to read the session outside of the context of React. It calls `/api/auth/session` and returns a promise with a session object, or null if no session exists.
When called, `getSession()` will send a request to `/api/auth/session` and returns a promise with a [session object](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/core/types.ts#L407-L425), or `null` if no session exists. #### Client Side Example
```js ```js
async function myFunction() { async function myFunction() {
@@ -176,7 +176,23 @@ async function myFunction() {
} }
``` ```
Read the tutorial [securing pages and API routes](/tutorials/securing-pages-and-api-routes) to know how to fetch the session in server side calls using `unstable_getServerSession()`. #### Server Side Example
```js
import { getSession } from "next-auth/react"
export default async (req, res) => {
const session = await getSession({ req })
/* ... */
res.end()
}
```
:::note
When calling `getSession()` server side, you need to pass `{req}` or `context` object.
:::
The tutorial [securing pages and API routes](/tutorials/securing-pages-and-api-routes) shows how to use `getSession()` in server side calls.
--- ---
@@ -238,7 +254,7 @@ export default async (req, res) => {
``` ```
:::note :::note
Unlike and `getCsrfToken()`, when calling `getProviders()` server side, you don't need to pass anything, just as calling it client side. Unlike `getSession()` and `getCsrfToken()`, when calling `getProviders()` server side, you don't need to pass anything, just as calling it client side.
::: :::
--- ---
@@ -420,14 +436,14 @@ If you pass the `session` page prop to the `<SessionProvider>` as in the exa
This only works on pages where you provide the correct `pageProps`, however. This is normally done in `getInitialProps` or `getServerSideProps` on an individual page basis like so: This only works on pages where you provide the correct `pageProps`, however. This is normally done in `getInitialProps` or `getServerSideProps` on an individual page basis like so:
```js title="pages/index.js" ```js title="pages/index.js"
import { unstable_getServerSession } from "next-auth/next" import { getSession } from "next-auth/react"
... ...
export async function getServerSideProps(ctx) { export async function getServerSideProps(ctx) {
return { return {
props: { props: {
session: await unstable_getServerSession(ctx) session: await getSession(ctx)
} }
} }
} }
@@ -439,7 +455,7 @@ If every one of your pages needs to be protected, you can do this in `getInitial
The session state is automatically synchronized across all open tabs/windows and they are all updated whenever they gain or lose focus or the state changes (e.g. a user signs in or out) when `refetchOnWindowFocus` is `true`. The session state is automatically synchronized across all open tabs/windows and they are all updated whenever they gain or lose focus or the state changes (e.g. a user signs in or out) when `refetchOnWindowFocus` is `true`.
If you have session expiry times of 30 days (the default) or more then you probably don't need to change any of the default options in the Provider. If you need to, you can trigger an update of the session object across all tabs/windows by calling [`getSession()`](/getting-started/client#getsession) from a client side function. If you have session expiry times of 30 days (the default) or more then you probably don't need to change any of the default options in the Provider. If you need to, you can trigger an update of the session object across all tabs/windows by calling `getSession()` from a client side function.
However, if you need to customize the session behavior and/or are using short session expiry times, you can pass options to the provider to customize the behavior of the `useSession()` hook. However, if you need to customize the session behavior and/or are using short session expiry times, you can pass options to the provider to customize the behavior of the `useSession()` hook.

View File

@@ -93,13 +93,13 @@ You can use the `useSession` hook from anywhere in your application (e.g. in a h
### Backend - API Route ### Backend - API Route
To protect an API Route, you can use the [`unstable_getServerSession()`](/configuration/nextjs#unstable_getserversession) method. 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 title="pages/api/restricted.js" showLineNumbers
import { unstable_getServerSession } from "next-auth/next" import { getSession } from "next-auth/react"
export default async (req, res) => { export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions) const session = await getSession({ req })
if (session) { if (session) {
res.send({ res.send({
@@ -143,7 +143,7 @@ callbacks: {
... ...
``` ```
Now whenever you call [`getSession`](/getting-started/client#getsession) or [`useSession`](/getting-started/client#usesession), the data object which is returned will include the `accessToken` value. Now whenever you call `getSession` or `useSession`, the data object which is returned will include the `accessToken` value.
```jsx title="components/accessToken.jsx" showLineNumbers ```jsx title="components/accessToken.jsx" showLineNumbers
import { useSession, signIn, signOut } from "next-auth/react" import { useSession, signIn, signOut } from "next-auth/react"

View File

@@ -30,8 +30,8 @@ import GitHubProvider from "next-auth/providers/github";
... ...
providers: [ providers: [
GitHubProvider({ GitHubProvider({
clientId: process.env.GITHUB_ID, clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_SECRET clientSecret: process.env.GITHUB_CLIENT_SECRET
}) })
] ]
... ...

View File

@@ -13,7 +13,7 @@ https://api.slack.com/docs/sign-in-with-slack
https://api.slack.com/apps https://api.slack.com/apps
:::warning :::warning
Slack requires that the redirect URL of your app uses `https`, even for local development. An easy workaround for this is using a service like [`ngrok`](https://ngrok.com) that creates a secure tunnel to your app, using `https`. Remember to set the url as `NEXTAUTH_URL` as well. Slack requires you that the redirect URL of your app uses `https`, even for local development. An easy workaround for this is using a service like [`ngrok`](https://ngrok.com) that creates a secure tunnel to your app, using `https`. Remember to set the url as `NEXTAUTH_URL` as well.
::: :::
![](https://i.imgur.com/ydYKTLD.png) ![](https://i.imgur.com/ydYKTLD.png)

View File

@@ -15,7 +15,7 @@ https://dashboard.workos.com
The **WorkOS Provider** comes with a set of default options: The **WorkOS Provider** comes with a set of default options:
- [WorkOS Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/workos.ts) - [WorkOS Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/workos.js)
You can override any of the options to suit your own use case. You can override any of the options to suit your own use case.

View File

@@ -40,28 +40,12 @@ export default function Page() {
} }
``` ```
### Next.js (Middleware)
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `_middleware.js` file in your root `pages` directory which looks like this.
```js title="/pages/_middleware.js"
export { default } from "next-auth/middleware"
```
Otherwise, if you only want to protect a subset of pages, you could put it in a subdirectory as well, for example in `/pages/admin/_middleware.js` would protect all pages under `/admin`.
For the time being, the `withAuth` middleware only supports `"jwt"` as [session strategy](https://next-auth.js.org/configuration/options#session).
More details can be found [here](https://next-auth.js.org/configuration/nextjs#middleware).
### Server Side ### Server Side
You can protect server side rendered pages using the `unstable_getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly. You can protect server side rendered pages using the `getSession()` method.
You need to add this to every server rendered page you want to protect.
```js title="pages/server-side-example.js" ```js title="pages/server-side-example.js"
import { useSession, unstable_getServerSession } from "next-auth/next" import { useSession, getSession } from "next-auth/react"
export default function Page() { export default function Page() {
const { data: session } = useSession() const { data: session } = useSession()
@@ -82,7 +66,7 @@ export default function Page() {
export async function getServerSideProps(context) { export async function getServerSideProps(context) {
return { return {
props: { props: {
session: await unstable_getServerSession(context.req, context.res, authOptions), session: await getSession(context),
}, },
} }
} }
@@ -110,15 +94,15 @@ export default function App({
## Securing API Routes ## Securing API Routes
### Using unstable_getServerSession() ### Using getSession()
You can protect API routes using the `unstable_getServerSession()` method. You can protect API routes using the `getSession()` method.
```js title="pages/api/get-session-example.js" ```js title="pages/api/get-session-example.js"
import { unstable_getServerSession } from "next-auth/next" import { getSession } from "next-auth/react"
export default async (req, res) => { export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions) const session = await getSession({ req })
if (session) { if (session) {
// Signed in // Signed in
console.log("Session", JSON.stringify(session, null, 2)) console.log("Session", JSON.stringify(session, null, 2))

View File

@@ -33,10 +33,6 @@ In development, we generate a `secret` based on your configuration for convenien
Twitter OAuth 2.0 is currently in beta as certain changes might still be necessary. This is not covered by semver. See the docs https://next-auth.js.org/providers/twitter#oauth-2 Twitter OAuth 2.0 is currently in beta as certain changes might still be necessary. This is not covered by semver. See the docs https://next-auth.js.org/providers/twitter#oauth-2
#### EXPERIMENTAL_API
Some APIs are still experimental; they may be changed or removed in the future. Use at your own risk.
## Adapter ## Adapter
### ADAPTER_TYPEORM_UPDATING_ENTITIES ### ADAPTER_TYPEORM_UPDATING_ENTITIES

View File

@@ -19,10 +19,10 @@
"generate-providers": "node ./scripts/generate-providers.js" "generate-providers": "node ./scripts/generate-providers.js"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "^2.0.0-beta.21", "@docusaurus/core": "^2.0.0-beta.20",
"@docusaurus/preset-classic": "^2.0.0-beta.21", "@docusaurus/preset-classic": "^2.0.0-beta.20",
"@docusaurus/remark-plugin-npm2yarn": "^2.0.0-beta.21", "@docusaurus/remark-plugin-npm2yarn": "^2.0.0-beta.20",
"@docusaurus/theme-common": "2.0.0-beta.21", "@docusaurus/theme-common": "2.0.0-beta.20",
"@mdx-js/react": "1.6.22", "@mdx-js/react": "1.6.22",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"mdx-mermaid": "^1.2.2", "mdx-mermaid": "^1.2.2",

View File

@@ -1,23 +1,4 @@
{ {
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
}
]
}
],
"redirects": [ "redirects": [
{ {
"source": "/schemas/models", "source": "/schemas/models",

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<!-- <p align="center" style="align: center;"> <!-- <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/prisma-adapter" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/prisma-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/prisma-adapter" alt="@next-auth/prisma-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/prisma-adapter" alt="@next-auth/prisma-adapter Version" />
</p> --> </p> -->
@@ -150,7 +150,7 @@ type User
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,9 +3,9 @@
"version": "1.0.3", "version": "1.0.3",
"description": "Dgraph adapter for next-auth.", "description": "Dgraph adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/adapters/issues"
}, },
"author": "Arnaud Derbey <arnaud@derbey.dev>", "author": "Arnaud Derbey <arnaud@derbey.dev>",
"contributors": [], "contributors": [],

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Build Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Build Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/dynamodb-adapter/latest" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/dynamodb-adapter/latest" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/dynamodb-adapter" alt="@next-auth/dynamodb-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/dynamodb-adapter" alt="@next-auth/dynamodb-adapter Version" />
</p> </p>
@@ -96,7 +96,7 @@ Here is a schema of the table :
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -1,6 +1,6 @@
{ {
"name": "@next-auth/dynamodb-adapter", "name": "@next-auth/dynamodb-adapter",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"version": "1.0.3", "version": "1.0.3",
"description": "AWS DynamoDB adapter for next-auth.", "description": "AWS DynamoDB adapter for next-auth.",
"keywords": [ "keywords": [

View File

@@ -7,7 +7,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Build Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Build Test" />
<a href="https://www.npmjs.com/package/@next-auth/faunadb-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/fauna-adapter/next" alt="Bundle Size"/></a> <a href="https://www.npmjs.com/package/@next-auth/faunadb-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/fauna-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/faunadb-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/fauna-adapter/next" alt="@next-auth/fauna-adapter Version" /></a> <a href="https://www.npmjs.com/package/@next-auth/faunadb-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/fauna-adapter/next" alt="@next-auth/fauna-adapter Version" /></a>
</p> </p>
@@ -53,7 +53,7 @@ export default NextAuth({
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3", "version": "1.0.3",
"description": "Fauna Adapter for NextAuth", "description": "Fauna Adapter for NextAuth",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },

View File

@@ -7,7 +7,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Build Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Build Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/firebase-adapter/latest" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/firebase-adapter/latest" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/firebase-adapter" alt="@next-auth/firebase-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/firebase-adapter" alt="@next-auth/firebase-adapter Version" />
</p> </p>
@@ -83,7 +83,7 @@ See [firebase.google.com/docs/web/setup](https://firebase.google.com/docs/web/se
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,9 +3,9 @@
"version": "0.1.3", "version": "0.1.3",
"description": "Firebase adapter for next-auth.", "description": "Firebase adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/adapters/issues"
}, },
"author": "Ron Houben <ron.houben85@gmail.com>", "author": "Ron Houben <ron.houben85@gmail.com>",
"contributors": [ "contributors": [

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/mikro-orm-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/mikro-orm-adapter/next" alt="Bundle Size"/></a> <a href="https://www.npmjs.com/package/@next-auth/mikro-orm-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/mikro-orm-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/mikro-orm-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/mikro-orm-adapter/next" alt="@next-auth/mikro-orm-adapter Version" /></a> <a href="https://www.npmjs.com/package/@next-auth/mikro-orm-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/mikro-orm-adapter/next" alt="@next-auth/mikro-orm-adapter Version" /></a>
</p> </p>
@@ -49,7 +49,7 @@ This is the MikroORM Adapter for [`next-auth`](https://next-auth.js.org). This p
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,7 +3,7 @@
"version": "2.0.1", "version": "2.0.1",
"description": "MikroORM adapter for next-auth.", "description": "MikroORM adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/mongodb-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/mongodb-adapter" alt="Bundle Size"/></a> <a href="https://www.npmjs.com/package/@next-auth/mongodb-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/mongodb-adapter" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/mongodb-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/mongodb-adapter" alt="@next-auth/mongodb-adapter Version" /></a> <a href="https://www.npmjs.com/package/@next-auth/mongodb-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/mongodb-adapter" alt="@next-auth/mongodb-adapter Version" /></a>
</p> </p>
@@ -79,7 +79,7 @@ export default NextAuth({
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3", "version": "1.0.3",
"description": "mongoDB adapter for next-auth.", "description": "mongoDB adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Canary CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Canary CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/neo4j-adapter" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/neo4j-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/neo4j-adapter" alt="@next-auth/neo4j-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/neo4j-adapter" alt="@next-auth/neo4j-adapter Version" />
</p> </p>
@@ -50,7 +50,7 @@ export default NextAuth({
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please first read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/canary/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please first read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/canary/CONTRIBUTING.md).
## License ## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3", "version": "1.0.3",
"description": "neo4j adapter for next-auth.", "description": "neo4j adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/pouchdb-adapter" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/pouchdb-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/pouchdb-adapter" alt="@next-auth/pouchdb-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/pouchdb-adapter" alt="@next-auth/pouchdb-adapter Version" />
</p> </p>
@@ -71,7 +71,7 @@ For more details, please see https://pouchdb.com/api.html#sync
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,7 +3,7 @@
"version": "0.1.3", "version": "0.1.3",
"description": "PouchDB adapter for next-auth.", "description": "PouchDB adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/prisma-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/prisma-adapter/next" alt="Bundle Size"/></a> <a href="https://www.npmjs.com/package/@next-auth/prisma-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/prisma-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/prisma-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/prisma-adapter/next" alt="@next-auth/prisma-adapter Version" /></a> <a href="https://www.npmjs.com/package/@next-auth/prisma-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/prisma-adapter/next" alt="@next-auth/prisma-adapter Version" /></a>
</p> </p>
@@ -48,7 +48,7 @@ export default NextAuth({
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3", "version": "1.0.3",
"description": "Prisma adapter for next-auth.", "description": "Prisma adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/sequelize-adapter" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/sequelize-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/sequelize-adapter" alt="@next-auth/sequelize-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/sequelize-adapter" alt="@next-auth/sequelize-adapter Version" />
</p> </p>
@@ -89,7 +89,7 @@ export default NextAuth({
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -1,11 +1,11 @@
{ {
"name": "@next-auth/sequelize-adapter", "name": "@next-auth/sequelize-adapter",
"version": "1.0.4", "version": "1.0.3",
"description": "Sequelize adapter for next-auth.", "description": "Sequelize adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/adapters/issues"
}, },
"author": "github.com/luke-j", "author": "github.com/luke-j",
"main": "dist/index.js", "main": "dist/index.js",
@@ -42,4 +42,4 @@
"jest": { "jest": {
"preset": "@next-auth/adapter-test/jest" "preset": "@next-auth/adapter-test/jest"
} }
} }

View File

@@ -1,7 +1,7 @@
module.exports = { module.exports = {
transform: { transform: {
".(ts|tsx)$": "@swc/jest", ".(ts|tsx)$": "ts-jest",
".(js|jsx)$": "@swc/jest", // jest's default ".(js|jsx)$": "babel-jest", // jest's default
}, },
transformIgnorePatterns: ["[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"], transformIgnorePatterns: ["[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"],
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],

View File

@@ -19,6 +19,7 @@
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@typescript-eslint/eslint-plugin": "^4.24.0", "@typescript-eslint/eslint-plugin": "^4.24.0",
"@typescript-eslint/parser": "^4.24.0", "@typescript-eslint/parser": "^4.24.0",
"babel-jest": "^27.4.2",
"eslint": "^7.27.0", "eslint": "^7.27.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-config-standard-with-typescript": "^20.0.0", "eslint-config-standard-with-typescript": "^20.0.0",

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Canary CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Canary CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/typeorm-legacy-adapter/canary" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/typeorm-legacy-adapter/canary" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/typeorm-legacy-adapter" alt="@next-auth/typeorm-legacy-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/typeorm-legacy-adapter" alt="@next-auth/typeorm-legacy-adapter Version" />
</p> </p>

View File

@@ -3,9 +3,9 @@
"version": "1.0.3", "version": "1.0.3",
"description": "TypeORM (legacy) adapter for next-auth.", "description": "TypeORM (legacy) adapter for next-auth.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/adapters/issues"
}, },
"author": "Iain Collins", "author": "Iain Collins",
"contributors": [ "contributors": [

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" /> <img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/upstash-adapter" alt="Bundle Size"/> <img src="https://img.shields.io/bundlephobia/minzip/@next-auth/upstash-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/upstash-adapter" alt="@next-auth/upstash-adapter Version" /> <img src="https://img.shields.io/npm/v/@next-auth/upstash-adapter" alt="@next-auth/upstash-adapter Version" />
</p> </p>
@@ -80,7 +80,7 @@ export default NextAuth({
## Contributing ## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md). We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License ## License

View File

@@ -3,9 +3,9 @@
"version": "3.0.0", "version": "3.0.0",
"description": "Upstash adapter for next-auth. It uses Upstash's connectionless (HTTP based) Redis client.", "description": "Upstash adapter for next-auth. It uses Upstash's connectionless (HTTP based) Redis client.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/adapters",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/adapters/issues"
}, },
"author": "github.com/kay-is", "author": "github.com/kay-is",
"main": "dist/index.js", "main": "dist/index.js",
@@ -36,7 +36,6 @@
"devDependencies": { "devDependencies": {
"@next-auth/adapter-test": "workspace:^0.0.0", "@next-auth/adapter-test": "workspace:^0.0.0",
"@next-auth/tsconfig": "workspace:^0.0.0", "@next-auth/tsconfig": "workspace:^0.0.0",
"@types/uuid": "^8.3.3",
"@upstash/redis": "^1.0.1", "@upstash/redis": "^1.0.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"jest": "^27.4.3", "jest": "^27.4.3",

View File

@@ -25,6 +25,7 @@ module.exports = (api) => {
ignore: [ ignore: [
"../src/**/__tests__/**", "../src/**/__tests__/**",
"../src/adapters.ts", "../src/adapters.ts",
"../src/lib/types.ts",
"../src/providers/oauth-types.ts", "../src/providers/oauth-types.ts",
], ],
comments: false, comments: false,
@@ -32,7 +33,7 @@ module.exports = (api) => {
{ {
test: [ test: [
"../src/react/index.tsx", "../src/react/index.tsx",
"../src/utils/logger.ts", "../src/lib/logger.ts",
"../src/core/errors.ts", "../src/core/errors.ts",
"../src/client/**", "../src/client/**",
], ],

View File

@@ -1,7 +1,10 @@
/** @type {import('@jest/types').Config.InitialOptions} */ /** @type {import('@jest/types').Config.InitialOptions} */
module.exports = { module.exports = {
transform: { transform: {
"\\.(js|jsx|ts|tsx)$": ["@swc/jest", require("./swc.config")], "\\.(js|jsx|ts|tsx)$": [
"babel-jest",
{ configFile: "./config/babel.config.js" },
],
}, },
rootDir: "../src", rootDir: "../src",
setupFilesAfterEnv: ["../config/jest-setup.js"], setupFilesAfterEnv: ["../config/jest-setup.js"],

View File

@@ -1,13 +0,0 @@
/** @type {import('@jest/types').Config.InitialOptions} */
module.exports = {
transform: {
"\\.(js|jsx|ts|tsx)$": ["@swc/jest", require("./swc.config")],
},
rootDir: "..",
testMatch: ["**/*.test.ts"],
setupFilesAfterEnv: ["./config/jest-setup.js"],
watchPlugins: [
"jest-watch-typeahead/filename",
"jest-watch-typeahead/testname",
],
}

View File

@@ -1,17 +0,0 @@
module.exports = {
jsc: {
parser: {
syntax: "typescript",
tsx: true,
},
transform: {
react: {
runtime: "automatic",
pragma: "React.createElement",
pragmaFrag: "React.Fragment",
throwIfNamespace: true,
useBuiltins: true,
},
},
},
}

View File

@@ -1,6 +1,6 @@
{ {
"name": "next-auth", "name": "next-auth",
"version": "4.7.0", "version": "4.4.0",
"description": "Authentication for Next.js", "description": "Authentication for Next.js",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth.git", "repository": "https://github.com/nextauthjs/next-auth.git",
@@ -37,13 +37,11 @@
}, },
"scripts": { "scripts": {
"build": "pnpm clean && pnpm build:js && pnpm build:css", "build": "pnpm clean && pnpm build:js && pnpm build:css",
"clean": "rm -rf client css utils providers core jwt react next index.d.ts index.js adapters.d.ts middleware.d.ts middleware.js", "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": "pnpm clean && pnpm generate-providers && tsc && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
"build:css": "postcss --config config/postcss.config.js src/**/*.css --base src --dir . && node config/wrap-css.js", "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 .", "watch:css": "postcss --config config/postcss.config.js --watch src/**/*.css --base src --dir .",
"test:client": "jest --config ./config/jest.client.config.js", "test": "jest --config ./config/jest.config.js",
"test:core": "jest --config ./config/jest.core.config.js",
"test": "pnpm test:core && pnpm test:client",
"prepublishOnly": "pnpm build", "prepublishOnly": "pnpm build",
"generate-providers": "node ./config/generate-providers.js", "generate-providers": "node ./config/generate-providers.js",
"setup": "pnpm generate-providers", "setup": "pnpm generate-providers",
@@ -62,8 +60,7 @@
"index.js", "index.js",
"adapters.d.ts", "adapters.d.ts",
"middleware.d.ts", "middleware.d.ts",
"middleware.js", "middleware.js"
"utils"
], ],
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@@ -88,41 +85,38 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.17.10", "@babel/cli": "^7.16.0",
"@babel/core": "^7.18.2", "@babel/core": "^7.16.0",
"@babel/plugin-proposal-optional-catch-binding": "^7.16.7", "@babel/plugin-proposal-optional-catch-binding": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.18.2", "@babel/plugin-transform-runtime": "^7.16.4",
"@babel/preset-env": "^7.18.2", "@babel/preset-env": "^7.16.4",
"@babel/preset-react": "^7.17.12", "@babel/preset-react": "^7.16.0",
"@babel/preset-typescript": "^7.17.12", "@babel/preset-typescript": "^7.16.0",
"@next-auth/tsconfig": "workspace:^0.0.0", "@next-auth/tsconfig": "workspace:^0.0.0",
"@swc/core": "^1.2.198", "@testing-library/dom": "^8.11.3",
"@swc/jest": "^0.2.21", "@testing-library/jest-dom": "^5.16.1",
"@testing-library/dom": "^8.13.0", "@testing-library/react": "^12.1.2",
"@testing-library/jest-dom": "^5.16.4", "@testing-library/react-hooks": "^7.0.2",
"@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0",
"@testing-library/react-hooks": "^8.0.0", "@types/node": "^16.11.12",
"@testing-library/user-event": "^14.2.0",
"@types/jest": "^28.1.3",
"@types/node": "^17.0.42",
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@types/oauth": "^0.9.1", "@types/oauth": "^0.9.1",
"@types/react": "^18.0.2", "@types/react": "^17.0.37",
"@types/react-dom": "^18.0.5", "@types/react-dom": "^17.0.11",
"autoprefixer": "^10.4.7", "autoprefixer": "^10.4.0",
"babel-jest": "^27.4.2",
"babel-plugin-jsx-pragmatic": "^1.0.2", "babel-plugin-jsx-pragmatic": "^1.0.2",
"babel-preset-preact": "^2.0.0", "babel-preset-preact": "^2.0.0",
"cssnano": "^5.1.11", "cssnano": "^5.0.12",
"jest": "^28.1.1", "jest": "^27.4.3",
"jest-environment-jsdom": "^28.1.1", "jest-watch-typeahead": "^1.0.0",
"jest-watch-typeahead": "^1.1.0", "msw": "^0.36.3",
"msw": "^0.42.3", "next": "12.1.0",
"next": "12.1.7-canary.51", "postcss": "^8.4.12",
"postcss": "^8.4.14", "postcss-cli": "^9.0.2",
"postcss-cli": "^9.1.0",
"postcss-nested": "^5.0.6", "postcss-nested": "^5.0.6",
"react": "^18", "react": "^17.0.2",
"react-dom": "^18", "react-dom": "^17.0.2",
"whatwg-fetch": "^3.6.2" "whatwg-fetch": "^3.6.2"
}, },
"engines": { "engines": {

View File

@@ -52,7 +52,7 @@ export interface VerificationToken {
* - `deleteUser` * - `deleteUser`
* - `unlinkAccount` * - `unlinkAccount`
* *
* [Adapters Overview](https://next-auth.js.org/adapters/overview) | * [Community adapters](https://github.com/nextauthjs/adapters) |
* [Create a custom adapter](https://next-auth.js.org/tutorials/creating-a-database-adapter) * [Create a custom adapter](https://next-auth.js.org/tutorials/creating-a-database-adapter)
*/ */
export interface Adapter { export interface Adapter {

View File

@@ -2,11 +2,11 @@ import { useState } from "react"
import userEvent from "@testing-library/user-event" import userEvent from "@testing-library/user-event"
import { render, screen, waitFor } from "@testing-library/react" import { render, screen, waitFor } from "@testing-library/react"
import { server, mockCSRFToken } from "./helpers/mocks" import { server, mockCSRFToken } from "./helpers/mocks"
import logger from "../../utils/logger" import logger from "../../lib/logger"
import { getCsrfToken } from "../../react" import { getCsrfToken } from "../../react"
import { rest } from "msw" import { rest } from "msw"
jest.mock("../../utils/logger", () => ({ jest.mock("../../lib/logger", () => ({
__esModule: true, __esModule: true,
default: { default: {
warn: jest.fn(), warn: jest.fn(),

View File

@@ -3,10 +3,10 @@ import userEvent from "@testing-library/user-event"
import { render, screen, waitFor } from "@testing-library/react" import { render, screen, waitFor } from "@testing-library/react"
import { server, mockProviders } from "./helpers/mocks" import { server, mockProviders } from "./helpers/mocks"
import { getProviders } from "../../react" import { getProviders } from "../../react"
import logger from "../../utils/logger" import logger from "../../lib/logger"
import { rest } from "msw" import { rest } from "msw"
jest.mock("../../utils/logger", () => ({ jest.mock("../../lib/logger", () => ({
__esModule: true, __esModule: true,
default: { default: {
warn: jest.fn(), warn: jest.fn(),

View File

@@ -1,12 +1,12 @@
import { render, screen, waitFor } from "@testing-library/react" import { render, screen, waitFor } from "@testing-library/react"
import { rest } from "msw" import { rest } from "msw"
import { server, mockSession } from "./helpers/mocks" import { server, mockSession } from "./helpers/mocks"
import logger from "../../utils/logger" import logger from "../../lib/logger"
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import { getSession } from "../../react" import { getSession } from "../../react"
import { getBroadcastEvents } from "./helpers/utils" import { getBroadcastEvents } from "./helpers/utils"
jest.mock("../../utils/logger", () => ({ jest.mock("../../lib/logger", () => ({
__esModule: true, __esModule: true,
default: { default: {
warn: jest.fn(), warn: jest.fn(),

View File

@@ -1,7 +1,7 @@
import { useState } from "react" import { useState } from "react"
import userEvent from "@testing-library/user-event" import userEvent from "@testing-library/user-event"
import { render, screen, waitFor } from "@testing-library/react" import { render, screen, waitFor } from "@testing-library/react"
import logger from "../../utils/logger" import logger from "../../lib/logger"
import { import {
server, server,
mockCredentialsResponse, mockCredentialsResponse,
@@ -13,7 +13,7 @@ import { rest } from "msw"
const { location } = window const { location } = window
jest.mock("../../utils/logger", () => ({ jest.mock("../../lib/logger", () => ({
__esModule: true, __esModule: true,
default: { default: {
warn: jest.fn(), warn: jest.fn(),

View File

@@ -1,20 +1,20 @@
import logger, { setLogger } from "../utils/logger" import logger, { setLogger } from "../lib/logger"
import { detectHost } from "../utils/detect-host"
import * as routes from "./routes" import * as routes from "./routes"
import renderPage from "./pages" import renderPage from "./pages"
import { init } from "./init" import { init } from "./init"
import { assertConfig } from "./lib/assert" import { assertConfig } from "./lib/assert"
import { SessionStore } from "./lib/cookie" import { SessionStore } from "./lib/cookie"
import type { NextAuthAction, NextAuthOptions } from "./types" import type { NextAuthOptions } from "./types"
import type { NextAuthAction } from "../lib/types"
import type { Cookie } from "./lib/cookie" import type { Cookie } from "./lib/cookie"
import type { ErrorType } from "./pages/error" import type { ErrorType } from "./pages/error"
export interface RequestInternal { export interface IncomingRequest {
/** @default "http://localhost:3000" */ /** @default "http://localhost:3000" */
host?: string host?: string
method?: string method?: string
cookies?: Partial<Record<string, string>> cookies?: Record<string, string>
headers?: Record<string, any> headers?: Record<string, any>
query?: Record<string, any> query?: Record<string, any>
body?: Record<string, any> body?: Record<string, any>
@@ -39,55 +39,18 @@ export interface OutgoingResponse<
} }
export interface NextAuthHandlerParams { export interface NextAuthHandlerParams {
req: Request | RequestInternal req: IncomingRequest
options: NextAuthOptions options: NextAuthOptions
} }
async function getBody(req: Request): Promise<Record<string, any> | undefined> {
try {
return await req.json()
} catch {}
}
// TODO:
async function toInternalRequest(
req: RequestInternal | Request
): Promise<RequestInternal> {
if (req instanceof Request) {
const url = new URL(req.url)
// TODO: handle custom paths?
const nextauth = url.pathname.split("/").slice(3)
const headers = Object.fromEntries(req.headers.entries())
const query: Record<string, any> = Object.fromEntries(
url.searchParams.entries()
)
query.nextauth = nextauth
return {
action: nextauth[0] as NextAuthAction,
method: req.method,
headers,
body: await getBody(req),
cookies: {},
providerId: nextauth[1],
error: url.searchParams.get("error") ?? nextauth[1],
host: detectHost(headers["x-forwarded-host"] ?? headers.host),
query,
}
}
return req
}
export async function NextAuthHandler< export async function NextAuthHandler<
Body extends string | Record<string, any> | any[] Body extends string | Record<string, any> | any[]
>(params: NextAuthHandlerParams): Promise<OutgoingResponse<Body>> { >(params: NextAuthHandlerParams): Promise<OutgoingResponse<Body>> {
const { options: userOptions, req: incomingRequest } = params const { options: userOptions, req } = params
const req = await toInternalRequest(incomingRequest)
setLogger(userOptions.logger, userOptions.debug) setLogger(userOptions.logger, userOptions.debug)
const assertionResult = assertConfig({ options: userOptions, req }) const assertionResult = assertConfig(params)
if (typeof assertionResult === "string") { if (typeof assertionResult === "string") {
logger.warn(assertionResult) logger.warn(assertionResult)

View File

@@ -1,6 +1,7 @@
import { NextAuthOptions } from ".." import { NextAuthOptions } from ".."
import logger from "../utils/logger" import logger from "../lib/logger"
import parseUrl from "../utils/parse-url" import parseUrl from "../lib/parse-url"
import { InternalOptions } from "../lib/types"
import { adapterErrorHandler, eventsErrorHandler } from "./errors" import { adapterErrorHandler, eventsErrorHandler } from "./errors"
import parseProviders from "./lib/providers" import parseProviders from "./lib/providers"
import createSecret from "./lib/utils" import createSecret from "./lib/utils"
@@ -9,9 +10,7 @@ import * as jwt from "../jwt"
import { defaultCallbacks } from "./lib/default-callbacks" import { defaultCallbacks } from "./lib/default-callbacks"
import { createCSRFToken } from "./lib/csrf-token" import { createCSRFToken } from "./lib/csrf-token"
import { createCallbackUrl } from "./lib/callback-url" import { createCallbackUrl } from "./lib/callback-url"
import { RequestInternal } from "." import { IncomingRequest } from "."
import type { InternalOptions } from "./types"
interface InitParams { interface InitParams {
host?: string host?: string
@@ -24,7 +23,7 @@ interface InitParams {
csrfToken?: string csrfToken?: string
/** Is the incoming request a POST request? */ /** Is the incoming request a POST request? */
isPost: boolean isPost: boolean
cookies: RequestInternal["cookies"] cookies: IncomingRequest["cookies"]
} }
/** Initialize all internal options and cookies. */ /** Initialize all internal options and cookies. */

View File

@@ -6,11 +6,11 @@ import {
UnsupportedStrategy, UnsupportedStrategy,
InvalidCallbackUrl, InvalidCallbackUrl,
} from "../errors" } from "../errors"
import parseUrl from "../../utils/parse-url" import parseUrl from "../../lib/parse-url"
import { defaultCookies } from "./cookie" import { defaultCookies } from "./cookie"
import type { NextAuthHandlerParams, RequestInternal } from ".." import type { NextAuthHandlerParams } from ".."
import type { WarningCode } from "../../utils/logger" import type { WarningCode } from "../../lib/logger"
type ConfigError = type ConfigError =
| MissingAPIRoute | MissingAPIRoute
@@ -21,11 +21,9 @@ type ConfigError =
let twitterWarned = false let twitterWarned = false
function isValidHttpUrl(url: string, baseUrl: string) { function isValidHttpUrl(url: string) {
try { try {
return /^https?:/.test( return /^https?:/.test(new URL(url).protocol)
new URL(url, url.startsWith("/") ? baseUrl : undefined).protocol
)
} catch { } catch {
return false return false
} }
@@ -38,13 +36,11 @@ function isValidHttpUrl(url: string, baseUrl: string) {
* REVIEW: Make some of these and corresponding docs less Next.js specific? * REVIEW: Make some of these and corresponding docs less Next.js specific?
*/ */
export function assertConfig( export function assertConfig(
params: NextAuthHandlerParams & { params: NextAuthHandlerParams
req: RequestInternal
}
): ConfigError | WarningCode | undefined { ): ConfigError | WarningCode | undefined {
const { options, req } = params const { options, req } = params
// req.query isn't defined when asserting `unstable_getServerSession` for example // req.query isn't defined when asserting `getServerSession` for example
if (!req.query?.nextauth && !req.action) { if (!req.query?.nextauth && !req.action) {
return new MissingAPIRoute( return new MissingAPIRoute(
"Cannot find [...nextauth].{js,ts} in `/pages/api/auth`. Make sure the filename is written correctly." "Cannot find [...nextauth].{js,ts} in `/pages/api/auth`. Make sure the filename is written correctly."
@@ -61,24 +57,23 @@ export function assertConfig(
const callbackUrlParam = req.query?.callbackUrl as string | undefined const callbackUrlParam = req.query?.callbackUrl as string | undefined
const url = parseUrl(req.host) if (callbackUrlParam && !isValidHttpUrl(callbackUrlParam)) {
if (callbackUrlParam && !isValidHttpUrl(callbackUrlParam, url.base)) {
return new InvalidCallbackUrl( return new InvalidCallbackUrl(
`Invalid callback URL. Received: ${callbackUrlParam}` `Invalid callback URL. Received: ${callbackUrlParam}`
) )
} }
// This is below the callbackUrlParam check because it would obscure the error
if (!req.host) return "NEXTAUTH_URL" if (!req.host) return "NEXTAUTH_URL"
const url = parseUrl(req.host)
const { callbackUrl: defaultCallbackUrl } = defaultCookies( const { callbackUrl: defaultCallbackUrl } = defaultCookies(
options.useSecureCookies ?? url.base.startsWith("https://") options.useSecureCookies ?? url.base.startsWith("https://")
) )
const callbackUrlCookie = const callbackUrlCookie =
req.cookies?.[options.cookies?.callbackUrl?.name ?? defaultCallbackUrl.name] req.cookies?.[options.cookies?.callbackUrl?.name ?? defaultCallbackUrl.name]
if (callbackUrlCookie && !isValidHttpUrl(callbackUrlCookie, url.base)) { if (callbackUrlCookie && !isValidHttpUrl(callbackUrlCookie)) {
return new InvalidCallbackUrl( return new InvalidCallbackUrl(
`Invalid callback URL. Received: ${callbackUrlCookie}` `Invalid callback URL. Received: ${callbackUrlCookie}`
) )

View File

@@ -1,12 +1,11 @@
import { randomBytes, randomUUID } from "crypto"
import { AccountNotLinkedError } from "../errors" import { AccountNotLinkedError } from "../errors"
import { fromDate } from "./utils" import { fromDate } from "./utils"
import { randomBytes, randomUUID } from "crypto"
import type { InternalOptions } from "../types" import { InternalOptions } from "../../lib/types"
import type { AdapterSession, AdapterUser } from "../../adapters" import { AdapterSession, AdapterUser } from "../../adapters"
import type { JWT } from "../../jwt" import { JWT } from "../../jwt"
import type { Account, User } from "../.." import { Account, User } from "../.."
import type { SessionToken } from "./cookie" import { SessionToken } from "./cookie"
/** /**
* This function handles the complex flow of signing users in, and either creating, * This function handles the complex flow of signing users in, and either creating,
@@ -155,7 +154,7 @@ export default async function callbackHandler(params: {
// If the user is already signed in and the OAuth account isn't already associated // If the user is already signed in and the OAuth account isn't already associated
// with another user account then we can go ahead and link the accounts safely. // with another user account then we can go ahead and link the accounts safely.
await linkAccount({ ...account, userId: user.id }) await linkAccount({ ...account, userId: user.id })
await events.linkAccount?.({ user, account, profile }) await events.linkAccount?.({ user, account })
// As they are already signed in, we don't need to do anything after linking them // As they are already signed in, we don't need to do anything after linking them
return { session, user, isNewUser } return { session, user, isNewUser }
@@ -205,7 +204,7 @@ export default async function callbackHandler(params: {
await events.createUser?.({ user }) await events.createUser?.({ user })
await linkAccount({ ...account, userId: user.id }) await linkAccount({ ...account, userId: user.id })
await events.linkAccount?.({ user, account, profile }) await events.linkAccount?.({ user, account })
session = useJwtSession session = useJwtSession
? {} ? {}

View File

@@ -1,4 +1,4 @@
import type { InternalOptions } from "../types" import { InternalOptions } from "../../lib/types"
interface CreateCallbackUrlParams { interface CreateCallbackUrlParams {
options: InternalOptions options: InternalOptions

View File

@@ -120,7 +120,7 @@ export class SessionStore {
constructor( constructor(
option: CookieOption, option: CookieOption,
req: { req: {
cookies?: Partial<Record<string, string> | Map<string, string>> cookies?: Record<string, string>
headers?: Headers | IncomingHttpHeaders | Record<string, string> headers?: Headers | IncomingHttpHeaders | Record<string, string>
}, },
logger: LoggerInstance | Console logger: LoggerInstance | Console
@@ -128,16 +128,11 @@ export class SessionStore {
this.#logger = logger this.#logger = logger
this.#option = option this.#option = option
const { cookies } = req if (!req) return
const { name: cookieName } = option
if (cookies instanceof Map) { for (const name in req.cookies) {
for (const name of cookies.keys()) { if (name.startsWith(option.name)) {
if (name.startsWith(cookieName)) this.#chunks[name] = cookies.get(name) this.#chunks[name] = req.cookies[name]
}
} else {
for (const name in cookies) {
if (name.startsWith(cookieName)) this.#chunks[name] = cookies[name]
} }
} }
} }

View File

@@ -1,6 +1,5 @@
import { createHash, randomBytes } from "crypto" import { createHash, randomBytes } from "crypto"
import { InternalOptions } from "../../lib/types"
import type { InternalOptions } from "../types"
interface CreateCSRFTokenParams { interface CreateCSRFTokenParams {
options: InternalOptions options: InternalOptions

View File

@@ -1,6 +1,6 @@
import { randomBytes } from "crypto" import { randomBytes } from "crypto"
import { InternalOptions } from "../../../lib/types"
import { hashToken } from "../utils" import { hashToken } from "../utils"
import type { InternalOptions } from "../../types"
/** /**
* Starts an e-mail login flow, by generating a token, * Starts an e-mail login flow, by generating a token,

View File

@@ -4,8 +4,8 @@ import { createState } from "./state-handler"
import { createPKCE } from "./pkce-handler" import { createPKCE } from "./pkce-handler"
import type { AuthorizationParameters } from "openid-client" import type { AuthorizationParameters } from "openid-client"
import type { InternalOptions } from "../../types" import type { InternalOptions } from "../../../lib/types"
import type { RequestInternal } from "../.." import type { IncomingRequest } from "../.."
import type { Cookie } from "../cookie" import type { Cookie } from "../cookie"
/** /**
@@ -16,7 +16,7 @@ import type { Cookie } from "../cookie"
*/ */
export default async function getAuthorizationUrl(params: { export default async function getAuthorizationUrl(params: {
options: InternalOptions<"oauth"> options: InternalOptions<"oauth">
query: RequestInternal["query"] query: IncomingRequest["query"]
}) { }) {
const { options, query } = params const { options, query } = params
const { logger, provider } = options const { logger, provider } = options

View File

@@ -8,16 +8,16 @@ import { OAuthCallbackError } from "../../errors"
import type { CallbackParamsType } from "openid-client" import type { CallbackParamsType } from "openid-client"
import type { Account, LoggerInstance, Profile } from "../../.." import type { Account, LoggerInstance, Profile } from "../../.."
import type { OAuthChecks, OAuthConfig } from "../../../providers" import type { OAuthChecks, OAuthConfig } from "../../../providers"
import type { InternalOptions } from "../../types" import type { InternalOptions } from "../../../lib/types"
import type { RequestInternal, OutgoingResponse } from "../.." import type { IncomingRequest, OutgoingResponse } from "../.."
import type { Cookie } from "../cookie" import type { Cookie } from "../cookie"
export default async function oAuthCallback(params: { export default async function oAuthCallback(params: {
options: InternalOptions<"oauth"> options: InternalOptions<"oauth">
query: RequestInternal["query"] query: IncomingRequest["query"]
body: RequestInternal["body"] body: IncomingRequest["body"]
method: Required<RequestInternal>["method"] method: Required<IncomingRequest>["method"]
cookies: RequestInternal["cookies"] cookies: IncomingRequest["cookies"]
}): Promise<GetProfileResult & { cookies?: OutgoingResponse["cookies"] }> { }): Promise<GetProfileResult & { cookies?: OutgoingResponse["cookies"] }> {
const { options, query, body, method, cookies } = params const { options, query, body, method, cookies } = params
const { logger, provider } = options const { logger, provider } = options

View File

@@ -2,7 +2,7 @@
// We have the intentions to provide only minor fixes for this in the future. // We have the intentions to provide only minor fixes for this in the future.
import { OAuth } from "oauth" import { OAuth } from "oauth"
import type { InternalOptions } from "../../types" import { InternalOptions } from "src/lib/types"
/** /**
* Client supporting OAuth 1.x * Client supporting OAuth 1.x

View File

@@ -1,6 +1,5 @@
import { Issuer, custom } from "openid-client" import { Issuer, Client, custom } from "openid-client"
import type { Client } from "openid-client" import { InternalOptions } from "src/lib/types"
import type { InternalOptions } from "../../types"
/** /**
* NOTE: We can add auto discovery of the provider's endpoint * NOTE: We can add auto discovery of the provider's endpoint
@@ -13,9 +12,9 @@ export async function openidClient(
options: InternalOptions<"oauth"> options: InternalOptions<"oauth">
): Promise<Client> { ): Promise<Client> {
const provider = options.provider const provider = options.provider
if (provider.httpOptions) custom.setHttpOptionsDefaults(provider.httpOptions) if (provider.httpOptions) custom.setHttpOptionsDefaults(provider.httpOptions)
let issuer: Issuer let issuer: Issuer
if (provider.wellKnown) { if (provider.wellKnown) {
issuer = await Issuer.discover(provider.wellKnown) issuer = await Issuer.discover(provider.wellKnown)

View File

@@ -1,6 +1,6 @@
import * as jwt from "../../../jwt" import * as jwt from "../../../jwt"
import { generators } from "openid-client" import { generators } from "openid-client"
import type { InternalOptions } from "../../types" import type { InternalOptions } from "src/lib/types"
import type { Cookie } from "../cookie" import type { Cookie } from "../cookie"
const PKCE_CODE_CHALLENGE_METHOD = "S256" const PKCE_CODE_CHALLENGE_METHOD = "S256"

View File

@@ -1,6 +1,6 @@
import { generators } from "openid-client" import { generators } from "openid-client"
import type { InternalOptions } from "../../types" import type { InternalOptions } from "src/lib/types"
import type { Cookie } from "../cookie" import type { Cookie } from "../cookie"
const STATE_MAX_AGE = 60 * 15 // 15 minutes in seconds const STATE_MAX_AGE = 60 * 15 // 15 minutes in seconds

View File

@@ -1,8 +1,8 @@
import { merge } from "../../utils/merge" import { merge } from "../../lib/merge"
import type { InternalProvider } from "../types" import type { InternalProvider } from "../../lib/types"
import type { Provider } from "../../providers" import type { Provider } from "../../providers"
import type { InternalUrl } from "../../utils/parse-url" import type { InternalUrl } from "../../lib/parse-url"
/** /**
* Adds `signinUrl` and `callbackUrl` to each provider * Adds `signinUrl` and `callbackUrl` to each provider

View File

@@ -1,8 +1,7 @@
import { createHash } from "crypto" import { createHash } from "crypto"
import { NextAuthOptions } from "../.."
import type { NextAuthOptions } from "../.." import { InternalOptions } from "../../lib/types"
import type { InternalOptions } from "../types" import { InternalUrl } from "../../lib/parse-url"
import type { InternalUrl } from "../../utils/parse-url"
/** /**
* Takes a number in seconds and returns the date in the future. * Takes a number in seconds and returns the date in the future.

View File

@@ -1,5 +1,5 @@
import { Theme } from "../.." import { Theme } from "../.."
import { InternalUrl } from "../../utils/parse-url" import { InternalUrl } from "../../lib/parse-url"
/** /**
* The following errors are passed as error query parameters to the default or overridden error page. * The following errors are passed as error query parameters to the default or overridden error page.

View File

@@ -5,13 +5,13 @@ import VerifyRequestPage from "./verify-request"
import ErrorPage from "./error" import ErrorPage from "./error"
import css from "../../css" import css from "../../css"
import type { InternalOptions } from "../types" import type { InternalOptions } from "../../lib/types"
import type { RequestInternal, OutgoingResponse } from ".." import type { IncomingRequest, OutgoingResponse } from ".."
import type { Cookie } from "../lib/cookie" import type { Cookie } from "../lib/cookie"
import type { ErrorType } from "./error" import type { ErrorType } from "./error"
type RenderPageParams = { type RenderPageParams = {
query?: RequestInternal["query"] query?: IncomingRequest["query"]
cookies?: Cookie[] cookies?: Cookie[]
} & Partial< } & Partial<
Pick< Pick<

View File

@@ -1,4 +1,5 @@
import type { InternalProvider, Theme } from "../types" import { Theme } from "../.."
import { InternalProvider } from "../../lib/types"
/** /**
* The following errors are passed as error query parameters to the default or overridden sign-in page. * The following errors are passed as error query parameters to the default or overridden sign-in page.

View File

@@ -1,5 +1,5 @@
import { Theme } from "../.." import { Theme } from "../.."
import { InternalUrl } from "../../utils/parse-url" import { InternalUrl } from "../../lib/parse-url"
export interface SignoutProps { export interface SignoutProps {
url: InternalUrl url: InternalUrl
@@ -12,17 +12,15 @@ export default function SignoutPage(props: SignoutProps) {
return ( return (
<div className="signout"> <div className="signout">
{theme.brandColor && ( { theme.brandColor && <style
<style dangerouslySetInnerHTML={{
dangerouslySetInnerHTML={{ __html: `
__html: `
:root { :root {
--brand-color: ${theme.brandColor} --brand-color: ${theme.brandColor}
} }
`, `,
}} }}
/> /> }
)}
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />} {theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<div className="card"> <div className="card">
<h1>Signout</h1> <h1>Signout</h1>

View File

@@ -1,5 +1,5 @@
import { Theme } from "../.." import { Theme } from "../.."
import { InternalUrl } from "../../utils/parse-url" import { InternalUrl } from "../../lib/parse-url"
interface VerifyRequestPageProps { interface VerifyRequestPageProps {
url: InternalUrl url: InternalUrl
@@ -11,17 +11,15 @@ export default function VerifyRequestPage(props: VerifyRequestPageProps) {
return ( return (
<div className="verify-request"> <div className="verify-request">
{theme.brandColor && ( { theme.brandColor && <style
<style dangerouslySetInnerHTML={{
dangerouslySetInnerHTML={{ __html: `
__html: `
:root { :root {
--brand-color: ${theme.brandColor} --brand-color: ${theme.brandColor}
} }
`, `,
}} }}
/> /> }
)}
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />} {theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<div className="card"> <div className="card">
<h1>Check your email</h1> <h1>Check your email</h1>

View File

@@ -2,19 +2,19 @@ import oAuthCallback from "../lib/oauth/callback"
import callbackHandler from "../lib/callback-handler" import callbackHandler from "../lib/callback-handler"
import { hashToken } from "../lib/utils" import { hashToken } from "../lib/utils"
import type { InternalOptions } from "../types" import type { InternalOptions } from "../../lib/types"
import type { RequestInternal, OutgoingResponse } from ".." import type { IncomingRequest, OutgoingResponse } from ".."
import type { Cookie, SessionStore } from "../lib/cookie" import type { Cookie, SessionStore } from "../lib/cookie"
import type { User } from "../.." import type { User } from "../.."
/** Handle callbacks from login services */ /** Handle callbacks from login services */
export default async function callback(params: { export default async function callback(params: {
options: InternalOptions<"oauth" | "credentials" | "email"> options: InternalOptions<"oauth" | "credentials" | "email">
query: RequestInternal["query"] query: IncomingRequest["query"]
method: Required<RequestInternal>["method"] method: Required<IncomingRequest>["method"]
body: RequestInternal["body"] body: IncomingRequest["body"]
headers: RequestInternal["headers"] headers: IncomingRequest["headers"]
cookies: RequestInternal["cookies"] cookies: IncomingRequest["cookies"]
sessionStore: SessionStore sessionStore: SessionStore
}): Promise<OutgoingResponse> { }): Promise<OutgoingResponse> {
const { options, query, body, method, headers, sessionStore } = params const { options, query, body, method, headers, sessionStore } = params

View File

@@ -1,5 +1,5 @@
import type { OutgoingResponse } from ".." import { OutgoingResponse } from ".."
import type { InternalProvider } from "../types" import { InternalProvider } from "../../lib/types"
export interface PublicProvider { export interface PublicProvider {
id: string id: string

View File

@@ -1,7 +1,7 @@
import { fromDate } from "../lib/utils" import { fromDate } from "../lib/utils"
import type { Adapter } from "../../adapters" import type { Adapter } from "../../adapters"
import type { InternalOptions } from "../types" import type { InternalOptions } from "../../lib/types"
import type { OutgoingResponse } from ".." import type { OutgoingResponse } from ".."
import type { Session } from "../.." import type { Session } from "../.."
import type { SessionStore } from "../lib/cookie" import type { SessionStore } from "../lib/cookie"

View File

@@ -1,14 +1,14 @@
import getAuthorizationUrl from "../lib/oauth/authorization-url" import getAuthorizationUrl from "../lib/oauth/authorization-url"
import emailSignin from "../lib/email/signin" import emailSignin from "../lib/email/signin"
import type { RequestInternal, OutgoingResponse } from ".." import { IncomingRequest, OutgoingResponse } from ".."
import type { InternalOptions } from "../types" import { InternalOptions } from "../../lib/types"
import type { Account, User } from "../.." import { Account, User } from "../.."
/** Handle requests to /api/auth/signin */ /** Handle requests to /api/auth/signin */
export default async function signin(params: { export default async function signin(params: {
options: InternalOptions<"oauth" | "email"> options: InternalOptions<"oauth" | "email">
query: RequestInternal["query"] query: IncomingRequest["query"]
body: RequestInternal["body"] body: IncomingRequest["body"]
}): Promise<OutgoingResponse> { }): Promise<OutgoingResponse> {
const { options, query, body } = params const { options, query, body } = params
const { url, adapter, callbacks, logger, provider } = options const { url, adapter, callbacks, logger, provider } = options

View File

@@ -1,5 +1,5 @@
import type { Adapter } from "../../adapters" import type { Adapter } from "../../adapters"
import type { InternalOptions } from "../types" import type { InternalOptions } from "../../lib/types"
import type { OutgoingResponse } from ".." import type { OutgoingResponse } from ".."
import type { SessionStore } from "../lib/cookie" import type { SessionStore } from "../lib/cookie"

View File

@@ -1,21 +1,10 @@
import type { Adapter } from "../adapters" import type { Adapter } from "../adapters"
import type { import type { Provider, CredentialInput, ProviderType } from "../providers"
Provider,
CredentialInput,
ProviderType,
OAuthConfig,
EmailConfig,
CredentialsConfig,
} from "../providers"
import type { TokenSetParameters } from "openid-client" import type { TokenSetParameters } from "openid-client"
import type { JWT, JWTOptions } from "../jwt" import type { JWT, JWTOptions } from "../jwt"
import type { LoggerInstance } from "../utils/logger" import type { LoggerInstance } from "../lib/logger"
import type { CookieSerializeOptions } from "cookie" import type { CookieSerializeOptions } from "cookie"
import type { NextApiRequest, NextApiResponse } from "next"
import type { InternalUrl } from "../utils/parse-url"
export type Awaitable<T> = T | PromiseLike<T> export type Awaitable<T> = T | PromiseLike<T>
export type { LoggerInstance } export type { LoggerInstance }
@@ -117,7 +106,7 @@ export interface NextAuthOptions {
* * **Required**: *No* * * **Required**: *No*
* *
* [Documentation](https://next-auth.js.org/configuration/options#adapter) | * [Documentation](https://next-auth.js.org/configuration/options#adapter) |
* [Adapters Overview](https://next-auth.js.org/adapters/overview) * [Community adapters](https://github.com/nextauthjs/adapters)
*/ */
adapter?: Adapter adapter?: Adapter
/** /**
@@ -389,11 +378,7 @@ export interface EventCallbacks {
signOut: (message: { session: Session; token: JWT }) => Awaitable<void> signOut: (message: { session: Session; token: JWT }) => Awaitable<void>
createUser: (message: { user: User }) => Awaitable<void> createUser: (message: { user: User }) => Awaitable<void>
updateUser: (message: { user: User }) => Awaitable<void> updateUser: (message: { user: User }) => Awaitable<void>
linkAccount: (message: { linkAccount: (message: { user: User; account: Account }) => Awaitable<void>
user: User
account: Account
profile: User
}) => Awaitable<void>
/** /**
* The message object will contain one of these depending on * The message object will contain one of these depending on
* if you use JWT or database persisted sessions: * if you use JWT or database persisted sessions:
@@ -486,71 +471,3 @@ export interface DefaultUser {
* [`profile` OAuth provider callback](https://next-auth.js.org/configuration/providers#using-a-custom-provider) * [`profile` OAuth provider callback](https://next-auth.js.org/configuration/providers#using-a-custom-provider)
*/ */
export interface User extends Record<string, unknown>, DefaultUser {} export interface User extends Record<string, unknown>, DefaultUser {}
// Below are types that are only supposed be used by next-auth internally
/** @internal */
export type InternalProvider<T extends ProviderType = any> = (T extends "oauth"
? OAuthConfig<any>
: T extends "email"
? EmailConfig
: T extends "credentials"
? CredentialsConfig
: never) & {
signinUrl: string
callbackUrl: string
}
export type NextAuthAction =
| "providers"
| "session"
| "csrf"
| "signin"
| "signout"
| "callback"
| "verify-request"
| "error"
| "_log"
/** @internal */
export interface InternalOptions<T extends ProviderType = any> {
providers: InternalProvider[]
/**
* Parsed from `NEXTAUTH_URL` or `x-forwarded-host` on Vercel.
* @default "http://localhost:3000/api/auth"
*/
url: InternalUrl
action: NextAuthAction
provider: T extends string
? InternalProvider<T>
: InternalProvider<T> | undefined
csrfToken?: string
csrfTokenVerified?: boolean
secret: string
theme: Theme
debug: boolean
logger: LoggerInstance
session: Required<SessionOptions>
pages: Partial<PagesOptions>
jwt: JWTOptions
events: Partial<EventCallbacks>
adapter?: Adapter
callbacks: CallbacksOptions
cookies: CookiesOptions
callbackUrl: string
}
/** @internal */
export interface NextAuthRequest extends NextApiRequest {
options: InternalOptions
}
/** @internal */
export type NextAuthResponse<T = any> = NextApiResponse<T>
/** @internal */
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
export type NextAuthApiHandler<Result = void, Response = any> = (
req: NextAuthRequest,
res: NextAuthResponse<Response>
) => Awaitable<Result>

View File

@@ -1,6 +1,6 @@
export * from "./core/types" export * from "./core/types"
export type { RequestInternal, OutgoingResponse } from "./core" export type { IncomingRequest, OutgoingResponse } from "./core"
export * from "./next" export * from "./next"
export { default } from "./next" export { default } from "./next"

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