mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
70 Commits
@next-auth
...
next-auth@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24945895e9 | ||
|
|
6deccf610f | ||
|
|
f770b90219 | ||
|
|
87f4786917 | ||
|
|
191ef06471 | ||
|
|
75e6d8f0aa | ||
|
|
17999edd30 | ||
|
|
54b1845e58 | ||
|
|
879faf9fab | ||
|
|
3e3c36891e | ||
|
|
ac5d8a9795 | ||
|
|
965c6267e2 | ||
|
|
bfc429d20b | ||
|
|
2d8e910a19 | ||
|
|
d16e04848e | ||
|
|
ff3a52895b | ||
|
|
e6e03e8842 | ||
|
|
715aad9474 | ||
|
|
902bf92a85 | ||
|
|
44f2a47e6e | ||
|
|
a3b92dbaec | ||
|
|
bdd3ab2816 | ||
|
|
ba55f06585 | ||
|
|
d2b877fb28 | ||
|
|
658b22d9fb | ||
|
|
a0beb02f77 | ||
|
|
5727c5f4e6 | ||
|
|
8104cb1287 | ||
|
|
44aaa6f1c3 | ||
|
|
ba20974b5f | ||
|
|
14b4ed1d8a | ||
|
|
6b3a82d1f5 | ||
|
|
600aaaa7e6 | ||
|
|
f1d3bc26f9 | ||
|
|
78664aab37 | ||
|
|
aeb3a44b27 | ||
|
|
d3571e01ba | ||
|
|
3b7c9886c3 | ||
|
|
39fec738c6 | ||
|
|
fa58143c6b | ||
|
|
26fb89e3c4 | ||
|
|
a82cbf5ddf | ||
|
|
24db833685 | ||
|
|
c57a810042 | ||
|
|
d980fa986b | ||
|
|
4676352ae0 | ||
|
|
c8780122b3 | ||
|
|
3131971e2c | ||
|
|
448ec1017a | ||
|
|
0e9404ebc1 | ||
|
|
d349ae2b1b | ||
|
|
32f4d5000e | ||
|
|
7f2dbfc65b | ||
|
|
a03657e615 | ||
|
|
3e312d0df1 | ||
|
|
d9167bbffe | ||
|
|
526a6c1adc | ||
|
|
ad03a4efc1 | ||
|
|
424af6cbc5 | ||
|
|
a3c6786f78 | ||
|
|
385037ab33 | ||
|
|
26a03da621 | ||
|
|
afb1fcdae3 | ||
|
|
a21db8950f | ||
|
|
e8371ab23a | ||
|
|
9cdeb2ce7d | ||
|
|
89829d8a88 | ||
|
|
aedabc8d3f | ||
|
|
9f2cdad457 | ||
|
|
b107ca4946 |
27
.eslintrc.js
Normal file
27
.eslintrc.js
Normal file
@@ -0,0 +1,27 @@
|
||||
const path = require("path")
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
project: [path.resolve(__dirname, "./packages/**/tsconfig.eslint.json")],
|
||||
},
|
||||
extends: ["standard-with-typescript", "prettier"],
|
||||
globals: {
|
||||
localStorage: "readonly",
|
||||
location: "readonly",
|
||||
fetch: "readonly",
|
||||
},
|
||||
rules: {
|
||||
camelcase: "off",
|
||||
"@typescript-eslint/naming-convention": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
},
|
||||
plugins: ["jest"],
|
||||
env: {
|
||||
"jest/globals": true,
|
||||
},
|
||||
ignorePatterns: [".eslintrc.js"],
|
||||
}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,6 +35,7 @@ packages/next-auth/core
|
||||
packages/next-auth/jwt
|
||||
packages/next-auth/react
|
||||
packages/next-auth/adapters.d.ts
|
||||
packages/next-auth/adapters.js
|
||||
packages/next-auth/index.d.ts
|
||||
packages/next-auth/index.js
|
||||
packages/next-auth/next
|
||||
|
||||
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting me@iaincollins.com or info@balazsorban.com and yo@ndo.dev.
|
||||
reported by contacting info@balazsorban.com, yo@ndo.dev, thvu@hey.com and me@iaincollins.com.
|
||||
All complaints will be reviewed and investigated and will result in a response
|
||||
that is deemed necessary and appropriate to the circumstances. The project team
|
||||
is obligated to maintain confidentiality with regard to the reporter of an
|
||||
|
||||
@@ -13,9 +13,9 @@ If you contact us regarding a serious issue:
|
||||
- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
|
||||
- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
|
||||
|
||||
The best way to report an issue is by contacting us via email at info@balazsorban.com or me@iaincollins.com and yo@ndo.dev, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||
The best way to report an issue is by contacting us via email at info@balazsorban.com, yo@ndo.dev, thvu@hey.com and me@iaincollins.com, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||
|
||||
> For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these these publically as bug reports or feature requests or to raise a question to open a discussion around them.
|
||||
> For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these publicly as bug reports or feature requests or to raise a question to open a discussion around them.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
|
||||
@@ -5,5 +5,4 @@ module.exports = {
|
||||
return config
|
||||
},
|
||||
typescript: { ignoreBuildErrors: true },
|
||||
experimental: { externalDir: true },
|
||||
}
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"clean": "rm -rf .next",
|
||||
"copy:css": "cpx \"../../packages/next-auth/css/**/*\" src/css --watch",
|
||||
"watch:css": "cd ../../packages/next-auth && pnpm watch:css",
|
||||
"dev": "concurrently \"pnpm dev:next\" \"pnpm watch:css\" \"pnpm copy:css\"",
|
||||
"dev:next": "next dev",
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"email": "fake-smtp-server",
|
||||
@@ -22,6 +19,7 @@
|
||||
"@prisma/client": "^3",
|
||||
"faunadb": "^4",
|
||||
"next": "12.2.0",
|
||||
"next-auth": "workspace:*",
|
||||
"nodemailer": "^6",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
@@ -29,8 +27,6 @@
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"concurrently": "^7",
|
||||
"cpx": "^1.5.0",
|
||||
"fake-smtp-server": "^0.8.0",
|
||||
"pg": "^8.7.3",
|
||||
"prisma": "^3",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// This is an example of to protect 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, options)
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
|
||||
if (session) {
|
||||
res.send({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// 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)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import Layout from "../components/layout"
|
||||
import { authOptions } from './api/auth/[...nextauth]';
|
||||
|
||||
export default function Page() {
|
||||
// As this page uses Server Side Rendering, the `session` will be already
|
||||
@@ -40,8 +41,8 @@ export async function getServerSideProps(context) {
|
||||
return {
|
||||
props: {
|
||||
session: await unstable_getServerSession(
|
||||
contex.req,
|
||||
contex.res,
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
),
|
||||
},
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
"incremental": true,
|
||||
"jsx": "preserve",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"next-auth": ["../../packages/next-auth/src"],
|
||||
"next-auth/*": ["../../packages/next-auth/src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules", "jest.config.js"]
|
||||
|
||||
@@ -2,12 +2,16 @@ 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 }: AppProps) {
|
||||
export default function App({
|
||||
Component,
|
||||
pageProps: { session, ...pageProps },
|
||||
}: AppProps<{ session: Session }>) {
|
||||
return (
|
||||
<SessionProvider session={pageProps.session} refetchInterval={0}>
|
||||
<SessionProvider session={session}>
|
||||
<Component {...pageProps} />
|
||||
</SessionProvider>
|
||||
)
|
||||
|
||||
@@ -4,8 +4,7 @@ import Layout from "../components/layout"
|
||||
import AccessDenied from "../components/access-denied"
|
||||
|
||||
export default function ProtectedPage() {
|
||||
const { data: session, status } = useSession()
|
||||
const loading = status === "loading"
|
||||
const { data: session } = useSession()
|
||||
const [content, setContent] = useState()
|
||||
|
||||
// Fetch content from protected route
|
||||
@@ -19,9 +18,7 @@ export default function ProtectedPage() {
|
||||
}
|
||||
fetchData()
|
||||
}, [session])
|
||||
|
||||
// When rendering client side don't display anything until loading is complete
|
||||
if (typeof window !== "undefined" && loading) return null
|
||||
|
||||
|
||||
// If no session exists, display access denied message
|
||||
if (!session) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VITE_GITHUB_CLIENT_ID=
|
||||
VITE_GITHUB_CLIENT_SECRET=
|
||||
VITE_NEXTAUTH_URL=
|
||||
VITE_NEXTAUTH_SECRET=
|
||||
GITHUB_CLIENT_ID=
|
||||
GITHUB_CLIENT_SECRET=
|
||||
NEXTAUTH_SECRET=
|
||||
PUBLIC_NEXTAUTH_URL=http://localhost:5173
|
||||
@@ -6,82 +6,60 @@ SvelteKit support with NextAuth.js is currently experimental. This directory con
|
||||
|
||||
## Existing Project
|
||||
|
||||
### Add API route
|
||||
### Add API Route
|
||||
|
||||
To add NextAuth.js to a project create a file called `[...nextauth].js` in routes/api/auth. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
|
||||
To add NextAuth.js to a project create a file called `[...nextauth]/+server.js` in routes/api/auth. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
|
||||
|
||||
```ts
|
||||
import NextAuth from "$lib"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
import { NextAuth, options } from "$lib/next-auth"
|
||||
|
||||
const nextAuthOptions = {
|
||||
// Configure one or more authentication providers
|
||||
providers: [
|
||||
GithubProvider({
|
||||
clientId: import.meta.env.VITE_GITHUB_CLIENT_ID,
|
||||
clientSecret: import.meta.env.VITE_GITHUB_CLIENT_SECRET,
|
||||
}),
|
||||
// ...add more providers here
|
||||
],
|
||||
}
|
||||
|
||||
export const { get, post } = NextAuth(nextAuthOptions)
|
||||
export const { GET, POST } = NextAuth(options)
|
||||
```
|
||||
|
||||
### Add [hook](https://kit.svelte.dev/docs/hooks)
|
||||
|
||||
```ts
|
||||
import { getServerSession } from "$lib"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
import type { Handle } from "@sveltejs/kit"
|
||||
import { getServerSession, options as nextAuthOptions } from "$lib/next-auth"
|
||||
|
||||
const nextAuthOptions = {
|
||||
providers: [
|
||||
GithubProvider({
|
||||
clientId: import.meta.env.VITE_GITHUB_CLIENT_ID,
|
||||
clientSecret: import.meta.env.VITE_GITHUB_CLIENT_SECRET,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
export async function handle({ event, resolve }) {
|
||||
export const handle: Handle = async function handle({
|
||||
event,
|
||||
resolve,
|
||||
}): Promise<Response> {
|
||||
const session = await getServerSession(event.request, nextAuthOptions)
|
||||
event.locals.session = session
|
||||
|
||||
return resolve(event)
|
||||
}
|
||||
```
|
||||
|
||||
export function getSession(event) {
|
||||
return event.locals.session || {}
|
||||
### Load Session from Primary Layout
|
||||
|
||||
```ts
|
||||
// src/lib/routes/+layout.server.ts
|
||||
import type { LayoutServerLoad } from "./$types"
|
||||
|
||||
export const load: LayoutServerLoad = ({ locals }) => {
|
||||
return {
|
||||
session: locals.session,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Protecting a route
|
||||
### Protecting a Route
|
||||
|
||||
```html
|
||||
<script context="module">
|
||||
export async function load({ session }) {
|
||||
const { user } = session
|
||||
```ts
|
||||
// src/lib/routes/protected/+page.ts
|
||||
import { redirect } from "@sveltejs/kit"
|
||||
import type { PageLoad } from "./$types"
|
||||
|
||||
if (!user) {
|
||||
return {
|
||||
status: 302,
|
||||
redirect: "/",
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
session,
|
||||
},
|
||||
}
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { session } = await parent()
|
||||
if (!session?.user) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
export let session
|
||||
</script>
|
||||
|
||||
<p>Session expiry: {session.expires}</p>
|
||||
return {}
|
||||
}
|
||||
```
|
||||
|
||||
## Packaging lib
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
{
|
||||
"name": "sveltekit-nextauth",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "svelte-kit dev",
|
||||
"build": "svelte-kit build",
|
||||
"preview": "svelte-kit preview",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
|
||||
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"lint": "prettier --check . && eslint .",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "next",
|
||||
"@sveltejs/kit": "next",
|
||||
"@types/cookie": "^0.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.1",
|
||||
"@typescript-eslint/parser": "^5.10.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-svelte3": "^3.2.1",
|
||||
"prettier": "^2.5.1",
|
||||
"prettier-plugin-svelte": "^2.5.0",
|
||||
"@sveltejs/adapter-auto": "1.0.0-next.66",
|
||||
"@sveltejs/kit": "1.0.0-next.443",
|
||||
"@types/cookie": "^0.5.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.35.1",
|
||||
"@typescript-eslint/parser": "^5.35.1",
|
||||
"eslint": "^8.22.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier-plugin-svelte": "^2.7.0",
|
||||
"svelte": "^3.49.0",
|
||||
"svelte-check": "^2.2.6",
|
||||
"svelte-preprocess": "^4.10.1",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "~4.5.4"
|
||||
"svelte-check": "^2.8.1",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "~4.8.2",
|
||||
"vite": "^2.9.13"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"cookie": "0.4.1",
|
||||
"next-auth": "workspace:*"
|
||||
"cookie": "0.5.0",
|
||||
"next-auth": "latest"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
|
||||
27
apps/playground-sveltekit/src/app.d.ts
vendored
27
apps/playground-sveltekit/src/app.d.ts
vendored
@@ -1,13 +1,30 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
import type {
|
||||
User as NextAuthUser,
|
||||
Session as NextAuthSession,
|
||||
} from "next-auth"
|
||||
|
||||
// optionally extend the `user`
|
||||
interface User extends NextAuthUser {
|
||||
// add custom fields here
|
||||
}
|
||||
|
||||
interface AppSession extends NextAuthSession {
|
||||
user: User
|
||||
}
|
||||
|
||||
// See https://kit.svelte.dev/docs/typescript
|
||||
// for information about these interfaces
|
||||
declare namespace App {
|
||||
interface Locals {}
|
||||
declare global {
|
||||
declare namespace App {
|
||||
interface Locals {
|
||||
session: AppSession
|
||||
}
|
||||
|
||||
interface Platform {}
|
||||
interface Platform {}
|
||||
|
||||
interface Session {}
|
||||
interface Session extends AppSession {}
|
||||
|
||||
interface Stuff {}
|
||||
interface Stuff {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="" />
|
||||
<link rel="icon" href="%svelte.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%svelte.head%
|
||||
</head>
|
||||
<body>
|
||||
<div>%svelte.body%</div>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body>
|
||||
<div>%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
8
apps/playground-sveltekit/src/global.d.ts
vendored
8
apps/playground-sveltekit/src/global.d.ts
vendored
@@ -1,8 +0,0 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
VITE_GITHUB_CLIENT_ID: string
|
||||
VITE_GITHUB_CLIENT_SECRET: string
|
||||
VITE_NEXTAUTH_URL: string
|
||||
VITE_NEXTAUTH_SECRET: string
|
||||
}
|
||||
@@ -1,24 +1,12 @@
|
||||
import { getServerSession } from "$lib"
|
||||
import type { Session } from "next-auth"
|
||||
import type { NextAuthOptions } from "next-auth"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
import type { Handle } from "@sveltejs/kit"
|
||||
import { getServerSession, options as nextAuthOptions } from "$lib/next-auth"
|
||||
|
||||
const nextAuthOptions: NextAuthOptions = {
|
||||
providers: [
|
||||
GithubProvider({
|
||||
clientId: import.meta.env.VITE_GITHUB_CLIENT_ID,
|
||||
clientSecret: import.meta.env.VITE_GITHUB_CLIENT_SECRET,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
export async function handle({ event, resolve }): Promise<Response> {
|
||||
export const handle: Handle = async function handle({
|
||||
event,
|
||||
resolve,
|
||||
}): Promise<Response> {
|
||||
const session = await getServerSession(event.request, nextAuthOptions)
|
||||
event.locals.session = session
|
||||
|
||||
return resolve(event)
|
||||
}
|
||||
|
||||
export function getSession(event): Session {
|
||||
return event.locals.session || {}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import NextAuth, { getServerSession } from "./next-auth"
|
||||
|
||||
export default NextAuth
|
||||
export { getServerSession }
|
||||
@@ -1,29 +1,53 @@
|
||||
import type { RequestEvent } from "@sveltejs/kit"
|
||||
import type { IncomingRequest, NextAuthOptions, Session } from "next-auth"
|
||||
import type { NextAuthAction } from "next-auth/lib/types"
|
||||
import type { OutgoingResponse } from "next-auth/core"
|
||||
import type { ServerLoadEvent } from "@sveltejs/kit"
|
||||
import type { RequestInternal } from "next-auth"
|
||||
import type { NextAuthAction, NextAuthOptions } from "next-auth/core/types"
|
||||
import type { OutgoingResponse as NextAuthResponse } from "next-auth/core"
|
||||
import { NextAuthHandler } from "next-auth/core"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
import cookie from "cookie"
|
||||
import {
|
||||
GITHUB_CLIENT_ID,
|
||||
GITHUB_CLIENT_SECRET,
|
||||
NEXTAUTH_SECRET,
|
||||
} from "$env/static/private"
|
||||
import { PUBLIC_NEXTAUTH_URL } from "$env/static/public"
|
||||
import getFormBody from "./utils/get-form-body"
|
||||
|
||||
async function toSvelteKitResponse(
|
||||
request: Request,
|
||||
nextAuthResponse: OutgoingResponse<unknown>
|
||||
) {
|
||||
const { headers, cookies, body, redirect, status = 200 } = nextAuthResponse
|
||||
const github = GithubProvider?.default || GithubProvider
|
||||
|
||||
const response = {
|
||||
status,
|
||||
headers: {},
|
||||
export const options: NextAuthOptions = {
|
||||
providers: [
|
||||
github({
|
||||
clientId: GITHUB_CLIENT_ID,
|
||||
clientSecret: GITHUB_CLIENT_SECRET,
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
const toSvelteKitResponse = async (
|
||||
request: Request,
|
||||
nextAuthResponse: NextAuthResponse<unknown>
|
||||
): Promise<Response> => {
|
||||
const { cookies, redirect } = nextAuthResponse
|
||||
|
||||
const headers = new Headers()
|
||||
for (const header of nextAuthResponse?.headers || []) {
|
||||
// pass headers along from next-auth
|
||||
headers.set(header.key, header.value)
|
||||
}
|
||||
|
||||
headers?.forEach((header) => {
|
||||
response.headers[header.key] = header.value
|
||||
})
|
||||
// set-cookie header
|
||||
if (cookies?.length) {
|
||||
headers.set(
|
||||
"set-cookie",
|
||||
cookies
|
||||
?.map((item) => cookie.serialize(item.name, item.value, item.options))
|
||||
.join(",") as string
|
||||
)
|
||||
}
|
||||
|
||||
response.headers["set-cookie"] = cookies?.map((item) => {
|
||||
return cookie.serialize(item.name, item.value, item.options)
|
||||
})
|
||||
let body = undefined
|
||||
let status = nextAuthResponse.status || 200
|
||||
|
||||
if (redirect) {
|
||||
let formData = null
|
||||
@@ -34,41 +58,45 @@ async function toSvelteKitResponse(
|
||||
// no formData passed
|
||||
}
|
||||
if (formData?.json !== "true") {
|
||||
response.status = 302
|
||||
response.headers["Location"] = redirect
|
||||
status = 302
|
||||
headers.set("Location", redirect)
|
||||
} else {
|
||||
response["body"] = { url: redirect }
|
||||
body = { url: redirect }
|
||||
}
|
||||
} else {
|
||||
response["body"] = body
|
||||
body = nextAuthResponse.body
|
||||
}
|
||||
|
||||
return response
|
||||
// @ts-expect-error - body is a known HTML document or JSON object
|
||||
return new Response(body, {
|
||||
status,
|
||||
headers,
|
||||
})
|
||||
}
|
||||
|
||||
async function SKNextAuthHandler(
|
||||
{ request, url, params }: RequestEvent,
|
||||
const SKNextAuthHandler = async (
|
||||
{ request, url, params }: ServerLoadEvent,
|
||||
options: NextAuthOptions
|
||||
) {
|
||||
const nextauth = params.nextauth.split("/")
|
||||
let body = null
|
||||
): Promise<Response> => {
|
||||
const [action, provider] = params.nextauth!.split("/")
|
||||
let body = undefined
|
||||
try {
|
||||
body = await request.formData()
|
||||
body = getFormBody(body)
|
||||
} catch {
|
||||
// no formData passed
|
||||
}
|
||||
options.secret = import.meta.env.VITE_NEXTAUTH_SECRET
|
||||
const req: IncomingRequest = {
|
||||
host: import.meta.env.VITE_NEXTAUTH_URL,
|
||||
options.secret = NEXTAUTH_SECRET
|
||||
const req: RequestInternal = {
|
||||
host: PUBLIC_NEXTAUTH_URL,
|
||||
body,
|
||||
query: Object.fromEntries(url.searchParams),
|
||||
headers: request.headers,
|
||||
method: request.method,
|
||||
cookies: cookie.parse(request.headers.get("cookie") ?? ""),
|
||||
action: nextauth[0] as NextAuthAction,
|
||||
providerId: nextauth[1],
|
||||
error: nextauth[1],
|
||||
cookies: cookie.parse(request.headers.get("cookie") || ""),
|
||||
action: action as NextAuthAction,
|
||||
providerId: provider,
|
||||
error: provider,
|
||||
}
|
||||
|
||||
const response = await NextAuthHandler({
|
||||
@@ -79,19 +107,18 @@ async function SKNextAuthHandler(
|
||||
return toSvelteKitResponse(request, response)
|
||||
}
|
||||
|
||||
export async function getServerSession(
|
||||
export const getServerSession = async (
|
||||
request: Request,
|
||||
options: NextAuthOptions
|
||||
): Promise<Session | null> {
|
||||
|
||||
options.secret = import.meta.env.VITE_NEXTAUTH_SECRET
|
||||
|
||||
const session = await NextAuthHandler<Session>({
|
||||
): Promise<App.Session | null> => {
|
||||
options.secret = NEXTAUTH_SECRET
|
||||
|
||||
const session = await NextAuthHandler<App.Session>({
|
||||
req: {
|
||||
host: import.meta.env.VITE_NEXTAUTH_URL,
|
||||
host: PUBLIC_NEXTAUTH_URL,
|
||||
action: "session",
|
||||
method: "GET",
|
||||
cookies: cookie.parse(request.headers.get("cookie") ?? ""),
|
||||
cookies: cookie.parse(request.headers.get("cookie") || ""),
|
||||
headers: request.headers,
|
||||
},
|
||||
options,
|
||||
@@ -99,16 +126,18 @@ export async function getServerSession(
|
||||
|
||||
const { body } = session
|
||||
|
||||
if (body && Object.keys(body).length) return body as Session
|
||||
if (body && Object.keys(body).length) {
|
||||
return body as App.Session
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export default (
|
||||
export const NextAuth = (
|
||||
options: NextAuthOptions
|
||||
): {
|
||||
get: (req: RequestEvent) => Promise<unknown>
|
||||
post: (req: RequestEvent) => Promise<unknown>
|
||||
GET: (event) => Promise<unknown>
|
||||
POST: (event) => Promise<unknown>
|
||||
} => ({
|
||||
get: (req) => SKNextAuthHandler(req, options),
|
||||
post: (req) => SKNextAuthHandler(req, options),
|
||||
GET: (event) => SKNextAuthHandler(event, options),
|
||||
POST: (event) => SKNextAuthHandler(event, options),
|
||||
})
|
||||
|
||||
7
apps/playground-sveltekit/src/routes/+layout.server.ts
Normal file
7
apps/playground-sveltekit/src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { LayoutServerLoad } from "./$types"
|
||||
|
||||
export const load: LayoutServerLoad = ({ locals }) => {
|
||||
return {
|
||||
session: locals.session,
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { session } from "$app/stores"
|
||||
import { page } from "$app/stores"
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<header>
|
||||
<div class="signedInStatus">
|
||||
<p class="nojs-show loaded">
|
||||
{#if Object.keys($session).length}
|
||||
{#if $session.user.image}
|
||||
{#if Object.keys($page.data.session || {}).length}
|
||||
{#if $page.data.session.user.image}
|
||||
<span
|
||||
style="background-image: url('{$session.user.image}')"
|
||||
style="background-image: url('{$page.data.session.user.image}')"
|
||||
class="avatar"
|
||||
/>
|
||||
{/if}
|
||||
<span class="signedInText">
|
||||
<small>Signed in as</small><br />
|
||||
<strong>{$session.user.email || $session.user.name}</strong>
|
||||
<strong
|
||||
>{$page.data.session.user.email ||
|
||||
$page.data.session.user.name}</strong
|
||||
>
|
||||
</span>
|
||||
<a href="/api/auth/signout" class="button">Sign out</a>
|
||||
{:else}
|
||||
@@ -38,7 +41,8 @@
|
||||
:global(body) {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
|
||||
"Noto Color Emoji";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
@@ -1,11 +0,0 @@
|
||||
import NextAuth from "$lib"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
|
||||
export const { get, post } = NextAuth({
|
||||
providers: [
|
||||
GithubProvider({
|
||||
clientId: import.meta.env.VITE_GITHUB_CLIENT_ID,
|
||||
clientSecret: import.meta.env.VITE_GITHUB_CLIENT_SECRET,
|
||||
}),
|
||||
],
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
import { NextAuth, options } from "$lib/next-auth"
|
||||
|
||||
export const { GET, POST } = NextAuth(options)
|
||||
@@ -1,27 +0,0 @@
|
||||
<script context="module" lang="ts">
|
||||
export async function load({ session }) {
|
||||
const { user } = session
|
||||
if (!user) {
|
||||
return {
|
||||
status: 302,
|
||||
redirect: "/",
|
||||
}
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
session,
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export let session
|
||||
</script>
|
||||
|
||||
<h1>Protected page</h1>
|
||||
<p>
|
||||
This is a protected content. You can access this content because you are
|
||||
signed in.
|
||||
</p>
|
||||
<p>Session expiry: {session.expires}</p>
|
||||
10
apps/playground-sveltekit/src/routes/protected/+page.svelte
Normal file
10
apps/playground-sveltekit/src/routes/protected/+page.svelte
Normal file
@@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores"
|
||||
</script>
|
||||
|
||||
<h1>Protected page</h1>
|
||||
<p>
|
||||
This is a protected content. You can access this content because you are
|
||||
signed in.
|
||||
</p>
|
||||
<p>Session expiry: {$page.data.session.expires}</p>
|
||||
10
apps/playground-sveltekit/src/routes/protected/+page.ts
Normal file
10
apps/playground-sveltekit/src/routes/protected/+page.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { redirect } from "@sveltejs/kit"
|
||||
import type { PageLoad } from "./$types"
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { session } = await parent()
|
||||
if (!session?.user) {
|
||||
throw redirect(302, "/")
|
||||
}
|
||||
return {}
|
||||
}
|
||||
@@ -9,6 +9,11 @@ const config = {
|
||||
|
||||
kit: {
|
||||
adapter: adapter(),
|
||||
|
||||
// Override http methods in the Todo forms
|
||||
methodOverride: {
|
||||
allowed: ["PATCH", "DELETE"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,17 @@
|
||||
{
|
||||
"extends": "./.svelte-kit/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"module": "es2020",
|
||||
"lib": ["es2020", "DOM"],
|
||||
"target": "es2020",
|
||||
/**
|
||||
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
|
||||
to enforce using \`import type\` instead of \`import\` for Types.
|
||||
*/
|
||||
"importsNotUsedAsValues": "error",
|
||||
/**
|
||||
TypeScript doesn't know about import usages in the template because it only sees the
|
||||
script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher.
|
||||
*/
|
||||
"preserveValueImports": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
/**
|
||||
To have warnings/errors of the Svelte compiler at the correct position,
|
||||
enable source maps by default.
|
||||
*/
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"baseUrl": ".",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"paths": {
|
||||
"$lib": ["src/lib"],
|
||||
"$lib/*": ["src/lib/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"strict": true
|
||||
}
|
||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||
//
|
||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||
}
|
||||
|
||||
8
apps/playground-sveltekit/vite.config.ts
Normal file
8
apps/playground-sveltekit/vite.config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { sveltekit } from "@sveltejs/kit/vite"
|
||||
import type { UserConfig } from "vite"
|
||||
|
||||
const config: UserConfig = {
|
||||
plugins: [sveltekit()],
|
||||
}
|
||||
|
||||
export default config
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ This is the Dgraph Adapter for [`next-auth`](https://next-auth.js.org).
|
||||
npm install next-auth @next-auth/dgraph-adapter
|
||||
```
|
||||
|
||||
2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
2. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
@@ -17,7 +17,7 @@ You can find the Fauna schema and seed information in the docs at [next-auth.js.
|
||||
npm install next-auth @next-auth/fauna-adapter faunadb
|
||||
```
|
||||
|
||||
2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
2. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
@@ -25,7 +25,7 @@ import { FirestoreAdapter } from "@next-auth/firebase-adapter"
|
||||
// For more information on each option (and a full list of options) go to
|
||||
// https://next-auth.js.org/configuration/options
|
||||
export default NextAuth({
|
||||
// https://next-auth.js.org/providers/overview
|
||||
// https://next-auth.js.org/providers
|
||||
providers: [
|
||||
GoogleProvider({
|
||||
clientId: process.env.GOOGLE_ID,
|
||||
|
||||
@@ -53,12 +53,12 @@ if (process.env.NODE_ENV === "development") {
|
||||
export default clientPromise
|
||||
```
|
||||
|
||||
3. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
3. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```js
|
||||
import NextAuth from "next-auth"
|
||||
import { MongoDBAdapter } from "@next-auth/mongodb-adapter"
|
||||
import clientPromise from "lib/mongodb"
|
||||
import clientPromise from "../../../lib/mongodb"
|
||||
|
||||
// For more information on each option (and a full list of options) go to
|
||||
// https://next-auth.js.org/configuration/options
|
||||
|
||||
@@ -15,7 +15,7 @@ This is the Neo4j Adapter for [`next-auth`](https://next-auth.js.org). This pack
|
||||
npm install next-auth @next-auth/neo4j-adapter neo4j-driver
|
||||
```
|
||||
|
||||
2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
2. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import neo4j from "neo4j-driver"
|
||||
|
||||
@@ -12,15 +12,24 @@ npm install next-auth @prisma/client @next-auth/prisma-adapter
|
||||
npm install prisma --save-dev
|
||||
```
|
||||
|
||||
Create a file with your Prisma Client:
|
||||
|
||||
```javascript title="lib/prismadb.js"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const client = globalThis.prisma || new PrismaClient()
|
||||
if (process.env.NODE_ENV !== "production") globalThis.prisma = client
|
||||
|
||||
export default client
|
||||
```
|
||||
|
||||
Configure your NextAuth.js to use the Prisma Adapter:
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
import { PrismaAdapter } from "@next-auth/prisma-adapter"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
import prisma from "../../../lib/prismadb"
|
||||
|
||||
export default NextAuth({
|
||||
adapter: PrismaAdapter(prisma),
|
||||
@@ -107,6 +116,8 @@ When using the MySQL connector for Prisma, the [Prisma `String` type](https://ww
|
||||
|
||||
### Create the database schema with Prisma Migrate
|
||||
|
||||
**Warning:** Make sure to back up your database before running using Prisma Migrate.
|
||||
|
||||
```
|
||||
npx prisma migrate dev
|
||||
```
|
||||
|
||||
@@ -19,7 +19,7 @@ npm install next-auth @next-auth/sequelize-adapter sequelize
|
||||
You'll also have to manually install [the driver for your database](https://sequelize.org/master/manual/getting-started.html) of choice.
|
||||
:::
|
||||
|
||||
2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
2. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
@@ -17,12 +17,12 @@ Configure your NextAuth.js to use the Upstash Redis Adapter:
|
||||
import NextAuth from "next-auth"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
import { UpstashRedisAdapter } from "@next-auth/upstash-redis-adapter"
|
||||
import upstashRedisClient from "@upstash/redis"
|
||||
import { Redis } from "@upstash/redis"
|
||||
|
||||
const redis = upstashRedisClient(
|
||||
process.env.UPSTASH_REDIS_URL,
|
||||
process.env.UPSTASH_REDIS_TOKEN
|
||||
)
|
||||
const redis = new Redis({
|
||||
url: process.env.UPSTASH_REDIS_URL,
|
||||
token: process.env.UPSTASH_REDIS_TOKEN
|
||||
})
|
||||
|
||||
export default NextAuth({
|
||||
adapter: UpstashRedisAdapter(redis),
|
||||
|
||||
@@ -12,11 +12,11 @@ Otherwise, if you only want to get the session token, see [`getToken`](/tutorial
|
||||
|
||||
`unstable_getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way:
|
||||
|
||||
In `[...nextauth.js]`:
|
||||
In `[...nextauth].ts`:
|
||||
```ts
|
||||
import { NextAuth } from 'next-auth'
|
||||
import type { NextAuthOptions } from 'next-auth'
|
||||
|
||||
|
||||
export const authOptions: NextAuthOptions = {
|
||||
// your configs
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export default NextAuth(authOptions);
|
||||
|
||||
In `getServerSideProps`:
|
||||
```js
|
||||
import { authOptions } from 'pages/api/[...nextauth]'
|
||||
import { authOptions } from 'pages/api/auth/[...nextauth]'
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
@@ -50,7 +50,7 @@ export async function getServerSideProps(context) {
|
||||
```
|
||||
In API routes:
|
||||
```js
|
||||
import { authOptions } from 'pages/api/[...nextauth]'
|
||||
import { authOptions } from 'pages/api/auth/[...nextauth]'
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
|
||||
|
||||
@@ -137,12 +137,16 @@ Callbacks are asynchronous functions you can use to control what happens when an
|
||||
|
||||
Specify URLs to be used if you want to create custom sign in, and error pages. Pages specified will override the corresponding built-in page.
|
||||
|
||||
:::note
|
||||
This should match the `pages` configuration that's found in `[...nextauth].ts`.
|
||||
:::
|
||||
|
||||
#### Example (default value)
|
||||
|
||||
```js
|
||||
pages: {
|
||||
signIn: '/auth/signin',
|
||||
error: '/auth/error',
|
||||
signIn: '/api/auth/signin',
|
||||
error: '/api/auth/error',
|
||||
}
|
||||
```
|
||||
|
||||
@@ -156,7 +160,7 @@ See the documentation for the [pages option](/configuration/pages) for more info
|
||||
|
||||
#### Description
|
||||
|
||||
The same `secret` used in the [NextAuth config](/configuration/options#options).
|
||||
The same `secret` used in the [NextAuth.js config](/configuration/options#options).
|
||||
|
||||
#### Example (default value)
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ A random string is used to hash tokens, sign/encrypt cookies and generate crypto
|
||||
|
||||
If you set [`NEXTAUTH_SECRET`](#nextauth_secret) as an environment variable, you don't have to define this option.
|
||||
|
||||
If no value specified specified in development (and there is no `NEXTAUTH_SECRET` variable either), it uses a hash for all configuration options, including OAuth Client ID / Secrets for entropy.
|
||||
If no value is specified in development (and there is no `NEXTAUTH_SECRET` variable either), it uses a hash for all configuration options, including OAuth Client ID / Secrets for entropy.
|
||||
|
||||
:::warning
|
||||
Not providing any `secret` or `NEXTAUTH_SECRET` will throw [an error](/errors#no_secret) in production.
|
||||
@@ -114,6 +114,12 @@ session: {
|
||||
// Use it to limit write operations. Set to 0 to always update the database.
|
||||
// Note: This option is ignored if using JSON Web Tokens
|
||||
updateAge: 24 * 60 * 60, // 24 hours
|
||||
|
||||
// The session token is usually either a random UUID or string, however if you
|
||||
// need a more customized session token string, you can define your own generate function.
|
||||
generateSessionToken: () => {
|
||||
return randomUUID?.() ?? randomBytes(32).toString("hex")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -326,7 +332,7 @@ Set debug to `true` to enable debug messages for authentication and database ope
|
||||
|
||||
#### Description
|
||||
|
||||
Override any of the logger levels (`undefined` levels will use the built-in logger), and intercept logs in NextAuth. You can use this to send NextAuth logs to a third-party logging service.
|
||||
Override any of the logger levels (`undefined` levels will use the built-in logger), and intercept logs in NextAuth.js. You can use this to send NextAuth.js logs to a third-party logging service.
|
||||
|
||||
The `code` parameter for `error` and `warn` are explained in the [Warnings](/warnings) and [Errors](/errors) pages respectively.
|
||||
|
||||
@@ -478,6 +484,15 @@ cookies: {
|
||||
secure: useSecureCookies,
|
||||
},
|
||||
},
|
||||
nonce: {
|
||||
name: `${cookiePrefix}next-auth.nonce`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
secure: useSecureCookies,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ TWITTER_ID=YOUR_TWITTER_CLIENT_ID
|
||||
TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET
|
||||
```
|
||||
|
||||
4. Now you can add the provider settings to the NextAuth options object. You can add as many OAuth providers as you like, as you can see `providers` is an array.
|
||||
4. Now you can add the provider settings to the NextAuth.js options object. You can add as many OAuth providers as you like, as you can see `providers` is an array.
|
||||
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import TwitterProvider from "next-auth/providers/"
|
||||
|
||||
@@ -76,7 +76,11 @@ Please check your OAuth provider and make sure your URLs and other options are
|
||||
|
||||
If you are using an OAuth v1 provider, check your OAuth v1 provider settings, especially the OAuth token and OAuth token secret.
|
||||
|
||||
#### CALLBACK_OAUTH_ERROR
|
||||
3. `openid-client` version mismatch
|
||||
|
||||
If you are seeing `expected 200 OK with body but no body was returned`, it might have happened due to `openid-client` (which is peer dependency) node version mismatch. For instance, `openid-client` requires `>=14.2.0` for `lts/fermium` and has similar limits for the other versions. For the full list of the compatible node versions please see [package.json](https://github.com/panva/node-openid-client/blob/2a84e46992e1ebeaf685c3f87b65663d126e81aa/package.json#L78).
|
||||
|
||||
#### OAUTH_CALLBACK_ERROR
|
||||
|
||||
This can occur during the handling of the callback if the `code_verifier` cookie was not found or an invalid state was returned from the OAuth provider.
|
||||
|
||||
@@ -152,7 +156,7 @@ This error occurs when there was an issue deleting the session from the database
|
||||
|
||||
---
|
||||
|
||||
### Other
|
||||
### Configuration
|
||||
|
||||
#### MISSING_NEXTAUTH_API_ROUTE_ERROR
|
||||
|
||||
@@ -164,6 +168,18 @@ Make sure the file is there and the filename is written correctly.
|
||||
|
||||
In production, we expect you to define a `secret` property in your configuration. In development, this is shown as a warning for convenience. [Read more](/configuration/options#secret)
|
||||
|
||||
#### oauth_callback_error expected 200 OK with body but no body was returned
|
||||
|
||||
This error might happen with some of the providers. It happens due to `openid-client`(which is peer dependency) node version mismatch. For instance, `openid-client` requires `>=14.2.0` for `lts/fermium` and has similar limits for the other versions. For the full list of the compatible node versions please see [package.json](https://github.com/panva/node-openid-client/blob/2a84e46992e1ebeaf685c3f87b65663d126e81aa/package.json#L78)
|
||||
#### AUTH_ON_ERROR_PAGE_ERROR
|
||||
|
||||
You have a custom error page defined that was rendered due to an error, but the page also required authentication. To avoid an infinite redirect loop, NextAuth.js bailed out and rendered its default error page instead.
|
||||
|
||||
If you are using a Middleware, make sure you include the same `pages` configuration in your `middleware.ts` and `[...nextauth].ts` files. Or use the `matcher` option to only require authentication for certain sites (and exclude your custom error page).
|
||||
|
||||
If you do not use a Middleware, make sure you don't try redirecting the user to the sign-in page when hitting your custom error page.
|
||||
|
||||
Useful links:
|
||||
|
||||
- https://next-auth.js.org/configuration/nextjs#pages
|
||||
- https://next-auth.js.org/configuration/pages
|
||||
- https://nextjs.org/docs/advanced-features/middleware#matcher
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ NextAuth.js was originally designed for use with Next.js and Serverless. However
|
||||
**Same root domain, different subdomains**: If you use NextAuth.js on a website with a different subdomain than the rest of your website (e.g. `auth.example.com` vs. `www.example.com`) you will need to set a custom cookie domain policy for the Session Token cookie. (See also: [Cookies](/configuration/options#cookies)).
|
||||
|
||||
:::warning
|
||||
Changing the default cookies domain policy is advanced and can lead to security issues if done correctly. Make sure you're aware of the security implication before proceeding.
|
||||
Changing the default cookies domain policy can lead to security issues if done incorrectly. Make sure you're aware of the implications before proceeding.
|
||||
:::
|
||||
|
||||
A working example can be found at <a href="https://github.com/vercel/examples/tree/main/solutions/subdomain-auth" target="_blank">this example repo</a>.
|
||||
@@ -236,6 +236,10 @@ Automatic account linking is not a planned feature of NextAuth.js, however there
|
||||
|
||||
Providing support for secure account linking and unlinking of additional providers - which can only be done if a user is already signed in already - was originally a feature in v1.x but has not been present since v2.0, is planned to return in a future release.
|
||||
|
||||
:::note
|
||||
If the user first signs in using Email and then tries to sign in again using an OAuth provider, NextAuth.js default behavior is to allow account linking even if the OAuth account's email address does not match the previous email address of the user.
|
||||
:::
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
@@ -329,7 +333,7 @@ JSON Web Tokens can be used for session tokens, but are also used for lots of ot
|
||||
|
||||
Avoid storing any data in a token that might be problematic if it were to be decrypted in the future.
|
||||
|
||||
- If you do not explicitly specify a secret for for NextAuth.js, existing sessions will be invalidated any time your NextAuth.js configuration changes, as NextAuth.js will default to an auto-generated secret. Since v4 this only impacts development and generating a secret is required in production.
|
||||
- If you do not explicitly specify a secret for NextAuth.js, existing sessions will be invalidated any time your NextAuth.js configuration changes, as NextAuth.js will default to an auto-generated secret. Since v4 this only impacts development and generating a secret is required in production.
|
||||
|
||||
|
||||
</p>
|
||||
|
||||
@@ -67,7 +67,7 @@ export default function Component() {
|
||||
|
||||
Due to the way how Next.js handles `getServerSideProps` and `getInitialProps`, every protected page load has to make a server-side request to check if the session is valid and then generate the requested page (SSR). This increases server load, and if you are good with making the requests from the client, there is an alternative. You can use `useSession` in a way that makes sure you always have a valid session. If after the initial loading state there was no session found, you can define the appropriate action to respond.
|
||||
|
||||
The default behavior is to redirect the user to the sign-in page, from where - after a successful login - they will be sent back to the page they started on. You can also define an `onFail()` callback, if you would like to do something else:
|
||||
The default behavior is to redirect the user to the sign-in page, from where - after a successful login - they will be sent back to the page they started on. You can also define an `onUnauthenticated()` callback, if you would like to do something else:
|
||||
|
||||
#### Example
|
||||
|
||||
|
||||
@@ -11,6 +11,17 @@ The easiest way to get started is to clone the [example app](https://github.com/
|
||||
|
||||
## Existing Project
|
||||
|
||||
### Install NextAuth
|
||||
|
||||
```bash npm2yarn2pnpm
|
||||
npm install next-auth
|
||||
```
|
||||
|
||||
:::info
|
||||
If you are using TypeScript, NextAuth.js comes with its types definitions within the package. To learn more about TypeScript for `next-auth`, check out the [TypeScript documentation](/getting-started/typescript)
|
||||
:::
|
||||
|
||||
|
||||
### Add API route
|
||||
|
||||
To add NextAuth.js to a project create a file called `[...nextauth].js` in `pages/api/auth`. This contains the dynamic route handler for NextAuth.js which will also contain all of your global NextAuth.js configurations.
|
||||
@@ -19,7 +30,7 @@ To add NextAuth.js to a project create a file called `[...nextauth].js` in `page
|
||||
import NextAuth from "next-auth"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
|
||||
export default NextAuth({
|
||||
export const authOptions = {
|
||||
// Configure one or more authentication providers
|
||||
providers: [
|
||||
GithubProvider({
|
||||
@@ -28,7 +39,9 @@ export default NextAuth({
|
||||
}),
|
||||
// ...add more providers here
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
export default NextAuth(authOptions)
|
||||
```
|
||||
|
||||
All requests to `/api/auth/*` (`signIn`, `callback`, `signOut`, etc.) will automatically be handled by NextAuth.js.
|
||||
@@ -97,7 +110,7 @@ To protect an API Route, you can use the [`unstable_getServerSession()`](/config
|
||||
|
||||
```javascript title="pages/api/restricted.js" showLineNumbers
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import { authOptions } from "./auth/[...nextauth]"
|
||||
|
||||
export default async (req, res) => {
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
@@ -109,7 +122,7 @@ export default async (req, res) => {
|
||||
})
|
||||
} else {
|
||||
res.send({
|
||||
error: "You must be sign in to view the protected content on this page.",
|
||||
error: "You must be signed in to view the protected content on this page.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ Introduced in https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.8
|
||||
|
||||
**This does not require any changes from the user - these are adapter specific changes only**
|
||||
|
||||
The Adapter API has been rewritten and significantly simplified in NextAuth v4. The adapters now have less work to do as some functionality has been migrated to the core of NextAuth, like hashing the [verification token](/adapters/models/#verification-token).
|
||||
The Adapter API has been rewritten and significantly simplified in NextAuth.js v4. The adapters now have less work to do as some functionality has been migrated to the core of NextAuth, like hashing the [verification token](/adapters/models/#verification-token).
|
||||
|
||||
If you are an adapter maintainer or are interested in writing your own adapter, you can find more information about this change in https://github.com/nextauthjs/next-auth/pull/2361 and release https://github.com/nextauthjs/next-auth/releases/tag/v4.0.0-next.22.
|
||||
|
||||
|
||||
@@ -24,7 +24,11 @@ providers: [
|
||||
AtlassianProvider({
|
||||
clientId: process.env.ATLASSIAN_CLIENT_ID,
|
||||
clientSecret: process.env.ATLASSIAN_CLIENT_SECRET,
|
||||
scope: "write:jira-work read:jira-work read:jira-user offline_access read:me"
|
||||
authorization: {
|
||||
params: {
|
||||
scope: "write:jira-work read:jira-work read:jira-user offline_access read:me"
|
||||
}
|
||||
}
|
||||
})
|
||||
]
|
||||
...
|
||||
|
||||
@@ -71,7 +71,7 @@ EMAIL_SERVER_PORT=587
|
||||
EMAIL_FROM=noreply@example.com
|
||||
```
|
||||
|
||||
Now you can add the provider settings to the NextAuth options object in the Email Provider.
|
||||
Now you can add the provider settings to the NextAuth.js options object in the Email Provider.
|
||||
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import EmailProvider from "next-auth/providers/email";
|
||||
@@ -223,3 +223,31 @@ providers: [
|
||||
})
|
||||
],
|
||||
```
|
||||
|
||||
## Normalizing the email address
|
||||
|
||||
By default, NextAuth.js will normalize the email address. It treats values as case-insensitive (which is technically not compliant to the [RFC 2821 spec](https://datatracker.ietf.org/doc/html/rfc2821), but in practice this causes more problems than it solves, eg. when looking up users by e-mail from databases.) and also removes any secondary email address that was passed in as a comma-separated list. You can apply your own normalization via the `normalizeIdentifier` method on the `EmailProvider`. The following example shows the default behavior:
|
||||
```ts
|
||||
EmailProvider({
|
||||
// ...
|
||||
normalizeIdentifier(identifier: string): string {
|
||||
// Get the first two elements only,
|
||||
// separated by `@` from user input.
|
||||
let [local, domain] = identifier.toLowerCase().trim().split("@")
|
||||
// The part before "@" can contain a ","
|
||||
// but we remove it on the domain part
|
||||
domain = domain.split(",")[0]
|
||||
return `${local}@${domain}`
|
||||
|
||||
// You can also throw an error, which will redirect the user
|
||||
// to the error page with error=EmailSignin in the URL
|
||||
// if (identifier.split("@").length > 2) {
|
||||
// throw new Error("Only one email allowed")
|
||||
// }
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
:::warning
|
||||
Always make sure this returns a single e-mail address, even if multiple ones were passed in.
|
||||
:::
|
||||
@@ -15,7 +15,7 @@ https://gitlab.com/-/profile/applications
|
||||
|
||||
The **Gitlab Provider** comes with a set of default options:
|
||||
|
||||
- [Gitlab Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/gitlab.js)
|
||||
- [Gitlab Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/gitlab.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
|
||||
43
docs/docs/providers/hubspot.md
Normal file
43
docs/docs/providers/hubspot.md
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
id: hubspot
|
||||
title: HubSpot
|
||||
---
|
||||
|
||||
:::note
|
||||
HubSpot returns a limited amount of information on the token holder (see [docs](https://legacydocs.hubspot.com/docs/methods/oauth2/get-access-token-information)). One other issue is that the name and profile photo cannot be fetched through API as discussed [here](https://community.hubspot.com/t5/APIs-Integrations/Profile-photo-is-not-retrieved-with-User-API/m-p/325521).
|
||||
:::
|
||||
|
||||
## Documentation
|
||||
|
||||
https://developers.hubspot.com/docs/api/oauth-quickstart-guide
|
||||
|
||||
## Configuration
|
||||
|
||||
You need to have an APP in your Developer Account as described at https://developers.hubspot.com/docs/api/developer-tools-overview
|
||||
|
||||
## Options
|
||||
|
||||
The **HubSpot Provider** comes with a set of default options:
|
||||
|
||||
- [HubSpot Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/hubspot.ts)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import HubspotProvider from "next-auth/providers/hubspot";
|
||||
...
|
||||
providers: [
|
||||
HubspotProvider({
|
||||
clientId: process.env.HUBSPOT_CLIENT_ID,
|
||||
clientSecret: process.env.HUBSPOT_CLIENT_SECRET
|
||||
})
|
||||
]
|
||||
...
|
||||
```
|
||||
|
||||
:::warning
|
||||
The **Redirect URL** under the **Auth** tab on the HubSpot App Settings page must match the callback url which would be http://localhost:3000/api/auth/callback/hubspot for local development. Only one callback URL per Client ID and Client Secret pair is allowed, so it might be easier to create a new app for local development then fiddle with the url changes.
|
||||
:::
|
||||
|
||||
@@ -7,9 +7,16 @@ title: Reddit
|
||||
|
||||
https://www.reddit.com/dev/api/
|
||||
|
||||
## Configuration
|
||||
## App Configuration
|
||||
|
||||
https://www.reddit.com/prefs/apps/
|
||||
1. Visit https://www.reddit.com/prefs/apps/ and create a new web app
|
||||
2. Provide a name for your web app
|
||||
3. Provide a redirect uri ending with `/api/auth/callback/reddit`:
|
||||
|
||||

|
||||
|
||||
4. All other fields are optional
|
||||
5. Click the "create app" button
|
||||
|
||||
## Options
|
||||
|
||||
@@ -46,27 +53,15 @@ This Provider template only has a one hour access token to it and only has the "
|
||||
|
||||
```js
|
||||
providers: [
|
||||
{
|
||||
id: "reddit",
|
||||
name: "Reddit",
|
||||
RedditProvider({
|
||||
clientId: process.env.REDDIT_CLIENT_ID,
|
||||
clientSecret: process.env.REDDIT_CLIENT_SECRET,
|
||||
scope: "identity mysubreddits read", //Check Reddit API Documentation for more. The identity scope is required.
|
||||
type: "oauth",
|
||||
version: "2.0",
|
||||
params: { grant_type: "authorization_code" },
|
||||
accessTokenUrl: " https://www.reddit.com/api/v1/access_token",
|
||||
authorizationUrl:
|
||||
"https://www.reddit.com/api/v1/authorize?response_type=code&duration=permanent",
|
||||
profileUrl: "https://oauth.reddit.com/api/v1/me",
|
||||
profile: (profile) => {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.name,
|
||||
email: null,
|
||||
}
|
||||
authorization: {
|
||||
params: {
|
||||
duration: 'permanent',
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ The **Strava Provider** comes with a set of default options:
|
||||
|
||||
- [Strava Provider options](https://github.com/nextauthjs/next-auth/blob/main/packages/next-auth/src/providers/strava.js)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
You can override any of the options to suit your own use case. Ensure the redirect_uri configuration fits your needs accordingly.
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ If you contact us regarding a serious issue:
|
||||
- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
|
||||
- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
|
||||
|
||||
The best way to report an issue is by contacting us via email at info@balazsorban.com or me@iaincollins.com and yo@ndo.dev, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||
The best way to report an issue is by contacting us via email at info@balazsorban.com, yo@ndo.dev, thvu@hey.com and me@iaincollins.com, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
|
||||
|
||||
:::note
|
||||
For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these these publically as bug reports or feature requests or to raise a question to open a discussion around them.
|
||||
|
||||
@@ -17,7 +17,7 @@ Using a [JWT callback](https://next-auth.js.org/configuration/callbacks#jwt-call
|
||||
|
||||
Below is a sample implementation using Google's Identity Provider. Please note that the OAuth 2.0 request in the `refreshAccessToken()` function will vary between different providers, but the core logic should remain similar.
|
||||
|
||||
```js title="pages/auth/[...nextauth.js]"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ callbacks: {
|
||||
async session({ session, token, user }) {
|
||||
session.user.role = user.role; // Add role value to user object so it is passed along with session
|
||||
return session;
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
@@ -42,18 +42,30 @@ export default function Page() {
|
||||
|
||||
### Next.js (Middleware)
|
||||
|
||||
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `_middleware.js` file in your root `pages` directory which looks like this.
|
||||
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `middleware.js` file in your root `pages` directory which looks like this:
|
||||
|
||||
```js title="/middleware.js"
|
||||
export { default } from "next-auth/middleware"
|
||||
```
|
||||
|
||||
Otherwise, if you only want to protect a subset of pages, you could put it in a subdirectory as well, for example in `/pages/admin/_middleware.js` would protect all pages under `/admin`.
|
||||
If you only want to secure certain pages, export a `config` object with a `matcher`:
|
||||
|
||||
```js
|
||||
export { default } from "next-auth/middleware"
|
||||
|
||||
export const config = { matcher: ["/dashboard"] }
|
||||
```
|
||||
|
||||
For the time being, the `withAuth` middleware only supports `"jwt"` as [session strategy](https://next-auth.js.org/configuration/options#session).
|
||||
|
||||
More details can be found [here](https://next-auth.js.org/configuration/nextjs#middleware).
|
||||
|
||||
:::tip
|
||||
To inclue all `dashboard` nested routes (sub pages like `/dashboard/settings`, `/dashboard/profile`) you can pass `matcher: "/dashboard/:path*"` to `config`.
|
||||
|
||||
For other patterns check out the [Next.js Middleware documentation](https://nextjs.org/docs/advanced-features/middleware#matcher).
|
||||
:::
|
||||
|
||||
### Server Side
|
||||
|
||||
You can protect server side rendered pages using the `unstable_getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly.
|
||||
@@ -122,7 +134,7 @@ You can protect API routes using the `unstable_getServerSession()` method.
|
||||
|
||||
```js title="pages/api/get-session-example.js"
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import { authOptions } from "./auth/[...nextauth]"
|
||||
|
||||
export default async (req, res) => {
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
|
||||
@@ -49,7 +49,7 @@ const features = [
|
||||
<ul>
|
||||
<li>Signed, prefixed, server-only cookies</li>
|
||||
<li>HTTP POST + CSRF Token validation</li>
|
||||
<li>JWT with JWS / JWE / JWK / JWK</li>
|
||||
<li>JWT with JWS / JWE / JWK</li>
|
||||
<li>Tab syncing, auto-revalidation, keepalives</li>
|
||||
<li>Doesn't rely on client side JavaScript</li>
|
||||
</ul>
|
||||
|
||||
@@ -17,7 +17,7 @@ You can find the Fauna schema and seed information in the docs at [next-auth.js.
|
||||
npm install next-auth @next-auth/fauna-adapter@canary
|
||||
```
|
||||
|
||||
2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
2. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
@@ -15,7 +15,7 @@ This is the Firebase Adapter for [`next-auth`](https://next-auth.js.org). This p
|
||||
npm install next-auth @next-auth/firebase-adapter@canary
|
||||
```
|
||||
|
||||
2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
|
||||
2. Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object.
|
||||
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
@@ -335,7 +335,7 @@ Set debug to `true` to enable debug messages for authentication and database ope
|
||||
|
||||
#### Description
|
||||
|
||||
Override any of the logger levels (`undefined` levels will use the built-in logger), and intercept logs in NextAuth. You can use this to send NextAuth logs to a third-party logging service.
|
||||
Override any of the logger levels (`undefined` levels will use the built-in logger), and intercept logs in NextAuth. You can use this to send NextAuth.js logs to a third-party logging service.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ TWITTER_ID=YOUR_TWITTER_CLIENT_ID
|
||||
TWITTER_SECRET=YOUR_TWITTER_CLIENT_SECRET
|
||||
```
|
||||
|
||||
4. Now you can add the provider settings to the NextAuth options object. You can add as many OAuth providers as you like, as you can see `providers` is an array.
|
||||
4. Now you can add the provider settings to the NextAuth.js options object. You can add as many OAuth providers as you like, as you can see `providers` is an array.
|
||||
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -59,7 +59,7 @@ This will work in code editors with a strong TypeScript integration like VSCode
|
||||
|
||||
Let's look at `Session`:
|
||||
|
||||
```ts title="pages/api/[...nextauth].ts"
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
export default NextAuth({
|
||||
|
||||
@@ -68,7 +68,7 @@ EMAIL_SERVER_HOST=smtp.example.com
|
||||
EMAIL_FROM=noreply@example.com
|
||||
```
|
||||
|
||||
Now you can add the provider settings to the NextAuth options object in the Email Provider.
|
||||
Now you can add the provider settings to the NextAuth.js options object in the Email Provider.
|
||||
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
providers: [
|
||||
|
||||
@@ -13,7 +13,7 @@ The **Strava Provider** comes with a set of default options:
|
||||
|
||||
- [Strava Provider options](https://github.com/nextauthjs/next-auth/blob/main/src/providers/strava.js)
|
||||
|
||||
You can override any of the options to suit your own use case.
|
||||
You can override any of the options to suit your own use case. Ensure the `redirect_uri` configuration fits your needs accordingly.
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ _New submissions and edits are welcome!_
|
||||
|
||||
### [NextJS Authentication Crash Course with NextAuth.js](https://youtu.be/o_wZIVmWteQ)
|
||||
|
||||
This tutorial dives in to the ins and outs of NextAuth including email, GitHub, Twitter and integrating with Auth0 in under hour.
|
||||
This tutorial dives in to the ins and outs of NextAuth.js including email, GitHub, Twitter and integrating with Auth0 in under hour.
|
||||
|
||||
### [Create your own NextAuth.js Login Pages](https://youtu.be/kB6YNYZ63fw)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Using a [JWT callback](https://next-auth.js.org/configuration/callbacks#jwt-call
|
||||
|
||||
Below is a sample implementation using Google's Identity Provider. Please note that the OAuth 2.0 request in the `refreshAccessToken()` function will vary between different providers, but the core logic should remain similar.
|
||||
|
||||
```js title="pages/auth/[...nextauth.js]"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
import Providers from "next-auth/providers"
|
||||
|
||||
@@ -121,7 +121,7 @@ The `RefreshAccessTokenError` error that is caught in the `refreshAccessToken()`
|
||||
|
||||
We can handle this functionality as a side effect:
|
||||
|
||||
```js title="pages/auth/[...nextauth.js]"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import { signIn, useSession } from "next-auth/client";
|
||||
import { useEffect } from "react";
|
||||
|
||||
|
||||
77
package.json
77
package.json
@@ -6,20 +6,20 @@
|
||||
"scripts": {
|
||||
"build:app": "turbo run build --filter=next-auth-app --include-dependencies",
|
||||
"build": "turbo run build --filter=next-auth --filter=@next-auth/* --no-deps",
|
||||
"lint": "turbo run lint --filter=!next-auth-docs",
|
||||
"lint:fix": "turbo run lint -- --fix",
|
||||
"test": "turbo run test --concurrency=1 --filter=!@next-auth/pouchdb-adapter --filter=!next-auth-* --filter=[HEAD^1]",
|
||||
"setup": "turbo run setup",
|
||||
"lint": "turbo run lint --filter=!next-auth-docs --parallel",
|
||||
"test": "turbo run test --concurrency=1 --filter=!@next-auth/pouchdb-adapter --filter=!@next-auth/upstash-redis-adapter --filter=!next-auth-* --filter=[HEAD^1]",
|
||||
"clean": "turbo run clean --no-cache",
|
||||
"dev:app": "turbo run dev --parallel --continue --filter=next-auth-app...",
|
||||
"dev:docs": "turbo run dev --filter=next-auth-docs",
|
||||
"dev": "pnpm dev:app",
|
||||
"email": "cd apps/dev && pnpm email",
|
||||
"dev:app": "turbo run dev --parallel --no-deps --no-cache --filter=next-auth-app",
|
||||
"dev:docs": "turbo run dev --parallel --no-deps --no-cache --filter=next-auth-docs",
|
||||
"version:pr": "node ./config/version-pr",
|
||||
"release": "release"
|
||||
"release": "release",
|
||||
"version:pr": "node ./config/version-pr"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/core": "^1.6.0",
|
||||
"@balazsorban/monorepo-release": "0.0.4",
|
||||
"@balazsorban/monorepo-release": "0.0.5",
|
||||
"@types/jest": "^28.1.3",
|
||||
"@types/node": "^17.0.25",
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
@@ -27,18 +27,20 @@
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-jest": "^25.3.0",
|
||||
"eslint-plugin-jest": "^27.0.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"husky": "^7.0.4",
|
||||
"prettier": "2.4.1",
|
||||
"pretty-quick": "^3.1.2",
|
||||
"semver": "7.3.5",
|
||||
"stream-to-array": "2.3.0",
|
||||
"ts-node": "10.5.0",
|
||||
"turbo": "1.3.1",
|
||||
"typescript": "^4.5.2"
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.19.0 || ^14.15.0 || ^16.13.0",
|
||||
"pnpm": ">=6.32.3"
|
||||
"node": "^12.19.0 || ^14.15.0 || ^16.13.0"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
@@ -52,55 +54,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"extends": [
|
||||
"standard-with-typescript",
|
||||
"prettier"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"node_modules",
|
||||
"next-env.d.ts",
|
||||
"types",
|
||||
".next",
|
||||
"dist",
|
||||
"/core",
|
||||
"/react.js"
|
||||
],
|
||||
"globals": {
|
||||
"localStorage": "readonly",
|
||||
"location": "readonly",
|
||||
"fetch": "readonly"
|
||||
},
|
||||
"rules": {
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/naming-convention": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"./**/*test.js"
|
||||
],
|
||||
"env": {
|
||||
"jest/globals": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:jest/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"jest"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"eslintIgnore": [
|
||||
"./*.d.ts",
|
||||
"**/tests",
|
||||
"**/__tests__"
|
||||
],
|
||||
"packageManager": "pnpm@7.5.1",
|
||||
"funding": [
|
||||
{
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/node-fetch": "^2.5.11",
|
||||
|
||||
8
packages/adapter-dgraph/tsconfig.eslint.json
Normal file
8
packages/adapter-dgraph/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-dynamodb": "^3.36.1",
|
||||
"@aws-sdk/lib-dynamodb": "^3.36.1",
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@shelf/jest-dynamodb": "^2.1.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
|
||||
8
packages/adapter-dynamodb/tsconfig.eslint.json
Normal file
8
packages/adapter-dynamodb/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"migrate": "fauna-schema-migrate generate",
|
||||
"build": "tsc",
|
||||
"dev": "tsc -w",
|
||||
"clean": "rm -rf dist",
|
||||
"migrate": "fauna-schema-migrate generate",
|
||||
"test": "./tests/test.sh"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -45,8 +47,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fauna-labs/fauna-schema-migrate": "^2.1.3",
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"faunadb": "^4.3.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*"
|
||||
|
||||
8
packages/adapter-fauna/tsconfig.eslint.json
Normal file
8
packages/adapter-fauna/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"firebase": "^9.7.0",
|
||||
"firebase-tools": "^10.7.2",
|
||||
"jest": "^27.4.3",
|
||||
|
||||
8
packages/adapter-firebase/tsconfig.eslint.json
Normal file
8
packages/adapter-firebase/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"exclude": ["tests", "dist", "jest.config.js"]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/mikro-orm-adapter",
|
||||
"version": "2.0.1",
|
||||
"version": "3.0.0",
|
||||
"description": "MikroORM adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -32,22 +32,22 @@
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@mikro-orm/core": "^5.0.2",
|
||||
"@mikro-orm/core": "^5",
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mikro-orm/core": "^5.0.2",
|
||||
"@mikro-orm/sqlite": "^5.0.2",
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"jest": "^27.4.3",
|
||||
"@mikro-orm/core": "^5",
|
||||
"@mikro-orm/sqlite": "^5",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/uuid": ">=8",
|
||||
"jest": "^29",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": "^9"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"uuid": "^8.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
OneToMany,
|
||||
Collection,
|
||||
ManyToOne,
|
||||
types,
|
||||
} from "@mikro-orm/core"
|
||||
|
||||
import type { DefaultAccount } from "next-auth"
|
||||
@@ -29,55 +30,56 @@ export class User implements RemoveIndex<AdapterUser> {
|
||||
@PrimaryKey()
|
||||
id: string = randomUUID()
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
name?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
@Unique()
|
||||
email?: string
|
||||
|
||||
@Property({ type: "Date", nullable: true })
|
||||
@Property({ type: types.datetime, nullable: true })
|
||||
emailVerified: Date | null = null
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
image?: string
|
||||
|
||||
@OneToMany({
|
||||
entity: () => Session,
|
||||
mappedBy: (session) => session.user,
|
||||
entity: 'Session',
|
||||
mappedBy: (session: Session) => session.user,
|
||||
hidden: true,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
sessions = new Collection<Session>(this)
|
||||
sessions = new Collection<Session, object>(this)
|
||||
|
||||
@OneToMany({
|
||||
entity: () => Account,
|
||||
mappedBy: (account) => account.user,
|
||||
entity: 'Account',
|
||||
mappedBy: (account: Account) => account.user,
|
||||
hidden: true,
|
||||
orphanRemoval: true,
|
||||
})
|
||||
accounts = new Collection<Account>(this)
|
||||
accounts = new Collection<Account, object>(this)
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class Session implements AdapterSession {
|
||||
@PrimaryKey()
|
||||
@Property({ type: types.string })
|
||||
id: string = randomUUID()
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => User,
|
||||
entity: 'User',
|
||||
hidden: true,
|
||||
onDelete: "cascade",
|
||||
})
|
||||
user!: User
|
||||
|
||||
@Property({ persist: false })
|
||||
@Property({ type: types.string, persist: false })
|
||||
userId!: string
|
||||
|
||||
@Property()
|
||||
@Property({ type: 'Date' })
|
||||
expires!: Date
|
||||
|
||||
@Property()
|
||||
@Property({ type: types.string })
|
||||
@Unique()
|
||||
sessionToken!: string
|
||||
}
|
||||
@@ -86,46 +88,47 @@ export class Session implements AdapterSession {
|
||||
@Unique({ properties: ["provider", "providerAccountId"] })
|
||||
export class Account implements RemoveIndex<DefaultAccount> {
|
||||
@PrimaryKey()
|
||||
@Property({ type: types.string })
|
||||
id: string = randomUUID()
|
||||
|
||||
@ManyToOne({
|
||||
entity: () => User,
|
||||
entity: 'User',
|
||||
hidden: true,
|
||||
onDelete: "cascade",
|
||||
})
|
||||
user!: User
|
||||
|
||||
@Property({ persist: false })
|
||||
@Property({ type: types.string, persist: false })
|
||||
userId!: string
|
||||
|
||||
@Enum()
|
||||
@Property({ type: types.string })
|
||||
type!: ProviderType
|
||||
|
||||
@Property()
|
||||
@Property({ type: types.string })
|
||||
provider!: string
|
||||
|
||||
@Property()
|
||||
@Property({ type: types.string })
|
||||
providerAccountId!: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
refresh_token?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
access_token?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.integer, nullable: true })
|
||||
expires_at?: number
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
token_type?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
scope?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.text, nullable: true })
|
||||
id_token?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Property({ type: types.string, nullable: true })
|
||||
session_state?: string
|
||||
}
|
||||
|
||||
@@ -133,12 +136,12 @@ export class Account implements RemoveIndex<DefaultAccount> {
|
||||
@Unique({ properties: ["token", "identifier"] })
|
||||
export class VerificationToken implements AdapterVerificationToken {
|
||||
@PrimaryKey()
|
||||
@Property()
|
||||
@Property({ type: types.string })
|
||||
token!: string
|
||||
|
||||
@Property()
|
||||
@Property({ type: 'Date' })
|
||||
expires!: Date
|
||||
|
||||
@Property()
|
||||
@Property({ type: types.string })
|
||||
identifier!: string
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { MikroORM, wrap } from "@mikro-orm/core"
|
||||
|
||||
import * as defaultEntities from "./entities"
|
||||
|
||||
export * as defaultEntities from "./entities"
|
||||
export { defaultEntities }
|
||||
|
||||
/**
|
||||
* The MikroORM adapter accepts a MikroORM configuration and returns a NextAuth adapter.
|
||||
|
||||
@@ -0,0 +1,591 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`run migrations: createSchemaSQL 1`] = `
|
||||
"pragma foreign_keys = off;
|
||||
|
||||
create table \`user\` (\`id\` text not null, \`name\` text null, \`email\` text null, \`email_verified\` datetime null, \`image\` text null, primary key (\`id\`));
|
||||
create unique index \`user_email_unique\` on \`user\` (\`email\`);
|
||||
|
||||
create table \`session\` (\`id\` text not null, \`user_id\` text not null, \`expires\` datetime not null, \`session_token\` text not null, constraint \`session_user_id_foreign\` foreign key(\`user_id\`) references \`user\`(\`id\`) on delete cascade on update cascade, primary key (\`id\`));
|
||||
create index \`session_user_id_index\` on \`session\` (\`user_id\`);
|
||||
create unique index \`session_session_token_unique\` on \`session\` (\`session_token\`);
|
||||
|
||||
create table \`account\` (\`id\` text not null, \`user_id\` text not null, \`type\` text not null, \`provider\` text not null, \`provider_account_id\` text not null, \`refresh_token\` text null, \`access_token\` text null, \`expires_at\` integer null, \`token_type\` text null, \`scope\` text null, \`id_token\` text null, \`session_state\` text null, constraint \`account_user_id_foreign\` foreign key(\`user_id\`) references \`user\`(\`id\`) on delete cascade on update cascade, primary key (\`id\`));
|
||||
create index \`account_user_id_index\` on \`account\` (\`user_id\`);
|
||||
create unique index \`account_provider_provider_account_id_unique\` on \`account\` (\`provider\`, \`provider_account_id\`);
|
||||
|
||||
create table \`verification_token\` (\`token\` text not null, \`expires\` datetime not null, \`identifier\` text not null, primary key (\`token\`));
|
||||
create unique index \`verification_token_token_identifier_unique\` on \`verification_token\` (\`token\`, \`identifier\`);
|
||||
|
||||
pragma foreign_keys = on;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`run migrations: targetSchema 1`] = `
|
||||
{
|
||||
"name": undefined,
|
||||
"namespaces": [],
|
||||
"tables": [
|
||||
{
|
||||
"checks": [],
|
||||
"columns": {
|
||||
"email": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "email",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"email_verified": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": 0,
|
||||
"mappedType": "datetime",
|
||||
"name": "email_verified",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "datetime",
|
||||
"unsigned": false,
|
||||
},
|
||||
"id": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "id",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"image": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "image",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"name": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "name",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
},
|
||||
"comment": undefined,
|
||||
"foreignKeys": {},
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"email",
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "user_email_unique",
|
||||
"primary": false,
|
||||
"unique": true,
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"id",
|
||||
],
|
||||
"composite": false,
|
||||
"expression": undefined,
|
||||
"keyName": "primary",
|
||||
"primary": true,
|
||||
"type": undefined,
|
||||
"unique": true,
|
||||
},
|
||||
],
|
||||
"name": "user",
|
||||
"schema": undefined,
|
||||
},
|
||||
{
|
||||
"checks": [],
|
||||
"columns": {
|
||||
"expires": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": 0,
|
||||
"mappedType": "datetime",
|
||||
"name": "expires",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "datetime",
|
||||
"unsigned": false,
|
||||
},
|
||||
"id": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "id",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"session_token": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "session_token",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"user_id": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "user_id",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
},
|
||||
"comment": undefined,
|
||||
"foreignKeys": {
|
||||
"session_user_id_foreign": {
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
],
|
||||
"constraintName": "session_user_id_foreign",
|
||||
"deleteRule": "cascade",
|
||||
"localTableName": "session",
|
||||
"referencedColumnNames": [
|
||||
"id",
|
||||
],
|
||||
"referencedTableName": "user",
|
||||
"updateRule": "cascade",
|
||||
},
|
||||
},
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "session_user_id_index",
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"session_token",
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "session_session_token_unique",
|
||||
"primary": false,
|
||||
"unique": true,
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"id",
|
||||
],
|
||||
"composite": false,
|
||||
"expression": undefined,
|
||||
"keyName": "primary",
|
||||
"primary": true,
|
||||
"type": undefined,
|
||||
"unique": true,
|
||||
},
|
||||
],
|
||||
"name": "session",
|
||||
"schema": undefined,
|
||||
},
|
||||
{
|
||||
"checks": [],
|
||||
"columns": {
|
||||
"access_token": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "access_token",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"expires_at": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "integer",
|
||||
"name": "expires_at",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "integer",
|
||||
"unsigned": false,
|
||||
},
|
||||
"id": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "id",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"id_token": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "id_token",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"provider": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "provider",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"provider_account_id": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "provider_account_id",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"refresh_token": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "refresh_token",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"scope": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "scope",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"session_state": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "session_state",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"token_type": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "token_type",
|
||||
"nullable": true,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"type": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "type",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"user_id": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "user_id",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
},
|
||||
"comment": undefined,
|
||||
"foreignKeys": {
|
||||
"account_user_id_foreign": {
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
],
|
||||
"constraintName": "account_user_id_foreign",
|
||||
"deleteRule": "cascade",
|
||||
"localTableName": "account",
|
||||
"referencedColumnNames": [
|
||||
"id",
|
||||
],
|
||||
"referencedTableName": "user",
|
||||
"updateRule": "cascade",
|
||||
},
|
||||
},
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"user_id",
|
||||
],
|
||||
"composite": false,
|
||||
"keyName": "account_user_id_index",
|
||||
"primary": false,
|
||||
"unique": false,
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"provider",
|
||||
"provider_account_id",
|
||||
],
|
||||
"composite": true,
|
||||
"expression": undefined,
|
||||
"keyName": "account_provider_provider_account_id_unique",
|
||||
"primary": false,
|
||||
"type": undefined,
|
||||
"unique": true,
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"id",
|
||||
],
|
||||
"composite": false,
|
||||
"expression": undefined,
|
||||
"keyName": "primary",
|
||||
"primary": true,
|
||||
"type": undefined,
|
||||
"unique": true,
|
||||
},
|
||||
],
|
||||
"name": "account",
|
||||
"schema": undefined,
|
||||
},
|
||||
{
|
||||
"checks": [],
|
||||
"columns": {
|
||||
"expires": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": 0,
|
||||
"mappedType": "datetime",
|
||||
"name": "expires",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "datetime",
|
||||
"unsigned": false,
|
||||
},
|
||||
"identifier": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "identifier",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
"token": {
|
||||
"autoincrement": false,
|
||||
"comment": undefined,
|
||||
"default": undefined,
|
||||
"enumItems": undefined,
|
||||
"extra": undefined,
|
||||
"length": undefined,
|
||||
"mappedType": "text",
|
||||
"name": "token",
|
||||
"nullable": false,
|
||||
"precision": undefined,
|
||||
"primary": false,
|
||||
"scale": undefined,
|
||||
"type": "text",
|
||||
"unsigned": false,
|
||||
},
|
||||
},
|
||||
"comment": undefined,
|
||||
"foreignKeys": {},
|
||||
"indexes": [
|
||||
{
|
||||
"columnNames": [
|
||||
"token",
|
||||
"identifier",
|
||||
],
|
||||
"composite": true,
|
||||
"expression": undefined,
|
||||
"keyName": "verification_token_token_identifier_unique",
|
||||
"primary": false,
|
||||
"type": undefined,
|
||||
"unique": true,
|
||||
},
|
||||
{
|
||||
"columnNames": [
|
||||
"token",
|
||||
],
|
||||
"composite": false,
|
||||
"expression": undefined,
|
||||
"keyName": "primary",
|
||||
"primary": true,
|
||||
"type": undefined,
|
||||
"unique": true,
|
||||
},
|
||||
],
|
||||
"name": "verification_token",
|
||||
"schema": undefined,
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
@@ -1,10 +1,69 @@
|
||||
import type { Options } from "@mikro-orm/core"
|
||||
import { Options, types } from "@mikro-orm/core"
|
||||
import type { SqliteDriver } from "@mikro-orm/sqlite"
|
||||
|
||||
import { MikroORM, wrap } from "@mikro-orm/core"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { MikroOrmAdapter, defaultEntities } from "../src"
|
||||
import { User, VeryImportantEntity } from "./testEntities"
|
||||
import {
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
Unique,
|
||||
} from "@mikro-orm/core"
|
||||
import { randomUUID } from "@next-auth/adapter-test"
|
||||
|
||||
@Entity()
|
||||
export class User implements defaultEntities.User {
|
||||
@PrimaryKey()
|
||||
@Property({ type: types.string })
|
||||
id: string = randomUUID()
|
||||
|
||||
@Property({ type: types.string, nullable: true })
|
||||
name?: string
|
||||
|
||||
@Property({ type: types.string, nullable: true })
|
||||
@Unique()
|
||||
email?: string
|
||||
|
||||
@Property({ type: 'Date', nullable: true })
|
||||
emailVerified: Date | null = null
|
||||
|
||||
@Property({ type: types.string, nullable: true })
|
||||
image?: string
|
||||
|
||||
@OneToMany({
|
||||
entity: 'Session',
|
||||
mappedBy: (session: defaultEntities.Session) => session.user,
|
||||
hidden: true,
|
||||
orphanRemoval: true,
|
||||
cascade: [Cascade.ALL],
|
||||
})
|
||||
sessions = new Collection<defaultEntities.Session>(this)
|
||||
|
||||
@OneToMany({
|
||||
entity: 'Account',
|
||||
mappedBy: (account: defaultEntities.Account) => account.user,
|
||||
hidden: true,
|
||||
orphanRemoval: true,
|
||||
cascade: [Cascade.ALL],
|
||||
})
|
||||
accounts = new Collection<defaultEntities.Account>(this)
|
||||
|
||||
@Property({ type: types.string, hidden: true })
|
||||
role = "ADMIN"
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class VeryImportantEntity {
|
||||
@PrimaryKey()
|
||||
@Property({ type: types.string })
|
||||
id: string = randomUUID()
|
||||
|
||||
@Property({ type: types.boolean })
|
||||
important = true
|
||||
}
|
||||
|
||||
let _init: MikroORM
|
||||
|
||||
28
packages/adapter-mikro-orm/tests/schema.test.ts
Normal file
28
packages/adapter-mikro-orm/tests/schema.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { MikroORM, Options } from "@mikro-orm/core";
|
||||
import { SqliteDriver } from "@mikro-orm/sqlite";
|
||||
import { defaultEntities } from "../src";
|
||||
|
||||
const config: Options<SqliteDriver> = {
|
||||
dbName: "./db.sqlite",
|
||||
type: "sqlite",
|
||||
entities: [
|
||||
defaultEntities.User,
|
||||
defaultEntities.Account,
|
||||
defaultEntities.Session,
|
||||
defaultEntities.VerificationToken,
|
||||
],
|
||||
}
|
||||
|
||||
it("run migrations", async () => {
|
||||
const orm = await MikroORM.init(config)
|
||||
await orm.getSchemaGenerator().dropSchema()
|
||||
|
||||
const createSchemaSQL = await orm.getSchemaGenerator().getCreateSchemaSQL()
|
||||
expect(createSchemaSQL).toMatchSnapshot('createSchemaSQL')
|
||||
|
||||
const targetSchema = await orm.getSchemaGenerator().getTargetSchema()
|
||||
expect(targetSchema).toMatchSnapshot('targetSchema')
|
||||
|
||||
await orm.getSchemaGenerator().dropSchema()
|
||||
await orm.close().catch(() => null)
|
||||
})
|
||||
@@ -1,61 +0,0 @@
|
||||
import {
|
||||
Cascade,
|
||||
Collection,
|
||||
Entity,
|
||||
OneToMany,
|
||||
PrimaryKey,
|
||||
Property,
|
||||
Unique,
|
||||
} from "@mikro-orm/core"
|
||||
import { randomUUID } from "@next-auth/adapter-test"
|
||||
import type { defaultEntities } from "../src"
|
||||
import { Account, Session } from "../src/entities"
|
||||
|
||||
@Entity()
|
||||
export class User implements defaultEntities.User {
|
||||
@PrimaryKey()
|
||||
id: string = randomUUID()
|
||||
|
||||
@Property({ nullable: true })
|
||||
name?: string
|
||||
|
||||
@Property({ nullable: true })
|
||||
@Unique()
|
||||
email?: string
|
||||
|
||||
@Property({ type: "Date", nullable: true })
|
||||
emailVerified: Date | null = null
|
||||
|
||||
@Property({ nullable: true })
|
||||
image?: string
|
||||
|
||||
@OneToMany({
|
||||
entity: () => Session,
|
||||
mappedBy: (session) => session.user,
|
||||
hidden: true,
|
||||
orphanRemoval: true,
|
||||
cascade: [Cascade.ALL],
|
||||
})
|
||||
sessions = new Collection<Session>(this)
|
||||
|
||||
@OneToMany({
|
||||
entity: () => Account,
|
||||
mappedBy: (account) => account.user,
|
||||
hidden: true,
|
||||
orphanRemoval: true,
|
||||
cascade: [Cascade.ALL],
|
||||
})
|
||||
accounts = new Collection<Account>(this)
|
||||
|
||||
@Property({ hidden: true })
|
||||
role = "ADMIN"
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class VeryImportantEntity {
|
||||
@PrimaryKey()
|
||||
id: string = randomUUID()
|
||||
|
||||
@Property()
|
||||
important = true
|
||||
}
|
||||
8
packages/adapter-mikro-orm/tsconfig.eslint.json
Normal file
8
packages/adapter-mikro-orm/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
@@ -8,5 +8,6 @@
|
||||
"outDir": "dist",
|
||||
"stripInternal": true
|
||||
},
|
||||
"exclude": ["tests", "dist", "jest.config.js"]
|
||||
"include": ["src"],
|
||||
"exclude": ["dist", "test", "node_modules"]
|
||||
}
|
||||
|
||||
@@ -72,7 +72,9 @@ import clientPromise from "lib/mongodb"
|
||||
// For more information on each option (and a full list of options) go to
|
||||
// https://next-auth.js.org/configuration/options
|
||||
export default NextAuth({
|
||||
adapter: MongoDBAdapter(clientPromise),
|
||||
adapter: MongoDBAdapter(clientPromise, {
|
||||
databaseName: 'my-data-base-name'
|
||||
}),
|
||||
...
|
||||
})
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/mongodb-adapter",
|
||||
"version": "1.0.4",
|
||||
"version": "1.1.0",
|
||||
"description": "mongoDB adapter for next-auth.",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -35,8 +35,8 @@
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"jest": "^27.4.3",
|
||||
"mongodb": "^4.4.0",
|
||||
"next-auth": "workspace:*"
|
||||
|
||||
@@ -17,6 +17,7 @@ export interface MongoDBAdapterOptions {
|
||||
Sessions?: string
|
||||
VerificationTokens?: string
|
||||
}
|
||||
databaseName?: string
|
||||
}
|
||||
|
||||
export const defaultCollections: Required<
|
||||
@@ -73,7 +74,7 @@ export function MongoDBAdapter(
|
||||
const { from, to } = format
|
||||
|
||||
const db = (async () => {
|
||||
const _db = (await client).db()
|
||||
const _db = (await client).db(options.databaseName)
|
||||
const c = { ...defaultCollections, ...collections }
|
||||
return {
|
||||
U: _db.collection<AdapterUser>(c.Users),
|
||||
|
||||
8
packages/adapter-mongodb/tsconfig.eslint.json
Normal file
8
packages/adapter-mongodb/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"jest": "^27.4.3",
|
||||
"neo4j-driver": "^4.4.0",
|
||||
|
||||
8
packages/adapter-neo4j/tsconfig.eslint.json
Normal file
8
packages/adapter-neo4j/tsconfig.eslint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["tests", "src"],
|
||||
"exclude": [
|
||||
"./*.js",
|
||||
"./*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@next-auth/tsconfig/adapters.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.adapters.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
"ulid": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/pouchdb": "^6.4.0",
|
||||
"jest": "^27.4.3",
|
||||
"next-auth": "workspace:*",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user