Compare commits

..

61 Commits

Author SHA1 Message Date
Balázs Orbán
54876744fe Merge branch 'feat/nextjs-auth' into feat/nextjs-auth-example-app 2023-05-01 12:52:34 +02:00
Balázs Orbán
28cbb3aac5 rename @auth/nextjs to next-auth 2023-05-01 12:41:12 +02:00
Balázs Orbán
ac0ca51278 Merge branch 'main' into feat/nextjs-auth 2023-05-01 11:32:56 +02:00
Balázs Orbán
5400645221 chore: improve errors, add more docs (#7415)
* JWT Token -> JWT

* document some errors

* improve errors, docs
2023-05-01 10:32:20 +01:00
Balázs Orbán
d739e8e04e feat(adapters): add Account mapping before database write (#7369)
* feat: map Account before saving to database

* document `acconut()`, explain default behaviour

* generate `expires_at` based on `expires_in`

Fixes #6538

* rename

* strip undefined on `defaultProfile`

* don't forward defaults to account callback

* improve internal namings, types, docs
2023-04-30 12:25:26 +01:00
Victor
c2eb9b3ad4 fix(docs): fix default maxAge formula (#7406) 2023-04-30 10:34:05 +02:00
Balázs Orbán
4f54840014 bump to next@canary 2023-04-28 12:59:48 +02:00
Balázs Orbán
d938333750 Merge branch 'main' into feat/nextjs-auth 2023-04-28 12:29:49 +02:00
ndom91
d837dfaea1 fix: app router style updates for example app 2023-04-27 14:17:03 +02:00
ndom91
a99f4bd8c6 fix: remove dependency on 'next-auth' from example package.json 2023-04-27 13:39:06 +02:00
Balázs Orbán
a96b8597b1 Merge branch 'main' into feat/nextjs-auth 2023-04-27 11:07:20 +02:00
Balázs Orbán
29ce4cb4d4 fix imports 2023-04-27 10:58:02 +02:00
Balázs Orbán
da40242e48 bump next 2023-04-27 10:57:56 +02:00
Balázs Orbán
3f211e7ad0 Merge branch 'main' into feat/nextjs-auth 2023-04-27 10:14:56 +02:00
ndom91
5f369b0981 fix: update README.md to '@auth/nextjs' 2023-04-26 16:25:52 +02:00
ndom91
4a056c774f fix: rm 'pages' dir 2023-04-26 16:25:41 +02:00
ndom91
038b9bccad fix: remove unnecessary header links in example app 2023-04-25 19:05:33 +02:00
ndom91
dfb20849c5 fix: pages/server page on dev and example app 2023-04-25 19:05:11 +02:00
ndom91
4a7a7ab757 fix: minor .env.local.example update 2023-04-25 18:44:05 +02:00
ndom91
f94b604397 fix: move pages to backup position in example app 2023-04-25 18:41:28 +02:00
ndom91
535f9276f6 feat: move nextjs example app to new primitives 2023-04-25 18:37:23 +02:00
Balázs Orbán
cd2872de89 Merge branch 'main' into feat/nextjs-auth 2023-04-24 12:00:11 +03:00
Balázs Orbán
2de2dc9bb3 set version 2023-04-21 12:38:15 +02:00
Balázs Orbán
6f96004d75 tweak docs 2023-04-21 12:37:21 +02:00
Balázs Orbán
f834bc2a99 mark getCsrfToken as internal 2023-04-21 12:35:19 +02:00
Balázs Orbán
551dcbd2d5 show client api in sidebar 2023-04-21 12:34:04 +02:00
Balázs Orbán
316b344930 remove gitignored file 2023-04-21 12:31:07 +02:00
Balázs Orbán
97ff6406cb Merge branch 'main' into feat/nextjs-auth 2023-04-21 12:30:48 +02:00
Balázs Orbán
1b9559fbb1 add docs, fix types 2023-04-21 13:21:55 +03:00
Balázs Orbán
27864eea2f handle JSX 2023-04-21 11:46:16 +02:00
Balázs Orbán
e5f18e3266 add @auth/nextjs/client 2023-04-21 11:46:08 +02:00
Balázs Orbán
47eec2c498 update pages 2023-04-21 11:45:05 +02:00
Balázs Orbán
77bba4ada7 App Router updates 2023-04-21 11:40:46 +02:00
Balázs Orbán
f081fcd31d remove supabase pages 2023-04-21 11:39:17 +02:00
Balázs Orbán
5f079930cc update imports 2023-04-21 11:38:45 +02:00
Balázs Orbán
4cc4b45e52 bump package versions 2023-04-21 11:37:37 +02:00
Balázs Orbán
c0cfb13c88 Merge branch 'main' into feat/nextjs-auth 2023-04-20 11:51:37 +02:00
Balázs Orbán
537112a306 Merge branch 'main' into feat/nextjs-auth 2023-04-19 10:57:14 +02:00
Balázs Orbán
6663003c7c remove crypto polyfill 2023-04-18 13:57:16 +02:00
Balázs Orbán
68559941a5 support __Secure session token cookie 2023-04-18 13:50:47 +02:00
Balázs Orbán
cec1fd753e ignore next-2 2023-04-18 10:40:26 +02:00
Balázs Orbán
c97c40c9cb fix types, default envs 2023-04-18 10:29:06 +02:00
Balázs Orbán
defc2233be update session expiry 2023-04-14 13:50:12 +02:00
Balázs Orbán
e0450c9d52 remove log 2023-04-14 12:19:28 +02:00
Balázs Orbán
04021c6d47 respect AUTH_SECRET 2023-04-14 12:14:17 +02:00
Balázs Orbán
210d28b6b0 add lib to package files 2023-04-14 12:14:07 +02:00
Balázs Orbán
fcd9bfc6f8 update node types 2023-04-14 12:01:56 +02:00
Balázs Orbán
0a027cf35d update deps/lock file 2023-04-14 11:58:32 +02:00
Balázs Orbán
47ac2e94ce document source code 2023-04-14 11:43:26 +02:00
Balázs Orbán
30e3672708 generate docs 2023-04-14 11:42:47 +02:00
Balázs Orbán
635a9b0c50 update dev app 2023-04-14 11:41:15 +02:00
Balázs Orbán
510b9764f5 add session rotation 2023-04-13 14:44:06 +02:00
Balázs Orbán
7329725702 update deps 2023-04-13 14:43:48 +02:00
Balázs Orbán
23ea9428e0 update dev app 2023-04-13 14:43:25 +02:00
Balázs Orbán
319f7af866 Merge branch 'main' into feat/nextjs-auth 2023-04-12 12:41:41 +02:00
Balázs Orbán
58be169b10 update dev app 2023-04-07 12:51:41 +02:00
Balázs Orbán
c87fdd9060 add implicit env reading, simplified API 2023-04-07 12:51:34 +02:00
Balázs Orbán
28263f52bd Merge branch 'main' into feat/nextjs-auth 2023-04-07 12:39:10 +02:00
Balázs Orbán
27869b70b8 Merge branch 'main' into feat/nextjs-auth 2023-04-01 14:39:34 +02:00
Balázs Orbán
7af7ca4d1c chore: bump turbo and pnpm 2023-03-31 15:50:44 +02:00
Balázs Orbán
30948fbada chore: update configs, dependencies 2023-03-30 18:13:07 +02:00
326 changed files with 2994 additions and 20060 deletions

View File

@@ -29,10 +29,10 @@ body:
- "@next-auth/mongodb-adapter" - "@next-auth/mongodb-adapter"
- "@next-auth/neo4j-adapter" - "@next-auth/neo4j-adapter"
- "@next-auth/pouchdb-adapter" - "@next-auth/pouchdb-adapter"
- "@auth/prisma-adapter" - "@next-auth/prisma-adapter"
- "@next-auth/sequelize-adapter" - "@next-auth/sequelize-adapter"
- "@next-auth/supabase-adapter" - "@next-auth/supabase-adapter"
- "@auth/typeorm-adapter" - "@next-auth/typeorm-legacy-adapter"
- "@next-auth/upstash-redis-adapter" - "@next-auth/upstash-redis-adapter"
- "@next-auth/xata-adapter" - "@next-auth/xata-adapter"
validations: validations:

View File

@@ -25,7 +25,7 @@ pouchdb:
- "@next-auth/pouchdb-adapter" - "@next-auth/pouchdb-adapter"
prisma: prisma:
- "@auth/prisma-adapter" - "@next-auth/prisma-adapter"
sequelize: sequelize:
- "@next-auth/sequelize-adapter" - "@next-auth/sequelize-adapter"
@@ -33,8 +33,8 @@ sequelize:
supabase: supabase:
- "@next-auth/supabase-adapter" - "@next-auth/supabase-adapter"
typeorm: typeorm-legacy:
- "@auth/typeorm-adapter" - "@next-auth/typeorm-legacy-adapter"
upstash-redis: upstash-redis:
- "@next-auth/upstash-redis-adapter" - "@next-auth/upstash-redis-adapter"

View File

@@ -21,6 +21,6 @@ solidjs: ["packages/frameworks-solid-start/**/*"]
supabase: ["packages/adapter-supabase/**/*"] supabase: ["packages/adapter-supabase/**/*"]
svelte: ["packages/frameworks-sveltekit/**/*"] svelte: ["packages/frameworks-sveltekit/**/*"]
test: ["**test**/*"] test: ["**test**/*"]
typeorm: ["packages/adapter-typeorm/**/*"] typeorm-legacy: ["packages/adapter-typeorm-legacy/**/*"]
upstash-redis: ["packages/adapter-upstash-redis/**/*"] upstash-redis: ["packages/adapter-upstash-redis/**/*"]
xata: ["packages/adapter-xata/**/*"] xata: ["packages/adapter-xata/**/*"]

View File

@@ -5,15 +5,14 @@ const core = require("@actions/core")
try { try {
const packageJSONPath = path.join( const packageJSONPath = path.join(
process.cwd(), process.cwd(),
`packages/${process.env.PACKAGE_PATH || "next-auth"}/package.json` "packages/next-auth/package.json"
) )
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, "utf8")) const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, "utf8"))
const sha8 = process.env.GITHUB_SHA.substring(0, 8) const sha8 = process.env.GITHUB_SHA.substring(0, 8)
const prefix = "0.0.0-" const prNumber = process.env.PR_NUMBER
const pr = process.env.PR_NUMBER
const source = pr ? `pr.${pr}` : "manual" const packageVersion = `0.0.0-pr.${prNumber}.${sha8}`
const packageVersion = `${prefix}${source}.${sha8}`
packageJSON.version = packageVersion packageJSON.version = packageVersion
core.setOutput("version", packageVersion) core.setOutput("version", packageVersion)
fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON)) fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON))

View File

@@ -8,54 +8,6 @@ on:
- next - next
- 3.x - 3.x
pull_request: pull_request:
# TODO: Support latest releases
workflow_dispatch:
inputs:
name:
type: choice
description: Package name (npm)
options:
- "@auth/core"
- "@auth/nextjs"
- "@auth/dgraph-adapter"
- "@auth/drizzle-adapter"
- "@auth/dynamodb-adapter"
- "@auth/fauna-adapter"
- "@auth/firebase-adapter"
- "@auth/mikro-orm-adapter"
- "@auth/mongodb-adapter"
- "@auth/neo4j-adapter"
- "@auth/pouchdb-adapter"
- "@auth/prisma-adapter"
- "@auth/sequelize-adapter"
- "@auth/supabase-adapter"
- "@auth/typeorm-adapter"
- "@auth/upstash-redis-adapter"
- "@auth/xata-adapter"
- "next-auth"
# TODO: Infer from package name
path:
type: choice
description: Directory name (packages/*)
options:
- "core"
- "frameworks-nextjs"
- "adapter-dgraph"
- "adapter-drizzle"
- "adapter-dynamodb"
- "adapter-fauna"
- "adapter-firebase"
- "adapter-mikro-orm"
- "adapter-mongodb"
- "adapter-neo4j"
- "adapter-pouchdb"
- "adapter-prisma"
- "adapter-sequelize"
- "adapter-supabase"
- "adapter-typeorm"
- "adapter-upstash-redis"
- "adapter-xata"
- "next-auth"
jobs: jobs:
test: test:
@@ -72,7 +24,6 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Run tests - name: Run tests
@@ -122,7 +73,6 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Publish to npm and GitHub - name: Publish to npm and GitHub
@@ -147,7 +97,6 @@ jobs:
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Determine version - name: Determine version
@@ -173,36 +122,3 @@ jobs:
env: env:
VERSION: ${{ steps.determine-version.outputs.version }} VERSION: ${{ steps.determine-version.outputs.version }}
GITHUB_TOKEN: ${{ secrets.GH_PAT }} GITHUB_TOKEN: ${{ secrets.GH_PAT }}
release-manual:
name: Publish manually
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' }}
steps:
- name: Init
uses: actions/checkout@v3
- name: Install pnpm
uses: pnpm/action-setup@v2.2.4
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Determine version
uses: ./.github/version-pr
id: determine-version
env:
PACKAGE_PATH: ${{ github.event.inputs.path }}
- name: Publish to npm
run: |
pnpm build
cd packages/$PACKAGE_PATH
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
pnpm publish --no-git-checks --access public --tag experimental
echo "🎉 Experimental release published 📦️ on npm: https://npmjs.com/package/${{ github.event.inputs.name }}/v/${{ env.VERSION }}"
echo "Install via: pnpm add ${{ github.event.inputs.name }}@${{ env.VERSION }}"
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
PACKAGE_PATH: ${{ github.event.inputs.path }}
VERSION: ${{ steps.determine-version.outputs.version }}

13
.gitignore vendored
View File

@@ -26,15 +26,7 @@ dist
# Generated files # Generated files
.docusaurus .docusaurus
.cache-loader .cache-loader
packages/next-auth/providers
packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/client
packages/next-auth/css
packages/next-auth/utils
packages/next-auth/core
packages/next-auth/jwt
packages/next-auth/react
packages/next-auth/next
packages/*/*.js packages/*/*.js
packages/*/*.d.ts packages/*/*.d.ts
packages/*/*.d.ts.map packages/*/*.d.ts.map
@@ -85,7 +77,10 @@ packages/core/providers
packages/core/src/lib/pages/styles.ts packages/core/src/lib/pages/styles.ts
docs/docs/reference/core docs/docs/reference/core
docs/docs/reference/sveltekit docs/docs/reference/sveltekit
docs/docs/reference/next-auth
# Next.js
packages/next-auth/lib
# SvelteKit # SvelteKit
packages/frameworks-sveltekit/index.* packages/frameworks-sveltekit/index.*

View File

@@ -40,10 +40,6 @@ packages/core/src/lib/pages/styles.ts
packages/frameworks-sveltekit/package packages/frameworks-sveltekit/package
packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-* packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*
# next-auth
packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/css/index.css
# Adapters # Adapters
.branches .branches

View File

@@ -1,8 +1,8 @@
{ {
"files.exclude": { "files.exclude": {
"packages/core/{lib,providers,*.js,*.d.ts,*.d.ts.map}": true, "packages/core/{lib,providers,*.js,*.d.ts*}": true,
"packages/next-auth/{client,core,css,jwt,next,providers,react,utils,*.js,*.d.ts}": true "packages/next-auth/{lib,*.js,*.d.ts*}": true,
}, },
"typescript.tsdk": "node_modules/typescript/lib", "typescript.tsdk": "node_modules/typescript/lib",
"openInGitHub.remote.branch": "main" "openInGitHub.remote.branch": "main"
} }

View File

@@ -15,9 +15,9 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@next-auth/fauna-adapter": "workspace:*", "@next-auth/fauna-adapter": "workspace:*",
"@auth/prisma-adapter": "workspace:*", "@next-auth/prisma-adapter": "workspace:*",
"@next-auth/supabase-adapter": "workspace:*", "@next-auth/supabase-adapter": "workspace:*",
"@auth/typeorm-adapter": "workspace:*", "@next-auth/typeorm-legacy-adapter": "workspace:*",
"@prisma/client": "^3", "@prisma/client": "^3",
"@supabase/supabase-js": "^2.0.5", "@supabase/supabase-js": "^2.0.5",
"faunadb": "^4", "faunadb": "^4",

View File

@@ -37,7 +37,7 @@ import WorkOS from "next-auth/providers/workos"
// // Prisma // // Prisma
// import { PrismaClient } from "@prisma/client" // import { PrismaClient } from "@prisma/client"
// import { PrismaAdapter } from "@auth/prisma-adapter" // import { PrismaAdapter } from "@next-auth/prisma-adapter"
// const client = globalThis.prisma || new PrismaClient() // const client = globalThis.prisma || new PrismaClient()
// if (process.env.NODE_ENV !== "production") globalThis.prisma = client // if (process.env.NODE_ENV !== "production") globalThis.prisma = client
// const adapter = PrismaAdapter(client) // const adapter = PrismaAdapter(client)
@@ -51,8 +51,8 @@ import WorkOS from "next-auth/providers/workos"
// const adapter = FaunaAdapter(client) // const adapter = FaunaAdapter(client)
// // TypeORM // // TypeORM
// import { TypeORMAdapter } from "@auth/typeorm-adapter" // import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
// const adapter = TypeORMAdapter({ // const adapter = TypeORMLegacyAdapter({
// type: "sqlite", // type: "sqlite",
// name: "next-auth-test-memory", // name: "next-auth-test-memory",
// database: "./typeorm/dev.db", // database: "./typeorm/dev.db",

View File

@@ -0,0 +1,3 @@
import { handlers } from "auth"
export const { GET, POST } = handlers
export const runtime = "edge"

View File

@@ -0,0 +1,10 @@
import { auth } from "auth"
import { NextResponse } from "next/server"
export const GET = auth(function GET(req) {
if (req.auth) {
return NextResponse.json(req.auth)
}
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
})

View File

@@ -1,6 +1,37 @@
import { unstable_getServerSession } from "next-auth/next" import { auth } from "auth"
import { cookies, headers } from "next/headers"
function SignIn({ id, children }: any) {
const $cookies = cookies()
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
return (
<form action={`/api/auth/signin/${id}`} method="post">
<button type="submit">{children}</button>
<input type="hidden" name="csrfToken" value={csrfToken} />
</form>
)
}
function SignOut({ children }: any) {
const $cookies = cookies()
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
return (
<form action="/api/auth/signout" method="post">
<button type="submit">{children}</button>
<input type="hidden" name="csrfToken" value={csrfToken} />
</form>
)
}
export default async function Page() { export default async function Page() {
const session = await unstable_getServerSession() const session = await auth(headers())
return <pre>{JSON.stringify(session, null, 2)}</pre> if (session) {
return (
<>
<pre>{JSON.stringify(session, null, 2)}</pre>
<SignOut>Sign out</SignOut>
</>
)
}
return <SignIn id="github">Sign in with github</SignIn>
} }

21
apps/dev/nextjs/auth.ts Normal file
View File

@@ -0,0 +1,21 @@
import { NextAuth } from "next-auth"
import GitHub from "@auth/core/providers/github"
export const { handlers, auth } = NextAuth({
providers: [GitHub],
callbacks: {
async authorized({ request, auth }) {
// if (request.method === "POST") {
// const [, token] = request.headers.get("Authorization")?.split(" ")
// const valid = validateToken(token)
// // If the request has a valid auth token, it is authorized
// if (valid) return true
// return NextResponse.json("Invalid auth token", { status: 401 })
// }
// Logged in users are authorized, otherwise, will redirect to login
// You could also return a custom redirect instead of the sign-in page
return !!auth
},
},
})

View File

@@ -1,6 +1,6 @@
import Link from "next/link" import Link from "next/link"
import styles from "./footer.module.css" import styles from "./footer.module.css"
import packageJSON from "package.json" import packageJSON from "next-auth/package.json"
export default function Footer() { export default function Footer() {
return ( return (

View File

@@ -76,12 +76,6 @@ export default function Header() {
<li className={styles.navItem}> <li className={styles.navItem}>
<Link href="/middleware-protected">Middleware protected</Link> <Link href="/middleware-protected">Middleware protected</Link>
</li> </li>
<li className={styles.navItem}>
<Link href="/supabase-client-rls">Supabase RLS</Link>
</li>
<li className={styles.navItem}>
<Link href="/supabase-ssr">Supabase RLS(SSR)</Link>
</li>
</ul> </ul>
</nav> </nav>
</header> </header>

View File

@@ -1,45 +1,10 @@
export { default } from "next-auth/middleware" // export { auth as default } from "auth"
import { auth } from "auth"
import { NextResponse } from "next/server"
export default auth((req) => {
if (req.auth) return NextResponse.json(req.auth)
return NextResponse.json("Not authorized", { status: 401 })
})
export const config = { matcher: ["/middleware-protected"] } export const config = { matcher: ["/middleware-protected"] }
// Other ways to use this middleware
// import withAuth from "next-auth/middleware"
// import { withAuth } from "next-auth/middleware"
// export function middleware(req, ev) {
// return withAuth(req)
// }
// export function middleware(req, ev) {
// return withAuth(req, ev)
// }
// export function middleware(req, ev) {
// return withAuth(req, {
// callbacks: {
// authorized: ({ token }) => !!token,
// },
// })
// }
// export default withAuth(function middleware(req, ev) {
// console.log(req.nextauth.token)
// })
// export default withAuth(
// function middleware(req, ev) {
// console.log(req, ev)
// },
// {
// callbacks: {
// authorized: ({ token }) => token.name === "Balázs Orbán",
// },
// }
// )
// export default withAuth({
// callbacks: {
// authorized: ({ token }) => !!token,
// },
// })

View File

@@ -15,14 +15,15 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@auth/core": "workspace:*", "@auth/core": "workspace:*",
"next-auth": "workspace:*",
"@next-auth/fauna-adapter": "workspace:*", "@next-auth/fauna-adapter": "workspace:*",
"@auth/prisma-adapter": "workspace:*", "@next-auth/prisma-adapter": "workspace:*",
"@next-auth/supabase-adapter": "workspace:*", "@next-auth/supabase-adapter": "workspace:*",
"@auth/typeorm-adapter": "workspace:*", "@next-auth/typeorm-legacy-adapter": "workspace:*",
"@prisma/client": "^3", "@prisma/client": "^3",
"@supabase/supabase-js": "^2.0.5", "@supabase/supabase-js": "^2.0.5",
"faunadb": "^4", "faunadb": "^4",
"next": "13.3.0", "next": "13.3.2-canary.12",
"next-auth": "workspace:*", "next-auth": "workspace:*",
"nodemailer": "^6", "nodemailer": "^6",
"react": "^18", "react": "^18",

View File

@@ -41,7 +41,7 @@ import WorkOS from "@auth/core/providers/workos"
// // Prisma // // Prisma
// import { PrismaClient } from "@prisma/client" // import { PrismaClient } from "@prisma/client"
// import { PrismaAdapter } from "@auth/prisma-adapter" // import { PrismaAdapter } from "@next-auth/prisma-adapter"
// const client = globalThis.prisma || new PrismaClient() // const client = globalThis.prisma || new PrismaClient()
// if (process.env.NODE_ENV !== "production") globalThis.prisma = client // if (process.env.NODE_ENV !== "production") globalThis.prisma = client
// const adapter = PrismaAdapter(client) // const adapter = PrismaAdapter(client)
@@ -55,8 +55,8 @@ import WorkOS from "@auth/core/providers/workos"
// const adapter = FaunaAdapter(client) // const adapter = FaunaAdapter(client)
// // TypeORM // // TypeORM
// import { TypeORMAdapter } from "@auth/typeorm-adapter" // import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
// const adapter = TypeORMAdapter({ // const adapter = TypeORMLegacyAdapter({
// type: "sqlite", // type: "sqlite",
// name: "next-auth-test-memory", // name: "next-auth-test-memory",
// database: "./typeorm/dev.db", // database: "./typeorm/dev.db",
@@ -94,7 +94,11 @@ export const authConfig: AuthConfig = {
tenantId: process.env.AZURE_AD_TENANT_ID, tenantId: process.env.AZURE_AD_TENANT_ID,
}), }),
AzureB2C({ clientId: process.env.AZURE_B2C_ID, clientSecret: process.env.AZURE_B2C_SECRET, issuer: process.env.AZURE_B2C_ISSUER }), AzureB2C({ clientId: process.env.AZURE_B2C_ID, clientSecret: process.env.AZURE_B2C_SECRET, issuer: process.env.AZURE_B2C_ISSUER }),
BeyondIdentity({ clientId: process.env.BEYOND_IDENTITY_CLIENT_ID, clientSecret: process.env.BEYOND_IDENTITY_CLIENT_SECRET, issuer: process.env.BEYOND_IDENTITY_ISSUER }), BeyondIdentity({
clientId: process.env.BEYOND_IDENTITY_CLIENT_ID,
clientSecret: process.env.BEYOND_IDENTITY_CLIENT_SECRET,
issuer: process.env.BEYOND_IDENTITY_ISSUER,
}),
BoxyHQSAML({ issuer: "https://jackson-demo.boxyhq.com", clientId: "tenant=boxyhq.com&product=saml-demo.boxyhq.com", clientSecret: "dummy" }), BoxyHQSAML({ issuer: "https://jackson-demo.boxyhq.com", clientId: "tenant=boxyhq.com&product=saml-demo.boxyhq.com", clientSecret: "dummy" }),
// Cognito({ clientId: process.env.COGNITO_ID, clientSecret: process.env.COGNITO_SECRET, issuer: process.env.COGNITO_ISSUER }), // Cognito({ clientId: process.env.COGNITO_ID, clientSecret: process.env.COGNITO_SECRET, issuer: process.env.COGNITO_ISSUER }),
Discord({ clientId: process.env.DISCORD_ID, clientSecret: process.env.DISCORD_SECRET }), Discord({ clientId: process.env.DISCORD_ID, clientSecret: process.env.DISCORD_SECRET }),
@@ -156,4 +160,4 @@ function AuthHandler(...args: any[]) {
export default AuthHandler(authConfig) export default AuthHandler(authConfig)
export const config = { runtime: "experimental-edge" } export const config = { runtime: "edge" }

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 { authConfig } from "../auth-old/[...nextauth]"
import { authOptions } from "../auth/[...nextauth]" import { getServerSession } from "next-auth/next"
export default async (req, res) => { export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions) const session = await getServerSession(req, res, authConfig as any)
if (session) { if (session) {
res.send({ res.send({

View File

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

View File

@@ -0,0 +1,8 @@
import { authConfig } from "../auth-old/[...nextauth]"
// This is an example of how to access a session from an API route
import { getServerSession } from "next-auth/next"
export default async (req, res) => {
const session = await getServerSession(req, res, authConfig as any)
res.json(session)
}

View File

@@ -1,30 +0,0 @@
// This is an example of how to query data from Supabase with RLS.
// Learn more about Row Levele Security (RLS): https://supabase.com/docs/guides/auth/row-level-security
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "../auth/[...nextauth]"
import { createClient } from "@supabase/supabase-js"
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
if (!session)
return res.send(JSON.stringify({ error: "No session!" }, null, 2))
const { supabaseAccessToken } = session
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
{
global: {
headers: {
Authorization: `Bearer ${supabaseAccessToken}`,
},
},
}
)
// Now you can query with RLS enabled.
const { data, error } = await supabase.from("users").select("*")
res.send(JSON.stringify({ supabaseAccessToken, data, error }, null, 2))
}

View File

@@ -1,6 +1,6 @@
// 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 { authConfig } from "./api/auth-old/[...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.req, context.res, authConfig)
context.req,
context.res,
authOptions
)
let content = null let content = null
if (session) { if (session) {

View File

@@ -1,6 +1,6 @@
import { unstable_getServerSession } from "next-auth/next" import { getServerSession } from "next-auth/next"
import Layout from "../components/layout" import Layout from "../components/layout"
import { authOptions } from "./api/auth/[...nextauth]" import { authConfig } from "./api/auth-old/[...nextauth]"
export default function Page() { export default function Page() {
// As this page uses Server Side Rendering, the `session` will be already // As this page uses Server Side Rendering, the `session` will be already
@@ -12,11 +12,11 @@ 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 <strong>getServerSession()</strong> method in{" "}
in <strong>getServerSideProps()</strong>. <strong>getServerSideProps()</strong>.
</p> </p>
<p> <p>
Using <strong>unstable_getServerSession()</strong> in{" "} Using <strong>getServerSession()</strong> in{" "}
<strong>getServerSideProps()</strong> is currently the recommended <strong>getServerSideProps()</strong> is currently the recommended
approach, although the API may still change, if you need to support approach, although the API may still change, if you need to support
Server Side Rendering with authentication. Server Side Rendering with authentication.
@@ -40,11 +40,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 getServerSession(context.req, context.res, authConfig),
context.req,
context.res,
authOptions
),
}, },
} }
} }

View File

@@ -1,48 +0,0 @@
import Layout from "../components/layout"
import { useState, useEffect } from "react"
import { useSession } from "next-auth/react"
import { createClient } from "@supabase/supabase-js"
export default function Page() {
const { data: session } = useSession()
const [data, setData] = useState(null)
useEffect(() => {
if (session) {
// User is logged in, let's fetch their data.
const { supabaseAccessToken } = session
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
{
global: {
headers: { Authorization: `Bearer ${supabaseAccessToken}` },
},
}
)
// Fetch data with RLS enabled.
supabase
.from("users")
.select("*")
.then(({ data }) => setData(data))
}
}, [session])
return (
<Layout>
<h1>Fetch Data from Supabase with RLS</h1>
<h2>Client-side data fetching with RLS:</h2>
<pre>{JSON.stringify(data, null, 2)}</pre>
<h2>API Example</h2>
<p>
You can also use Supabase in API routes. See the code in the
`/pages/api/examples/supabase-rls.js` file.
</p>
<p>
<em>You must be signed in to see responses.</em>
</p>
<p>/api/examples/supabase-rls</p>
<iframe src="/api/examples/supabase-rls" />
</Layout>
)
}

View File

@@ -1,68 +0,0 @@
// This is an example of how to protect content using server rendering
// and fetching data from Supabase with RLS enabled.
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import { createClient } from "@supabase/supabase-js"
import Layout from "../components/layout"
import AccessDenied from "../components/access-denied"
export default function Page({ data, session }) {
// If no session exists, display access denied message
if (!session) {
return (
<Layout>
<AccessDenied />
</Layout>
)
}
// If session exists, display content
return (
<Layout>
<h1>Protected Page</h1>
<p>Data fetched during SSR from Supabase with RSL enabled:</p>
<pre>{JSON.stringify(data, null, 2)}</pre>
</Layout>
)
}
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(
context.req,
context.res,
authOptions
)
if (!session)
return {
props: {
session,
data: null,
error: "No session",
},
}
const { supabaseAccessToken } = session
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
{
global: {
headers: {
Authorization: `Bearer ${supabaseAccessToken}`,
},
},
}
)
// Now you can query with RLS enabled.
const { data, error } = await supabase.from("users").select("*")
return {
props: {
session,
data,
error,
},
}
}

View File

@@ -18,3 +18,12 @@ declare module "next-auth" {
foo: string foo: string
} }
} }
declare global {
namespace NodeJS {
interface ProcessEnv {
[key: string]: string;
}
}
}

View File

@@ -0,0 +1,4 @@
/** @type {import("next").NextConfig} */
module.exports = {
reactStrictMode: true,
}

View File

@@ -1,5 +1,5 @@
NEXTAUTH_URL=http://localhost:3000 NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32 NEXTAUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.vercel.app/32
AUTH0_ID= AUTH0_ID=

View File

@@ -8,7 +8,7 @@
<a href="https://nextjs.org" target="_blank"> <a href="https://nextjs.org" target="_blank">
<img height="64" src="https://nextjs.org/static/favicon/android-chrome-192x192.png" /> <img height="64" src="https://nextjs.org/static/favicon/android-chrome-192x192.png" />
</a> </a>
<h3 align="center"><b>NextAuth.js</b> - Example App</h3> <h3 align="center"><b>next-auth</b> - Example App</h3>
<p align="center"> <p align="center">
Open Source. Full Stack. Own Your Data. Open Source. Full Stack. Own Your Data.
</p> </p>
@@ -36,7 +36,7 @@ This is an example application that shows how `next-auth` is applied to a basic
The deployed version can be found at [`next-auth-example.vercel.app`](https://next-auth-example.vercel.app) The deployed version can be found at [`next-auth-example.vercel.app`](https://next-auth-example.vercel.app)
Go to [next-auth.js.org](https://next-auth.js.org) for more information and documentation. Go to [authjs.dev](https://authjs.dev) for more information and documentation.
## Getting Started ## Getting Started
@@ -66,7 +66,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: [authjs.dev/reference/adapters](https://authjs.dev/reference/adapters)
### 3. Configure Authentication Providers ### 3. Configure Authentication Providers
@@ -76,7 +76,7 @@ For more information about setting up a database, please check out the following
e.g. For Google OAuth you would use: `http://localhost:3000/api/auth/callback/google` e.g. For Google OAuth you would use: `http://localhost:3000/api/auth/callback/google`
A list of configured providers and their callback URLs is available from the endpoint `/api/auth/providers`. You can find more information at https://next-auth.js.org/configuration/providers/oauth A list of configured providers and their callback URLs is available from the endpoint `/api/auth/providers`. You can find more information at [authjs.dev/getting-started/oauth-tutorial](https://authjs.dev/getting-started/oauth-tutorial)
3. You can also choose to specify an SMTP server for passwordless sign in via email. 3. You can also choose to specify an SMTP server for passwordless sign in via email.
@@ -106,4 +106,4 @@ Follow the [Deployment documentation](https://authjs.dev/guides/basics/deploymen
<a href="https://vercel.com?utm_source=nextauthjs&utm_campaign=oss"> <a href="https://vercel.com?utm_source=nextauthjs&utm_campaign=oss">
<img width="170px" src="https://raw.githubusercontent.com/nextauthjs/next-auth/main/docs/static/img/powered-by-vercel.svg" alt="Powered By Vercel" /> <img width="170px" src="https://raw.githubusercontent.com/nextauthjs/next-auth/main/docs/static/img/powered-by-vercel.svg" alt="Powered By Vercel" />
</a> </a>
<p align="left">Thanks to Vercel sponsoring this project by allowing it to be deployed for free for the entire Auth.js Team</p> <p align="left">Thanks to Vercel sponsoring this project by allowing it to be deployed for free for the entire Auth.js Team</p>

View File

@@ -0,0 +1,3 @@
import { handlers } from "auth"
export const { GET, POST } = handlers
export const runtime = "edge"

View File

@@ -0,0 +1,10 @@
import { auth } from "auth"
import { NextResponse } from "next/server"
export const GET = auth(function GET(req) {
if (req.auth) {
return NextResponse.json(req.auth)
}
return NextResponse.json({ message: "Not authenticated" }, { status: 401 })
})

View File

@@ -1,15 +1,13 @@
import Layout from "../components/layout" export default function Page() {
export default function ClientPage() {
return ( return (
<Layout> <>
<h1>Client Side Rendering</h1> <h1>Client Side Rendering</h1>
<p> <p>
This page uses the <strong>useSession()</strong> React Hook in the{" "} This page uses the <strong>useSession()</strong> React Hook in the{" "}
<strong>&lt;Header/&gt;</strong> component. <strong>&lt;/Header&gt;</strong> component.
</p> </p>
<p> <p>
The <strong>useSession()</strong> React Hook is easy to use and allows The <strong>useSession()</strong> React Hook easy to use and allows
pages to render very quickly. pages to render very quickly.
</p> </p>
<p> <p>
@@ -22,6 +20,6 @@ export default function ClientPage() {
The disadvantage of <strong>useSession()</strong> is that it requires The disadvantage of <strong>useSession()</strong> is that it requires
client side JavaScript. client side JavaScript.
</p> </p>
</Layout> </>
) )
} }

View File

@@ -0,0 +1,24 @@
import Header from "components/header"
import Footer from "components/footer"
import './styles.css'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<head></head>
<body>
<Header />
<main>
{children}
</main>
<Footer />
</body>
</html>
)
}
export const runtime = "experimental-edge"

View File

@@ -0,0 +1,13 @@
export default function Page() {
return (
<>
<h1>NextAuth.js Example</h1>
<p>
This is an example site to demonstrate how to use{" "}
<a href="https://authjs.dev">NextAuth.js</a> for authentication.
</p>
</>
)
}
export const runtime = "experimental-edge"

View File

@@ -0,0 +1,39 @@
import { auth } from "auth"
import { cookies, headers } from "next/headers"
function SignIn({ id, children, className }: any) {
const $cookies = cookies()
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
return (
<form action={`/api/auth/signin/${id}`} method="post">
<button className={className} type="submit">{children}</button>
<input type="hidden" name="csrfToken" value={csrfToken} />
</form>
)
}
function SignOut({ children }: any) {
const $cookies = cookies()
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
return (
<form action="/api/auth/signout" method="post">
<button type="submit">{children}</button>
<input type="hidden" name="csrfToken" value={csrfToken} />
</form>
)
}
export default async function Page() {
const session = await auth(headers())
if (session) {
return (
<>
<pre>{JSON.stringify(session, null, 2)}</pre>
<SignOut>Sign out</SignOut>
</>
)
}
return <SignIn id="github">Sign in with github</SignIn>
}
export const runtime = "experimental-edge"

View File

@@ -1,4 +1,5 @@
body { body {
color: red;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
@@ -6,7 +7,7 @@ body {
max-width: 680px; max-width: 680px;
margin: 0 auto; margin: 0 auto;
background: #fff; background: #fff;
color: #333; color: var(--color-text);
} }
li, li,

View File

@@ -0,0 +1,21 @@
import NextAuth from "next-auth"
import GitHub from "@auth/core/providers/github"
export const { handlers, auth } = NextAuth({
providers: [GitHub],
callbacks: {
async authorized({ request, auth }) {
// if (request.method === "POST") {
// const [, token] = request.headers.get("Authorization")?.split(" ")
// const valid = validateToken(token)
// // If the request has a valid auth token, it is authorized
// if (valid) return true
// return NextResponse.json("Invalid auth token", { status: 401 })
// }
// Logged in users are authorized, otherwise, will redirect to login
// You could also return a custom redirect instead of the sign-in page
return !!auth
},
},
})

View File

@@ -1,6 +1,6 @@
import Link from "next/link" import Link from "next/link"
import styles from "./footer.module.css" import styles from "./footer.module.css"
import packageJSON from "../package.json" import packageJSON from "next-auth/package.json"
export default function Footer() { export default function Footer() {
return ( return (
@@ -8,10 +8,10 @@ export default function Footer() {
<hr /> <hr />
<ul className={styles.navItems}> <ul className={styles.navItems}>
<li className={styles.navItem}> <li className={styles.navItem}>
<a href="https://next-auth.js.org">Documentation</a> <a href="https://authjs.dev">Documentation</a>
</li> </li>
<li className={styles.navItem}> <li className={styles.navItem}>
<a href="https://www.npmjs.com/package/next-auth">NPM</a> <a href="https://www.npmjs.com/package/@auth/core">NPM</a>
</li> </li>
<li className={styles.navItem}> <li className={styles.navItem}>
<a href="https://github.com/nextauthjs/next-auth-example">GitHub</a> <a href="https://github.com/nextauthjs/next-auth-example">GitHub</a>
@@ -20,7 +20,7 @@ export default function Footer() {
<Link href="/policy">Policy</Link> <Link href="/policy">Policy</Link>
</li> </li>
<li className={styles.navItem}> <li className={styles.navItem}>
<em>next-auth@{packageJSON.dependencies["next-auth"]}</em> <em>{packageJSON.version}</em>
</li> </li>
</ul> </ul>
</footer> </footer>

View File

@@ -1,5 +1,6 @@
/* Set min-height to avoid page reflow while session loading */ /* Set min-height to avoid page reflow while session loading */
.signedInStatus { .signedInStatus {
position: relative;
display: block; display: block;
min-height: 4rem; min-height: 4rem;
width: 100%; width: 100%;

View File

@@ -1,65 +1,63 @@
import Link from "next/link" import Link from "next/link"
import { signIn, signOut, useSession } from "next-auth/react" import { auth } from "auth"
import { cookies, headers } from "next/headers"
import styles from "./header.module.css" import styles from "./header.module.css"
// The approach used in this component shows how to build a sign in and sign out function SignIn({ id, children, className }: any) {
const $cookies = cookies()
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
return (
<form action={`/api/auth/signin/${id}`} method="post">
<button className={className} type="submit">{children}</button>
<input type="hidden" name="csrfToken" value={csrfToken} />
</form>
)
}
function SignOut({ children, className }: any) {
const $cookies = cookies()
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
return (
<form action="/api/auth/signout" method="post">
<button className={className} type="submit">{children}</button>
<input type="hidden" name="csrfToken" value={csrfToken} />
</form>
)
}
// The approach used in this component shows how to built a sign in and sign out
// component that works on pages which support both client and server side // component that works on pages which support both client and server side
// rendering, and avoids any flash incorrect content on initial page load. // rendering, and avoids any flash incorrect content on initial page load.
export default function Header() { export default async function Header() {
const { data: session, status } = useSession() const session = await auth(headers())
const loading = status === "loading"
return ( return (
<header> <header>
<noscript> <noscript>
<style>{`.nojs-show { opacity: 1; top: 0; }`}</style> <style>{".nojs-show { opacity: 1; top: 0; }"}</style>
</noscript> </noscript>
<div className={styles.signedInStatus}> <div className={styles.signedInStatus}>
<p <p className={`nojs-show ${styles.loaded}`}>
className={`nojs-show ${
!session && loading ? styles.loading : styles.loaded
}`}
>
{!session && ( {!session && (
<> <>
<span className={styles.notSignedInText}> <span className={styles.notSignedInText}>
You are not signed in You are not signed in
</span> </span>
<a <SignIn className={styles.buttonPrimary}>Sign In</SignIn>
href={`/api/auth/signin`}
className={styles.buttonPrimary}
onClick={(e) => {
e.preventDefault()
signIn()
}}
>
Sign in
</a>
</> </>
)} )}
{session?.user && ( {session && (
<> <>
{session.user.image && ( {session.user.image && (
<span <img src={session.user.image} className={styles.avatar} />
style={{ backgroundImage: `url('${session.user.image}')` }}
className={styles.avatar}
/>
)} )}
<span className={styles.signedInText}> <span className={styles.signedInText}>
<small>Signed in as</small> <small>Signed in as</small>
<br /> <br />
<strong>{session.user.email ?? session.user.name}</strong> <strong>{session.user.email} </strong>
{session.user.name ? `(${session.user.name})` : null}
</span> </span>
<a <SignOut className={styles.button}>Sign Out</SignOut>
href={`/api/auth/signout`}
className={styles.button}
onClick={(e) => {
e.preventDefault()
signOut()
}}
>
Sign out
</a>
</> </>
)} )}
</p> </p>
@@ -73,7 +71,7 @@ export default function Header() {
<Link href="/client">Client</Link> <Link href="/client">Client</Link>
</li> </li>
<li className={styles.navItem}> <li className={styles.navItem}>
<Link href="/server">Server</Link> <Link href="/server-component">Server</Link>
</li> </li>
<li className={styles.navItem}> <li className={styles.navItem}>
<Link href="/protected">Protected</Link> <Link href="/protected">Protected</Link>
@@ -82,13 +80,12 @@ export default function Header() {
<Link href="/api-example">API</Link> <Link href="/api-example">API</Link>
</li> </li>
<li className={styles.navItem}> <li className={styles.navItem}>
<Link href="/admin">Admin</Link> <Link href="/middleware-protected">Middleware protected</Link>
</li>
<li className={styles.navItem}>
<Link href="/me">Me</Link>
</li> </li>
</ul> </ul>
</nav> </nav>
</header> </header>
) )
} }
export const runtime = "experimental-edge"

View File

@@ -1,13 +0,0 @@
import Header from "./header"
import Footer from "./footer"
import type { ReactNode } from "react"
export default function Layout({ children }: { children: ReactNode }) {
return (
<>
<Header />
<main>{children}</main>
<Footer />
</>
)
}

View File

@@ -1,17 +1,10 @@
import { withAuth } from "next-auth/middleware" // export { auth as default } from "auth"
import { auth } from "auth"
import { NextResponse } from "next/server"
// More on how NextAuth.js middleware works: https://next-auth.js.org/configuration/nextjs#middleware export default auth((req) => {
export default withAuth({ if (req.auth) return NextResponse.json(req.auth)
callbacks: { return NextResponse.json("Not authorized", { status: 401 })
authorized({ req, token }) {
// `/admin` requires admin role
if (req.nextUrl.pathname === "/admin") {
return token?.userRole === "admin"
}
// `/me` only requires the user to be logged in
return !!token
},
},
}) })
export const config = { matcher: ["/admin", "/me"] } export const config = { matcher: ["/middleware-protected"] }

View File

@@ -1,10 +0,0 @@
import "next-auth/jwt"
// Read more at: https://next-auth.js.org/getting-started/typescript#module-augmentation
declare module "next-auth/jwt" {
interface JWT {
/** The user's role. */
userRole?: "admin"
}
}

View File

@@ -1,4 +1,9 @@
/** @type {import("next").NextConfig} */ /** @type {import("next").NextConfig} */
module.exports = { module.exports = {
reactStrictMode: true, webpack(config) {
config.experiments = { ...config.experiments, topLevelAwait: true }
return config
},
experimental: { appDir: true },
typescript: { ignoreBuildErrors: true },
} }

View File

@@ -1,5 +1,6 @@
{ {
"private": true, "private": true,
"name": "nextjs-example-app",
"description": "An example project for NextAuth.js with Next.js", "description": "An example project for NextAuth.js with Next.js",
"repository": "https://github.com/nextauthjs/next-auth-example.git", "repository": "https://github.com/nextauthjs/next-auth-example.git",
"bugs": { "bugs": {
@@ -18,8 +19,9 @@
"Lluis Agusti <hi@llu.lu>" "Lluis Agusti <hi@llu.lu>"
], ],
"dependencies": { "dependencies": {
"@auth/core": "workspace:*",
"next": "latest", "next": "latest",
"next-auth": "latest", "next-auth": "workspace:*",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },

View File

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

View File

@@ -1,17 +0,0 @@
import Layout from "../components/layout"
export default function Page() {
return (
<Layout>
<h1>This page is protected by Middleware</h1>
<p>Only admin users can see this page.</p>
<p>
To learn more about the NextAuth middleware see&nbsp;
<a href="https://next-auth.js.org/configuration/nextjs#middleware">
the docs
</a>
.
</p>
</Layout>
)
}

View File

@@ -1,19 +0,0 @@
import Layout from "../components/layout"
export default function ApiExamplePage() {
return (
<Layout>
<h1>API Example</h1>
<p>The examples below show responses from the example API endpoints.</p>
<p>
<em>You must be signed in to see responses.</em>
</p>
<h2>Session</h2>
<p>/api/examples/session</p>
<iframe src="/api/examples/session" />
<h2>JSON Web Token</h2>
<p>/api/examples/jwt</p>
<iframe src="/api/examples/jwt" />
</Layout>
)
}

View File

@@ -1,44 +0,0 @@
import NextAuth, { NextAuthOptions } from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import FacebookProvider from "next-auth/providers/facebook"
import GithubProvider from "next-auth/providers/github"
import TwitterProvider from "next-auth/providers/twitter"
import Auth0Provider from "next-auth/providers/auth0"
// For more information on each option (and a full list of options) go to
// https://next-auth.js.org/configuration/options
export const authOptions: NextAuthOptions = {
// https://next-auth.js.org/configuration/providers/oauth
providers: [
Auth0Provider({
clientId: process.env.AUTH0_ID,
clientSecret: process.env.AUTH0_SECRET,
issuer: process.env.AUTH0_ISSUER,
}),
FacebookProvider({
clientId: process.env.FACEBOOK_ID,
clientSecret: process.env.FACEBOOK_SECRET,
}),
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
TwitterProvider({
clientId: process.env.TWITTER_ID,
clientSecret: process.env.TWITTER_SECRET,
version: "2.0",
}),
],
callbacks: {
async jwt({ token }) {
token.userRole = "admin"
return token
},
},
}
export default NextAuth(authOptions)

View File

@@ -1,14 +0,0 @@
// This is an example of how to read a JSON Web Token from an API route
import { getToken } from "next-auth/jwt"
import type { NextApiRequest, NextApiResponse } from "next"
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// If you don't have the NEXTAUTH_SECRET environment variable set,
// you will have to pass your secret as `secret` to `getToken`
const token = await getToken({ req })
res.send(JSON.stringify(token, null, 2))
}

View File

@@ -1,23 +0,0 @@
// This is an example of to protect an API route
import { getServerSession } from "next-auth/next"
import { authOptions } from "../auth/[...nextauth]"
import type { NextApiRequest, NextApiResponse } from "next"
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await getServerSession(req, res, authOptions)
if (session) {
return res.send({
content:
"This is protected content. You can access this content because you are signed in.",
})
}
res.send({
error: "You must be signed in to view the protected content on this page.",
})
}

View File

@@ -1,13 +0,0 @@
// This is an example of how to access a session from an API route
import { getServerSession } from "next-auth"
import { authOptions } from "../auth/[...nextauth]"
import type { NextApiRequest, NextApiResponse } from "next"
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await getServerSession(req, res, authOptions)
res.send(JSON.stringify(session, null, 2))
}

View File

@@ -1,13 +0,0 @@
import Layout from "../components/layout"
export default function IndexPage() {
return (
<Layout>
<h1>NextAuth.js Example</h1>
<p>
This is an example site to demonstrate how to use{" "}
<a href="https://next-auth.js.org">NextAuth.js</a> for authentication.
</p>
</Layout>
)
}

View File

@@ -1,12 +0,0 @@
import { useSession } from "next-auth/react"
import Layout from "../components/layout"
export default function MePage() {
const { data } = useSession()
return (
<Layout>
<pre>{JSON.stringify(data, null, 2)}</pre>
</Layout>
)
}

View File

@@ -1,32 +0,0 @@
import Layout from "../components/layout"
export default function PolicyPage() {
return (
<Layout>
<p>
This is an example site to demonstrate how to use{" "}
<a href="https://next-auth.js.org">NextAuth.js</a> for authentication.
</p>
<h2>Terms of Service</h2>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</p>
<h2>Privacy Policy</h2>
<p>
This site uses JSON Web Tokens and an in-memory database which resets
every ~2 hours.
</p>
<p>
Data provided to this site is exclusively used to support signing in and
is not passed to any third party services, other than via SMTP or OAuth
for the purposes of authentication.
</p>
</Layout>
)
}

View File

@@ -1,40 +0,0 @@
import { useState, useEffect } from "react"
import { useSession } from "next-auth/react"
import Layout from "../components/layout"
import AccessDenied from "../components/access-denied"
export default function ProtectedPage() {
const { data: session } = useSession()
const [content, setContent] = useState()
// Fetch content from protected route
useEffect(() => {
const fetchData = async () => {
const res = await fetch("/api/examples/protected")
const json = await res.json()
if (json.content) {
setContent(json.content)
}
}
fetchData()
}, [session])
// If no session exists, display access denied message
if (!session) {
return (
<Layout>
<AccessDenied />
</Layout>
)
}
// If session exists, display content
return (
<Layout>
<h1>Protected Page</h1>
<p>
<strong>{content ?? "\u00a0"}</strong>
</p>
</Layout>
)
}

View File

@@ -1,44 +0,0 @@
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout"
import type { GetServerSidePropsContext } from "next"
import { useSession } from "next-auth/react"
export default function ServerSidePage() {
const { data: session } = useSession()
// As this page uses Server Side Rendering, the `session` will be already
// populated on render without needing to go through a loading stage.
return (
<Layout>
<h1>Server Side Rendering</h1>
<p>
This page uses the <strong>getServerSession()</strong> method in{" "}
<strong>getServerSideProps()</strong>.
</p>
<p>
Using <strong>getServerSession()</strong> in{" "}
<strong>getServerSideProps()</strong> is the recommended approach if you
need to support Server Side Rendering with authentication.
</p>
<p>
The advantage of Server Side Rendering is this page does not require
client side JavaScript.
</p>
<p>
The disadvantage of Server Side Rendering is that this page is slower to
render.
</p>
<pre>{JSON.stringify(session, null, 2)}</pre>
</Layout>
)
}
// Export the `session` prop to use sessions with Server Side Rendering
export async function getServerSideProps(context: GetServerSidePropsContext) {
return {
props: {
session: await getServerSession(context.req, context.res, authOptions),
},
}
}

View File

@@ -1,10 +1,14 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "esnext",
"lib": ["dom", "dom.iterable", "esnext"], "lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": false,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"noEmit": true, "noEmit": true,
"esModuleInterop": true, "esModuleInterop": true,
@@ -12,15 +16,24 @@
"moduleResolution": "node", "moduleResolution": "node",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"incremental": true,
"jsx": "preserve", "jsx": "preserve",
"incremental": true "baseUrl": ".",
"plugins": [
{
"name": "next"
}
],
"strictNullChecks": true
}, },
"include": [ "include": [
"process.d.ts",
"next-env.d.ts", "next-env.d.ts",
"next-auth.d.ts",
"**/*.ts", "**/*.ts",
"**/*.tsx" "**/*.tsx",
".next/types/**/*.ts"
], ],
"exclude": ["node_modules"] "exclude": [
"node_modules",
"jest.config.js"
]
} }

View File

@@ -1,4 +1,4 @@
import { Session } from "@auth/core/types" import { Session } from "@auth/core"
export default function useSession() { export default function useSession() {
return useState<Session | null>("session", () => null) return useState<Session | null>("session", () => null)

View File

@@ -43,7 +43,7 @@ export async function signIn<
// TODO: Handle custom base path // TODO: Handle custom base path
// TODO: Remove this since Sveltekit offers the CSRF protection via origin check // TODO: Remove this since Sveltekit offers the CSRF protection via origin check
const { csrfToken } = await $fetch<{ csrfToken: string }>("/api/auth/csrf") const { csrfToken } = await $fetch("/api/auth/csrf")
console.log(_signInUrl) console.log(_signInUrl)

View File

@@ -1,14 +1,13 @@
import { AuthConfig, Session } from "@auth/core/types" import { AuthHandler, AuthOptions, Session } from "@auth/core"
import { Auth } from "@auth/core"
import { fromNodeMiddleware, H3Event } from "h3" import { fromNodeMiddleware, H3Event } from "h3"
import getURL from "requrl" import getURL from "requrl"
import { createMiddleware } from "@hattip/adapter-node" import { createMiddleware } from "@hattip/adapter-node"
export function NuxtAuthHandler(options: AuthConfig) { export function NuxtAuthHandler(options: AuthOptions) {
async function handler(ctx: { request: Request }) { async function handler(ctx: { request: Request }) {
options.trustHost ??= true options.trustHost ??= true
return Auth(ctx.request, options) return AuthHandler(ctx.request, options)
} }
const middleware = createMiddleware(handler) const middleware = createMiddleware(handler)
@@ -18,7 +17,7 @@ export function NuxtAuthHandler(options: AuthConfig) {
export async function getSession( export async function getSession(
event: H3Event, event: H3Event,
options: AuthConfig options: AuthOptions
): Promise<Session | null> { ): Promise<Session | null> {
options.trustHost ??= true options.trustHost ??= true
@@ -31,7 +30,7 @@ export async function getSession(
nodeHeaders.append(key, headers[key] as any) nodeHeaders.append(key, headers[key] as any)
}) })
const response = await Auth( const response = await AuthHandler(
new Request(url, { headers: nodeHeaders }), new Request(url, { headers: nodeHeaders }),
options options
) )

View File

@@ -1,21 +1,21 @@
{ {
"name": "next-auth-nuxt", "name": "playground-nuxt",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "nuxt build", "build": "nuxt prepare && nuxt build",
"dev": "nuxt prepare && nuxt dev", "dev": "nuxt prepare && export NODE_OPTIONS='--no-experimental-fetch' && nuxt dev",
"generate": "nuxt generate", "generate": "nuxt generate",
"preview": "nuxt preview" "preview": "nuxt preview"
}, },
"devDependencies": { "devDependencies": {
"@nuxt/eslint-config": "^0.1.1", "@nuxt/eslint-config": "^0.1.1",
"eslint": "^8.29.0", "eslint": "^8.29.0",
"h3": "1.6.6", "h3": "1.0.2",
"nuxt": "3.5.1" "nuxt": "3.0.0"
}, },
"dependencies": { "dependencies": {
"@auth/core": "workspace:*", "@auth/core": "workspace:*",
"@hattip/adapter-node": "^0.0.34", "@hattip/adapter-node": "^0.0.22",
"requrl": "^3.0.2" "requrl": "^3.0.2"
} }
} }

View File

@@ -1,4 +1,4 @@
import { Session } from "@auth/core/types" import { Session } from "@auth/core"
export default defineNuxtPlugin(async () => { export default defineNuxtPlugin(async () => {
const session = useSession() const session = useSession()

View File

@@ -1,10 +1,10 @@
import { NuxtAuthHandler } from "@/lib/auth/server" import { NuxtAuthHandler } from "@/lib/auth/server"
import GithubProvider from "@auth/core/providers/github" import GithubProvider from "@auth/core/providers/github"
import type { AuthConfig } from "@auth/core" import type { AuthOptions } from "@auth/core"
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
export const authOptions = { export const authOptions: AuthOptions = {
secret: runtimeConfig.secret, secret: runtimeConfig.secret,
providers: [ providers: [
GithubProvider({ GithubProvider({
@@ -12,6 +12,6 @@ export const authOptions = {
clientSecret: runtimeConfig.github.clientSecret, clientSecret: runtimeConfig.github.clientSecret,
}), }),
], ],
} as AuthConfig }
export default NuxtAuthHandler(authOptions) export default NuxtAuthHandler(authOptions)

View File

@@ -36,10 +36,6 @@ This tutorial assumes you have a Next.js application set up. If you don't, you c
npm install next-auth npm install next-auth
``` ```
:::info
We are working on a new `@auth/nextjs` package that will make it easier to set up Auth.js with Next.js. Stay tuned! For now, you can use the `next-auth` package.
:::
### Creating the server config ### Creating the server config
Create the following [API route](https://nextjs.org/docs/api-routes/dynamic-api-routes#catch-all-api-routes) file. This route contains the necessary configuration for NextAuth.js, as well as the dynamic route handler: Create the following [API route](https://nextjs.org/docs/api-routes/dynamic-api-routes#catch-all-api-routes) file. This route contains the necessary configuration for NextAuth.js, as well as the dynamic route handler:
@@ -243,13 +239,10 @@ http://localhost:5173/auth/callback/github
TODO Core TODO Core
</TabItem> </TabItem>
</Tabs> </Tabs>
:::info :::info
The last part of the URL, `[provider]`, is the ID of the provider you're using. In this case, we're using GitHub, so it's `github`. If you're using Google, it'll be `google`, etc... We keep track of the provider IDs internally. The last part of the URL, `[provider]`, is the ID of the provider you're using. In this case, we're using GitHub, so it's `github`. If you're using Google, it'll be `google`, etc... We keep track of the provider IDs internally.
The same id is used in the `signIn()` method we saw earlier. The same id is used in the `signIn()` method we saw earlier.
::: :::
To register, tap on "Register application" button. To register, tap on "Register application" button.
The next screen shows all the configurations for your newly created OAuth app. For now, we need two things from it - the **Client ID** and **Client Secret**: The next screen shows all the configurations for your newly created OAuth app. For now, we need two things from it - the **Client ID** and **Client Secret**:
@@ -273,7 +266,7 @@ Note that, for each provider, the configuration process will be similar to what
2. Create create your OAuth application within it 2. Create create your OAuth application within it
3. Set the callback URL 3. Set the callback URL
4. Get the Client ID and Generate a Client Secret 4. Get the Client ID and Generate a Client Secret
::: :::
## 3. Wiring all together ## 3. Wiring all together

View File

@@ -117,7 +117,7 @@ Using the database strategy is very similar, but instead of preserving the `acce
import { Auth } from "@auth/core" import { Auth } from "@auth/core"
import { type TokenSet } from "@auth/core/types" import { type TokenSet } from "@auth/core/types"
import Google from "@auth/core/providers/google" import Google from "@auth/core/providers/google"
import { PrismaAdapter } from "@auth/prisma-adapter" import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client" import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient() const prisma = new PrismaClient()

View File

@@ -22,18 +22,11 @@ Next you will have to create some configuration files for Cypress.
First, the primary cypress config: First, the primary cypress config:
```ts title="cypress.config.ts" ```js title="cypress.json"
import { defineConfig } from 'cypress' {
"baseUrl": "http://localhost:3000",
export default defineConfig({ "chromeWebSecurity": false
e2e: { }
baseUrl: 'http://localhost:3000',
chromeWebSecurity: false,
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
})
``` ```
This initial Cypress config will tell Cypress where to find your site on initial launch as well as allow it to open up URLs at domains that aren't your page, for example to be able to login to a social provider. This initial Cypress config will tell Cypress where to find your site on initial launch as well as allow it to open up URLs at domains that aren't your page, for example to be able to login to a social provider.
@@ -53,24 +46,14 @@ You must change the login credentials you want to use, but you can also redefine
Third, if you're using the `cypress-social-login` plugin, you must add this to your `/cypress/plugins/index.js` file like so: Third, if you're using the `cypress-social-login` plugin, you must add this to your `/cypress/plugins/index.js` file like so:
```js title="cypress.config.ts" {3-4,10-14} ```js title="cypress/plugins/index.js"
import { defineConfig } from 'cypress' const { GoogleSocialLogin } = require("cypress-social-logins").plugins
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { GoogleSocialLogin } = require('cypress-social-logins').plugins
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
chromeWebSecurity: false,
setupNodeEvents(on, config) {
on('task', {
GoogleSocialLogin,
})
},
},
})
module.exports = (on, config) => {
on("task", {
GoogleSocialLogin: GoogleSocialLogin,
})
}
``` ```
Finally, you can also add the following npm scripts to your `package.json`: Finally, you can also add the following npm scripts to your `package.json`:
@@ -127,6 +110,10 @@ describe("Login page", () => {
secure: cookie.secure, secure: cookie.secure,
}) })
Cypress.Cookies.defaults({
preserve: cookieName,
})
// remove the two lines below if you need to stay logged in // remove the two lines below if you need to stay logged in
// for your remaining tests // for your remaining tests
cy.visit("/api/auth/signout") cy.visit("/api/auth/signout")

View File

@@ -96,13 +96,8 @@ erDiagram
string type string type
string provider string provider
string providerAccountId string providerAccountId
string refresh_token
string access_token string access_token
int expires_at
string token_type
string scope
string id_token string id_token
string session_state
} }
VerificationToken { VerificationToken {
string identifier string identifier
@@ -142,7 +137,7 @@ The Account model is for information about OAuth accounts associated with a User
A single User can have multiple Accounts, but each Account can only have one User. A single User can have multiple Accounts, but each Account can only have one User.
Account creation in the database is automatic and happens when the user is logging in for the first time with a provider, or the [`Adapter.linkAccount`](/reference/core/adapters#linkaccount) method is invoked. The default data saved is `access_token`, `expires_at`, `refresh_token`, `id_token`, `token_type`, `scope` and `session_state`. You can save other fields or remove the ones you don't need by returning them in the [OAuth provider](/guides/providers/custom-provider)'s [`account()`](/reference/core/providers#account) callback. Account creation in the database is automatic and happens when the user is logging in for the first time with a provider, or the [`Adapter.linkAccount`](/reference/core/adapters#linkaccount) method is invoked. The default data saved is `access_token`, `refresh_token`, `id_token` and `expires_at`. You can save other fields by returning them in the [OAuth provider](/guides/providers/custom-provider)'s [`account()`](/reference/core/providers#account) callback.
Linking Accounts to Users happen automatically, only when they have the same e-mail address, and the user is currently signed in. Check the [FAQ](/concepts/faq#security) for more information on why this is a requirement. Linking Accounts to Users happen automatically, only when they have the same e-mail address, and the user is currently signed in. Check the [FAQ](/concepts/faq#security) for more information on why this is a requirement.

View File

@@ -1,7 +0,0 @@
---
title: Client
---
:::warning WIP
`@auth/nextjs/client` is work in progress. For now, please use [NextAuth.js Client API](https://next-auth.js.org/getting-started/client).
:::

View File

@@ -1,7 +0,0 @@
---
title: Next.js Auth
---
:::warning WIP
`@auth/nextjs` is work in progress. For now, please use [NextAuth.js](https://next-auth.js.org).
:::

View File

@@ -38,6 +38,22 @@ function typedocAdapter(name) {
] ]
} }
function typedocFramework(id, entrypoints) {
return [
"docusaurus-plugin-typedoc",
{
...typedocConfig,
id: id.replace("frameworks-", ""),
plugin: [require.resolve("./typedoc-mdn-links")],
watch: process.env.TYPEDOC_WATCH,
entryPoints: entrypoints.map((e) => `../packages/${id}/src/${e}`),
tsconfig: `../packages/${id}/tsconfig.json`,
out: `reference/${id.replace("frameworks-", "")}`,
sidebar: { indexLabel: "index" },
},
]
}
/** @type {import("@docusaurus/types").Config} */ /** @type {import("@docusaurus/types").Config} */
const docusaurusConfig = { const docusaurusConfig = {
markdown: { markdown: {
@@ -231,36 +247,9 @@ const docusaurusConfig = {
], ],
], ],
plugins: [ plugins: [
[ typedocFramework("core", ["index.ts", "adapters.ts", "errors.ts", "jwt.ts", "types.ts"]),
"docusaurus-plugin-typedoc", typedocFramework("frameworks-sveltekit", ["lib/index.ts", "lib/client.ts"]),
{ typedocFramework("next-auth", ["index.ts", "react.tsx", "jwt.ts", "adapters.ts", "next.ts", "types.ts", "middleware.ts"]),
...typedocConfig,
id: "core",
plugin: [require.resolve("./typedoc-mdn-links")],
watch: process.env.TYPEDOC_WATCH,
entryPoints: ["index.ts", "adapters.ts", "errors.ts", "jwt.ts", "types.ts"].map((e) => `${coreSrc}/${e}`).concat(providers),
tsconfig: "../packages/core/tsconfig.json",
out: "reference/core",
sidebar: {
indexLabel: "index",
},
},
],
[
"docusaurus-plugin-typedoc",
{
...typedocConfig,
id: "sveltekit",
plugin: [require.resolve("./typedoc-mdn-links")],
watch: process.env.TYPEDOC_WATCH,
entryPoints: ["index.ts", "client.ts"].map((e) => `../packages/frameworks-sveltekit/src/lib/${e}`),
tsconfig: "../packages/frameworks-sveltekit/tsconfig.json",
out: "reference/sveltekit",
sidebar: {
indexLabel: "index",
},
},
],
...(process.env.TYPEDOC_SKIP_ADAPTERS ...(process.env.TYPEDOC_SKIP_ADAPTERS
? [] ? []
: [ : [
@@ -273,7 +262,19 @@ const docusaurusConfig = {
typedocAdapter("Neo4j"), typedocAdapter("Neo4j"),
typedocAdapter("PouchDB"), typedocAdapter("PouchDB"),
typedocAdapter("Prisma"), typedocAdapter("Prisma"),
typedocAdapter("TypeORM"), [
"docusaurus-plugin-typedoc",
{
...typedocConfig,
id: "typeorm",
plugin: [require.resolve("./typedoc-mdn-links")],
watch: process.env.TYPEDOC_WATCH,
entryPoints: [`../packages/adapter-typeorm-legacy/src/index.ts`],
tsconfig: `../packages/adapter-typeorm-legacy/tsconfig.json`,
out: `reference/adapter/typeorm`,
sidebar: { indexLabel: "TypeORM" },
},
],
typedocAdapter("Sequelize"), typedocAdapter("Sequelize"),
typedocAdapter("Supabase"), typedocAdapter("Supabase"),
typedocAdapter("Upstash Redis"), typedocAdapter("Upstash Redis"),

View File

@@ -35,16 +35,9 @@ module.exports = {
}, },
{ {
type: "category", type: "category",
label: "@auth/nextjs", label: "next-auth",
link: { type: "doc", id: "reference/nextjs/index" }, link: { type: "doc", id: "reference/next-auth/index" },
items: [ items: [{ type: "autogenerated", dirName: "reference/next-auth" }],
"reference/nextjs/client",
{
type: "link",
label: "NextAuth.js (next-auth)",
href: "https://next-auth.js.org",
},
],
}, },
...(process.env.TYPEDOC_SKIP_ADAPTERS ...(process.env.TYPEDOC_SKIP_ADAPTERS
? [] ? []

View File

@@ -29,7 +29,6 @@ html[data-theme="dark"] .adapter-card {
color: #f5f5f5; color: #f5f5f5;
} }
html[data-theme="dark"] .adapter-card:hover,
.adapter-card:hover { .adapter-card:hover {
text-decoration: none; text-decoration: none;
color: black; color: black;

View File

@@ -9,6 +9,7 @@
"build": "turbo run build --filter=next-auth --filter=@next-auth/* --filter=@auth/* --no-deps", "build": "turbo run build --filter=next-auth --filter=@next-auth/* --filter=@auth/* --no-deps",
"test": "turbo run test --concurrency=1 --filter=[HEAD^1] --filter=./packages/* --filter=!@*upstash* --filter=!*dynamodb-*", "test": "turbo run test --concurrency=1 --filter=[HEAD^1] --filter=./packages/* --filter=!@*upstash* --filter=!*dynamodb-*",
"clean": "turbo run clean --no-cache", "clean": "turbo run clean --no-cache",
"dev:example": "turbo run dev --parallel --continue --filter=nextjs-example-app... --filter=!./packages/adapter-*",
"dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...", "dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...",
"dev": "turbo run dev --parallel --continue --filter=next-auth-app... --filter=!./packages/adapter-*", "dev": "turbo run dev --parallel --continue --filter=next-auth-app... --filter=!./packages/adapter-*",
"dev-v4:db": "turbo run dev --parallel --continue --filter=next-auth-app-v4...", "dev-v4:db": "turbo run dev --parallel --continue --filter=next-auth-app-v4...",
@@ -28,7 +29,7 @@
"@actions/core": "^1.10.0", "@actions/core": "^1.10.0",
"@balazsorban/monorepo-release": "0.1.8", "@balazsorban/monorepo-release": "0.1.8",
"@types/jest": "^28.1.3", "@types/jest": "^28.1.3",
"@types/node": "^17.0.25", "@types/node": "^18.15.11",
"@typescript-eslint/eslint-plugin": "5.47.0", "@typescript-eslint/eslint-plugin": "5.47.0",
"@typescript-eslint/parser": "5.47.0", "@typescript-eslint/parser": "5.47.0",
"eslint": "8.30.0", "eslint": "8.30.0",
@@ -43,7 +44,7 @@
"eslint-plugin-svelte3": "^4.0.0", "eslint-plugin-svelte3": "^4.0.0",
"prettier": "2.8.1", "prettier": "2.8.1",
"prettier-plugin-svelte": "^2.8.1", "prettier-plugin-svelte": "^2.8.1",
"turbo": "1.10.1", "turbo": "1.8.8",
"typescript": "4.9.4" "typescript": "4.9.4"
}, },
"engines": { "engines": {
@@ -96,8 +97,6 @@
"packages/core/src/lib/pages/styles.ts", "packages/core/src/lib/pages/styles.ts",
"packages/frameworks-sveltekit/package", "packages/frameworks-sveltekit/package",
"packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*", "packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*",
"packages/next-auth/src/providers/oauth-types.ts",
"packages/next-auth/css/index.css",
".branches", ".branches",
"db.sqlite", "db.sqlite",
"dev.db", "dev.db",
@@ -248,8 +247,10 @@
"overrides": [ "overrides": [
{ {
"files": [ "files": [
"apps/dev/nextjs/pages/api/auth/[...nextauth].ts", "apps/dev/nextjs/pages/api/auth-old/[...nextauth].ts",
"docs/{sidebars,docusaurus.config}.js" "apps/dev/nextjs/app/api/auth/[...nextauth]/route.ts",
"docs/{sidebars,docusaurus.config}.js",
"packages/next-auth/src/lib/env.ts"
], ],
"options": { "options": {
"printWidth": 150 "printWidth": 150

View File

@@ -8,14 +8,14 @@
</a> </a>
<h3 align="center"><b>Prisma Adapter</b> - NextAuth.js / Auth.js</a></h3> <h3 align="center"><b>Prisma Adapter</b> - NextAuth.js / Auth.js</a></h3>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<a href="https://npm.im/@auth/prisma-adapter"> <a href="https://npm.im/@next-auth/prisma-adapter">
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" /> <img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
</a> </a>
<a href="https://npm.im/@auth/prisma-adapter"> <a href="https://npm.im/@next-auth/prisma-adapter">
<img alt="npm" src="https://img.shields.io/npm/v/@auth/prisma-adapter?color=green&label=@auth/prisma-adapter&style=flat-square"> <img alt="npm" src="https://img.shields.io/npm/v/@next-auth/prisma-adapter?color=green&label=@next-auth/prisma-adapter&style=flat-square">
</a> </a>
<a href="https://www.npmtrends.com/@auth/prisma-adapter"> <a href="https://www.npmtrends.com/@next-auth/prisma-adapter">
<img src="https://img.shields.io/npm/dm/@auth/prisma-adapter?label=%20downloads&style=flat-square" alt="Downloads" /> <img src="https://img.shields.io/npm/dm/@next-auth/prisma-adapter?label=%20downloads&style=flat-square" alt="Downloads" />
</a> </a>
<a href="https://github.com/nextauthjs/next-auth/stargazers"> <a href="https://github.com/nextauthjs/next-auth/stargazers">
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" /> <img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" />

View File

@@ -1,29 +1,14 @@
{ {
"name": "@auth/prisma-adapter", "name": "@next-auth/prisma-adapter",
"version": "1.0.0", "version": "1.0.6",
"description": "Prisma adapter for Auth.js", "description": "Prisma adapter for next-auth.",
"homepage": "https://authjs.dev/reference/adapter/prisma", "homepage": "https://authjs.dev",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
}, },
"author": "William Luke", "author": "William Luke",
"contributors": [ "main": "dist/index.js",
"Balázs Orbán <info@balazsorban.com>"
],
"type": "module",
"types": "./index.d.ts",
"files": [
"*.js",
"*.d.ts*",
"src"
],
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.js"
}
},
"license": "ISC", "license": "ISC",
"keywords": [ "keywords": [
"next-auth", "next-auth",
@@ -47,19 +32,22 @@
"dev": "prisma generate && tsc -w", "dev": "prisma generate && tsc -w",
"studio": "prisma studio" "studio": "prisma studio"
}, },
"dependencies": { "files": [
"@auth/core": "workspace:*" "README.md",
}, "dist"
],
"peerDependencies": { "peerDependencies": {
"@prisma/client": ">=2.26.0 || >=3 || >=4" "@prisma/client": ">=2.26.0 || >=3",
"next-auth": "^4"
}, },
"devDependencies": { "devDependencies": {
"@next-auth/adapter-test": "workspace:*", "@next-auth/adapter-test": "workspace:*",
"@next-auth/tsconfig": "workspace:*", "@next-auth/tsconfig": "workspace:*",
"@prisma/client": "^4.15.0", "@prisma/client": "^3.10.0",
"jest": "^27.4.3", "jest": "^27.4.3",
"mongodb": "^4.4.0", "mongodb": "^4.4.0",
"prisma": "^4.15.0" "next-auth": "workspace:*",
"prisma": "^3.10.0"
}, },
"jest": { "jest": {
"preset": "@next-auth/adapter-test/jest" "preset": "@next-auth/adapter-test/jest"

View File

@@ -9,14 +9,14 @@
* ## Installation * ## Installation
* *
* ```bash npm2yarn2pnpm * ```bash npm2yarn2pnpm
* npm install @prisma/client @auth/prisma-adapter * npm install next-auth @prisma/client @next-auth/prisma-adapter
* npm install prisma --save-dev * npm install prisma --save-dev
* ``` * ```
* *
* @module @auth/prisma-adapter * @module @next-auth/prisma-adapter
*/ */
import type { PrismaClient, Prisma } from "@prisma/client" import type { PrismaClient, Prisma } from "@prisma/client"
import type { Adapter, AdapterAccount } from "@auth/core/adapters" import type { Adapter, AdapterAccount } from "next-auth/adapters"
/** /**
* ## Setup * ## Setup
@@ -26,7 +26,7 @@ import type { Adapter, AdapterAccount } from "@auth/core/adapters"
* ```js title="pages/api/auth/[...nextauth].js" * ```js title="pages/api/auth/[...nextauth].js"
* import NextAuth from "next-auth" * import NextAuth from "next-auth"
* import GoogleProvider from "next-auth/providers/google" * import GoogleProvider from "next-auth/providers/google"
* import { PrismaAdapter } from "@auth/prisma-adapter" * import { PrismaAdapter } from "@next-auth/prisma-adapter"
* import { PrismaClient } from "@prisma/client" * import { PrismaClient } from "@prisma/client"
* *
* const prisma = new PrismaClient() * const prisma = new PrismaClient()
@@ -42,6 +42,8 @@ import type { Adapter, AdapterAccount } from "@auth/core/adapters"
* }) * })
* ``` * ```
* *
* ## Advanced usage
*
* ### Create the Prisma schema from scratch * ### Create the Prisma schema from scratch
* *
* You need to use at least Prisma 2.26.0. Create a schema file in `prisma/schema.prisma` similar to this one: * You need to use at least Prisma 2.26.0. Create a schema file in `prisma/schema.prisma` similar to this one:

View File

@@ -1,25 +1,9 @@
{ {
"extends": "@next-auth/tsconfig/tsconfig.base.json", "extends": "@next-auth/tsconfig/tsconfig.adapters.json",
"compilerOptions": { "compilerOptions": {
"allowJs": true,
"baseUrl": ".",
"isolatedModules": true,
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"outDir": ".",
"rootDir": "src", "rootDir": "src",
"skipDefaultLibCheck": true, "outDir": "dist"
"strictNullChecks": true,
"stripInternal": true,
"declarationMap": true,
"declaration": true
}, },
"include": [ "include": ["."],
"src/**/*" "exclude": ["tests", "dist", "jest.config.js"]
], }
"exclude": [
"*.js",
"*.d.ts",
]
}

View File

@@ -1,4 +1,4 @@
import type { Adapter } from "@auth/core/adapters" import type { Adapter } from "next-auth/adapters"
import { createHash, randomUUID } from "crypto" import { createHash, randomUUID } from "crypto"
const requiredMethods = [ const requiredMethods = [
@@ -58,8 +58,7 @@ export async function runBasicTests(options: TestOptions) {
await options.db.connect?.() await options.db.connect?.()
}) })
const { adapter: _adapter, db, skipTests } = options const { adapter, db, skipTests } = options
const adapter = _adapter as Required<Adapter>
afterAll(async () => { afterAll(async () => {
// @ts-expect-error This is only used for the TypeORM adapter // @ts-expect-error This is only used for the TypeORM adapter
@@ -89,7 +88,7 @@ export async function runBasicTests(options: TestOptions) {
providerAccountId: randomUUID(), providerAccountId: randomUUID(),
type: "oauth", type: "oauth",
access_token: randomUUID(), access_token: randomUUID(),
expires_at: ONE_MONTH / 1000, expires_at: ONE_MONTH,
id_token: randomUUID(), id_token: randomUUID(),
refresh_token: randomUUID(), refresh_token: randomUUID(),
token_type: "bearer", token_type: "bearer",

View File

@@ -12,13 +12,13 @@
"license": "ISC", "license": "ISC",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@auth/core": "workspace:*",
"@babel/cli": "^7.14.3", "@babel/cli": "^7.14.3",
"@babel/plugin-transform-runtime": "^7.14.3", "@babel/plugin-transform-runtime": "^7.14.3",
"@babel/preset-env": "^7.14.2", "@babel/preset-env": "^7.14.2",
"@types/jest": "^26.0.23", "@types/jest": "^26.0.23",
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"jest": "^27.0.3", "jest": "^27.0.3",
"next-auth": "workspace:*",
"ts-jest": "^27.0.3", "ts-jest": "^27.0.3",
"typescript": "^4.2.4" "typescript": "^4.2.4"
} }

View File

@@ -8,14 +8,14 @@
</a> </a>
<h3 align="center"><b>TypeORM Adapter</b> - NextAuth.js / Auth.js</a></h3> <h3 align="center"><b>TypeORM Adapter</b> - NextAuth.js / Auth.js</a></h3>
<p align="center" style="align: center;"> <p align="center" style="align: center;">
<a href="https://npm.im/@auth/typeorm-adapter"> <a href="https://npm.im/@next-auth/typeorm-legacy-adapter">
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" /> <img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
</a> </a>
<a href="https://npm.im/@auth/typeorm-adapter"> <a href="https://npm.im/@next-auth/typeorm-legacy-adapter">
<img alt="npm" src="https://img.shields.io/npm/v/@auth/typeorm-adapter?color=green&label=@auth/typeorm-adapter&style=flat-square"> <img alt="npm" src="https://img.shields.io/npm/v/@next-auth/typeorm-legacy-adapter?color=green&label=@next-auth/typeorm-legacy-adapter&style=flat-square">
</a> </a>
<a href="https://www.npmtrends.com/@auth/typeorm-adapter"> <a href="https://www.npmtrends.com/@next-auth/typeorm-legacy-adapter">
<img src="https://img.shields.io/npm/dm/@auth/typeorm-adapter?label=%20downloads&style=flat-square" alt="Downloads" /> <img src="https://img.shields.io/npm/dm/@next-auth/typeorm-legacy-adapter?label=%20downloads&style=flat-square" alt="Downloads" />
</a> </a>
<a href="https://github.com/nextauthjs/next-auth/stargazers"> <a href="https://github.com/nextauthjs/next-auth/stargazers">
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" /> <img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" />

View File

@@ -1,8 +1,8 @@
{ {
"name": "@auth/typeorm-adapter", "name": "@next-auth/typeorm-legacy-adapter",
"version": "1.0.0", "version": "2.0.2",
"description": "TypeORM adapter for Auth.js.", "description": "TypeORM (legacy) adapter for next-auth.",
"homepage": "https://authjs.dev/reference/adapter/typeorm", "homepage": "https://authjs.dev",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",
"bugs": { "bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues" "url": "https://github.com/nextauthjs/next-auth/issues"
@@ -11,19 +11,11 @@
"contributors": [ "contributors": [
"Balázs Orbán <info@balazsorban.com>" "Balázs Orbán <info@balazsorban.com>"
], ],
"type": "module", "main": "dist/index.js",
"types": "./index.d.ts",
"files": [ "files": [
"*.js", "README.md",
"*.d.ts*", "dist"
"src"
], ],
"exports": {
".": {
"types": "./index.d.ts",
"import": "./index.js"
}
},
"license": "ISC", "license": "ISC",
"keywords": [ "keywords": [
"next-auth", "next-auth",
@@ -46,27 +38,26 @@
"test:containers": "tests/test.sh", "test:containers": "tests/test.sh",
"test": "tests/test.sh" "test": "tests/test.sh"
}, },
"dependencies": {
"@auth/core": "workspace:*"
},
"devDependencies": { "devDependencies": {
"@next-auth/adapter-test": "workspace:*", "@next-auth/adapter-test": "workspace:*",
"@next-auth/tsconfig": "workspace:*", "@next-auth/tsconfig": "workspace:*",
"jest": "^27.4.3", "jest": "^27.4.3",
"mssql": "^7.2.1", "mssql": "^7.2.1",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"next-auth": "workspace:*",
"pg": "^8.7.3", "pg": "^8.7.3",
"sqlite3": "^5.0.8", "sqlite3": "^5.0.8",
"typeorm": "0.3.15", "typeorm": "0.3.7",
"typeorm-naming-strategies": "^4.1.0", "typeorm-naming-strategies": "^4.1.0",
"typescript": "^4.7.4" "typescript": "^4.7.4"
}, },
"peerDependencies": { "peerDependencies": {
"mssql": "^6.2.1 || 7", "mssql": "^6.2.1 || 7",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"next-auth": "^4",
"pg": "^8.2.1", "pg": "^8.2.1",
"sqlite3": "^5.0.2", "sqlite3": "^5.0.2",
"typeorm": "^0.3.7" "typeorm": "0.3.7"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"mysql": { "mysql": {

View File

@@ -9,17 +9,17 @@
* ## Installation * ## Installation
* *
* ```bash npm2yarn2pnpm * ```bash npm2yarn2pnpm
* npm install @auth/typeorm-adapter typeorm * npm install next-auth @next-auth/typeorm-legacy-adapter typeorm
* ``` * ```
* *
* @module @auth/typeorm-adapter * @module @next-auth/typeorm-legacy-adapter
*/ */
import type { import type {
Adapter, Adapter,
AdapterUser, AdapterUser,
AdapterAccount, AdapterAccount,
AdapterSession, AdapterSession,
} from "@auth/core/adapters" } from "next-auth/adapters"
import { DataSourceOptions, DataSource, EntityManager } from "typeorm" import { DataSourceOptions, DataSource, EntityManager } from "typeorm"
import * as defaultEntities from "./entities" import * as defaultEntities from "./entities"
import { parseDataSourceConfig, updateConnectionEntities } from "./utils" import { parseDataSourceConfig, updateConnectionEntities } from "./utils"
@@ -29,7 +29,7 @@ export const entities = defaultEntities
export type Entities = typeof entities export type Entities = typeof entities
/** This is the interface for the TypeORM adapter options. */ /** This is the interface for the TypeORM adapter options. */
export interface TypeORMAdapterOptions { export interface TypeORMLegacyAdapterOptions {
/** /**
* The {@link https://orkhan.gitbook.io/typeorm/docs/entities TypeORM entities} to create the database tables from. * The {@link https://orkhan.gitbook.io/typeorm/docs/entities TypeORM entities} to create the database tables from.
*/ */
@@ -70,16 +70,16 @@ export async function getManager(options: {
* *
* ```javascript title="pages/api/auth/[...nextauth].js" * ```javascript title="pages/api/auth/[...nextauth].js"
* import NextAuth from "next-auth" * import NextAuth from "next-auth"
* import { TypeORMAdapter } from "@auth/typeorm-adapter" * import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
* *
* *
* export default NextAuth({ * export default NextAuth({
* adapter: TypeORMAdapter("yourconnectionstring"), * adapter: TypeORMLegacyAdapter("yourconnectionstring"),
* ... * ...
* }) * })
* ``` * ```
* *
* `TypeORMAdapter` takes either a connection string, or a [`ConnectionOptions`](https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md) object as its first parameter. * `TypeORMLegacyAdapter` takes either a connection string, or a [`ConnectionOptions`](https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md) object as its first parameter.
* *
* ## Advanced usage * ## Advanced usage
* *
@@ -93,7 +93,7 @@ export async function getManager(options: {
* *
* 1. Create a file containing your modified entities: * 1. Create a file containing your modified entities:
* *
* (The file below is based on the [default entities](https://github.com/nextauthjs/next-auth/blob/main/packages/adapter-typeorm/src/entities.ts)) * (The file below is based on the [default entities](https://github.com/nextauthjs/next-auth/blob/main/packages/adapter-typeorm-legacy/src/entities.ts))
* *
* ```diff title="lib/entities.ts" * ```diff title="lib/entities.ts"
* import { * import {
@@ -231,15 +231,15 @@ export async function getManager(options: {
* } * }
* ``` * ```
* *
* 2. Pass them to `TypeORMAdapter` * 2. Pass them to `TypeORMLegacyAdapter`
* *
* ```javascript title="pages/api/auth/[...nextauth].js" * ```javascript title="pages/api/auth/[...nextauth].js"
* import NextAuth from "next-auth" * import NextAuth from "next-auth"
* import { TypeORMAdapter } from "@auth/typeorm-adapter" * import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
* import * as entities from "lib/entities" * import * as entities from "lib/entities"
* *
* export default NextAuth({ * export default NextAuth({
* adapter: TypeORMAdapter("yourconnectionstring", { entities }), * adapter: TypeORMLegacyAdapter("yourconnectionstring", { entities }),
* ... * ...
* }) * })
* ``` * ```
@@ -260,7 +260,7 @@ export async function getManager(options: {
* *
* ```javascript title="pages/api/auth/[...nextauth].js" * ```javascript title="pages/api/auth/[...nextauth].js"
* import NextAuth from "next-auth" * import NextAuth from "next-auth"
* import { TypeORMAdapter } from "@auth/typeorm-adapter" * import { TypeORMLegacyAdapter } from "@next-auth/typeorm-legacy-adapter"
* import { SnakeNamingStrategy } from 'typeorm-naming-strategies' * import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
* import { ConnectionOptions } from "typeorm" * import { ConnectionOptions } from "typeorm"
* *
@@ -275,14 +275,14 @@ export async function getManager(options: {
* } * }
* *
* export default NextAuth({ * export default NextAuth({
* adapter: TypeORMAdapter(connection), * adapter: TypeORMLegacyAdapter(connection),
* ... * ...
* }) * })
* ``` * ```
*/ */
export function TypeORMAdapter( export function TypeORMLegacyAdapter(
dataSource: string | DataSourceOptions, dataSource: string | DataSourceOptions,
options?: TypeORMAdapterOptions options?: TypeORMLegacyAdapterOptions
): Adapter { ): Adapter {
const entities = options?.entities const entities = options?.entities
const c = { const c = {
@@ -328,10 +328,8 @@ export function TypeORMAdapter(
}, },
async getUserByAccount(provider_providerAccountId) { async getUserByAccount(provider_providerAccountId) {
const m = await getManager(c) const m = await getManager(c)
// @ts-expect-error
const account = await m.findOne<AdapterAccount & { user: AdapterUser }>( const account = await m.findOne<AdapterAccount & { user: AdapterUser }>(
"AccountEntity", "AccountEntity",
// @ts-expect-error
{ where: provider_providerAccountId, relations: ["user"] } { where: provider_providerAccountId, relations: ["user"] }
) )
if (!account) return null if (!account) return null

View File

@@ -1,5 +1,5 @@
import { runBasicTests } from "../../../adapter-test" import { runBasicTests } from "../../../adapter-test"
import { TypeORMAdapter } from "../../src" import { TypeORMLegacyAdapter } from "../../src"
import * as entities from "../custom-entities" import * as entities from "../custom-entities"
import { db } from "../helpers" import { db } from "../helpers"
import { SnakeNamingStrategy } from "typeorm-naming-strategies" import { SnakeNamingStrategy } from "typeorm-naming-strategies"
@@ -18,7 +18,7 @@ const mysqlConfig: ConnectionOptions = {
} }
runBasicTests({ runBasicTests({
adapter: TypeORMAdapter(mysqlConfig, { adapter: TypeORMLegacyAdapter(mysqlConfig, {
entities, entities,
}), }),
db: db(mysqlConfig, entities), db: db(mysqlConfig, entities),

View File

@@ -1,5 +1,5 @@
import { runBasicTests } from "../../../adapter-test" import { runBasicTests } from "../../../adapter-test"
import { TypeORMAdapter } from "../../src" import { TypeORMLegacyAdapter } from "../../src"
import { db } from "../helpers" import { db } from "../helpers"
const mysqlConfig = { const mysqlConfig = {
@@ -13,6 +13,6 @@ const mysqlConfig = {
} }
runBasicTests({ runBasicTests({
adapter: TypeORMAdapter(mysqlConfig), adapter: TypeORMLegacyAdapter(mysqlConfig),
db: db(mysqlConfig), db: db(mysqlConfig),
}) })

View File

@@ -1,5 +1,5 @@
import { runBasicTests } from "../../../adapter-test" import { runBasicTests } from "../../../adapter-test"
import { TypeORMAdapter } from "../../src" import { TypeORMLegacyAdapter } from "../../src"
import * as entities from "../custom-entities" import * as entities from "../custom-entities"
import { db } from "../helpers" import { db } from "../helpers"
@@ -7,7 +7,7 @@ const postgresConfig =
"postgres://nextauth:password@localhost:5432/nextauth?synchronize=true" "postgres://nextauth:password@localhost:5432/nextauth?synchronize=true"
runBasicTests({ runBasicTests({
adapter: TypeORMAdapter(postgresConfig, { adapter: TypeORMLegacyAdapter(postgresConfig, {
entities, entities,
}), }),
db: db(postgresConfig, entities), db: db(postgresConfig, entities),

View File

@@ -1,11 +1,11 @@
import { runBasicTests } from "../../../adapter-test" import { runBasicTests } from "../../../adapter-test"
import { TypeORMAdapter } from "../../src" import { TypeORMLegacyAdapter } from "../../src"
import { db } from "../helpers" import { db } from "../helpers"
const postgresConfig = const postgresConfig =
"postgres://nextauth:password@localhost:5432/nextauth?synchronize=true" "postgres://nextauth:password@localhost:5432/nextauth?synchronize=true"
runBasicTests({ runBasicTests({
adapter: TypeORMAdapter(postgresConfig), adapter: TypeORMLegacyAdapter(postgresConfig),
db: db(postgresConfig), db: db(postgresConfig),
}) })

View File

@@ -1,5 +1,5 @@
import { runBasicTests } from "../../../adapter-test" import { runBasicTests } from "../../../adapter-test"
import { TypeORMAdapter } from "../../src" import { TypeORMLegacyAdapter } from "../../src"
import * as entities from "../custom-entities" import * as entities from "../custom-entities"
import { db } from "../helpers" import { db } from "../helpers"
@@ -11,7 +11,7 @@ const sqliteConfig = {
} }
runBasicTests({ runBasicTests({
adapter: TypeORMAdapter(sqliteConfig, { adapter: TypeORMLegacyAdapter(sqliteConfig, {
entities, entities,
}), }),
db: db(sqliteConfig, entities), db: db(sqliteConfig, entities),

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