Compare commits
67 Commits
feat/nextj
...
feat/docs-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
657dd57ef7 | ||
|
|
39691313fb | ||
|
|
a7e02266cf | ||
|
|
bac8b8d13a | ||
|
|
bb4d5ce29b | ||
|
|
436d46ab89 | ||
|
|
b17dc76a70 | ||
|
|
b96f01319c | ||
|
|
5fb4caa485 | ||
|
|
24e8100a61 | ||
|
|
b17c5deafb | ||
|
|
7da32563d6 | ||
|
|
c470960d93 | ||
|
|
8cfd1aeb15 | ||
|
|
af81776e4b | ||
|
|
3ba510c0e0 | ||
|
|
65fe0ef363 | ||
|
|
587d3666fc | ||
|
|
8f416b68ec | ||
|
|
e4d568c220 | ||
|
|
aaff906c68 | ||
|
|
8f40883de5 | ||
|
|
eaf5080721 | ||
|
|
601c8c915f | ||
|
|
e0b5f18c5b | ||
|
|
7fae8744b2 | ||
|
|
99247ce446 | ||
|
|
0afb1797ba | ||
|
|
d6bc65f0d8 | ||
|
|
0b80c65a0c | ||
|
|
a7991aed15 | ||
|
|
c47a2eb7ac | ||
|
|
6f5a50313f | ||
|
|
3c23a4f4e2 | ||
|
|
52c04fe89e | ||
|
|
440317aa2f | ||
|
|
18a4e8b255 | ||
|
|
c411c6f5dc | ||
|
|
46f622a5b4 | ||
|
|
1b984f09ab | ||
|
|
fbc1ed857c | ||
|
|
0d6ad6beb6 | ||
|
|
b972742171 | ||
|
|
01d6f86538 | ||
|
|
bf89d9fabb | ||
|
|
90b01c4613 | ||
|
|
47794e68cc | ||
|
|
0c6b8581a7 | ||
|
|
7ece5a0a9d | ||
|
|
828e38c976 | ||
|
|
47d4a3f80f | ||
|
|
14f9388148 | ||
|
|
46659f04b7 | ||
|
|
fc4abd174f | ||
|
|
ebefd25bd6 | ||
|
|
e3bdb38df2 | ||
|
|
da9ce95677 | ||
|
|
8c99f5c9cf | ||
|
|
92a0fc42fa | ||
|
|
62e2ad115c | ||
|
|
5551c4f147 | ||
|
|
e2ef07688c | ||
|
|
542c35d729 | ||
|
|
e62fa3a0af | ||
|
|
771e993ce9 | ||
|
|
c4a15ae3dd | ||
|
|
80d1a8fd70 |
9
.github/version-pr/index.js
vendored
@@ -5,14 +5,15 @@ const core = require("@actions/core")
|
||||
try {
|
||||
const packageJSONPath = path.join(
|
||||
process.cwd(),
|
||||
"packages/next-auth/package.json"
|
||||
`packages/${process.env.PACKAGE_PATH || "next-auth"}/package.json`
|
||||
)
|
||||
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, "utf8"))
|
||||
|
||||
const sha8 = process.env.GITHUB_SHA.substring(0, 8)
|
||||
const prNumber = process.env.PR_NUMBER
|
||||
|
||||
const packageVersion = `0.0.0-pr.${prNumber}.${sha8}`
|
||||
const prefix = "0.0.0-"
|
||||
const pr = process.env.PR_NUMBER
|
||||
const source = pr ? `pr.${pr}` : "manual"
|
||||
const packageVersion = `${prefix}${source}.${sha8}`
|
||||
packageJSON.version = packageVersion
|
||||
core.setOutput("version", packageVersion)
|
||||
fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON))
|
||||
|
||||
49
.github/workflows/release.yml
vendored
@@ -8,6 +8,24 @@ on:
|
||||
- next
|
||||
- 3.x
|
||||
pull_request:
|
||||
# TODO: Support latest releases
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
name:
|
||||
type: choice
|
||||
description: Package name (npm)
|
||||
options:
|
||||
- "@auth/nextjs"
|
||||
- "@auth/core"
|
||||
- "next-auth"
|
||||
# TODO: Infer from package name
|
||||
path:
|
||||
type: choice
|
||||
description: Directory name (packages/*)
|
||||
options:
|
||||
- "frameworks-nextjs"
|
||||
- "core"
|
||||
- "next-auth"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -122,3 +140,34 @@ jobs:
|
||||
env:
|
||||
VERSION: ${{ steps.determine-version.outputs.version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
|
||||
release-manual:
|
||||
name: Publish manually
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
steps:
|
||||
- name: Init
|
||||
uses: actions/checkout@v3
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- name: Determine version
|
||||
uses: ./.github/version-pr
|
||||
id: determine-version
|
||||
env:
|
||||
PACKAGE_PATH: ${{ github.event.inputs.path }}
|
||||
- name: Publish to npm
|
||||
run: |
|
||||
cd packages/$PACKAGE_PATH
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
|
||||
pnpm publish --no-git-checks --access public --tag experimental
|
||||
echo "🎉 Experimental release published 📦️ on npm: https://npmjs.com/package/${{ github.event.inputs.name }}/v/${{ env.VERSION }}"
|
||||
echo "Install via: pnpm add ${{ github.event.inputs.name }}@${{ env.VERSION }}"
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
PACKAGE_PATH: ${{ github.event.inputs.path }}
|
||||
VERSION: ${{ steps.determine-version.outputs.version }}
|
||||
|
||||
14
.gitignore
vendored
@@ -26,7 +26,15 @@ dist
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
packages/next-auth/providers
|
||||
packages/next-auth/src/providers/oauth-types.ts
|
||||
packages/next-auth/client
|
||||
packages/next-auth/css
|
||||
packages/next-auth/utils
|
||||
packages/next-auth/core
|
||||
packages/next-auth/jwt
|
||||
packages/next-auth/react
|
||||
packages/next-auth/next
|
||||
packages/*/*.js
|
||||
packages/*/*.d.ts
|
||||
packages/*/*.d.ts.map
|
||||
@@ -77,10 +85,10 @@ packages/core/providers
|
||||
packages/core/src/lib/pages/styles.ts
|
||||
docs/docs/reference/core
|
||||
docs/docs/reference/sveltekit
|
||||
docs/docs/reference/next-auth
|
||||
docs/docs/reference/nextjs
|
||||
|
||||
# Next.js
|
||||
packages/next-auth/lib
|
||||
packages/frameworks-nextjs/lib
|
||||
|
||||
# SvelteKit
|
||||
packages/frameworks-sveltekit/index.*
|
||||
|
||||
@@ -40,6 +40,10 @@ packages/core/src/lib/pages/styles.ts
|
||||
packages/frameworks-sveltekit/package
|
||||
packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*
|
||||
|
||||
# next-auth
|
||||
packages/next-auth/src/providers/oauth-types.ts
|
||||
packages/next-auth/css/index.css
|
||||
|
||||
|
||||
# Adapters
|
||||
.branches
|
||||
|
||||
6
.vscode/settings.json
vendored
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"files.exclude": {
|
||||
"packages/core/{lib,providers,*.js,*.d.ts*}": true,
|
||||
"packages/next-auth/{lib,*.js,*.d.ts*}": true,
|
||||
"packages/core/{lib,providers,*.js,*.d.ts,*.d.ts.map}": true,
|
||||
"packages/next-auth/{client,core,css,jwt,next,providers,react,utils,*.js,*.d.ts}": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"openInGitHub.remote.branch": "main"
|
||||
}
|
||||
}
|
||||
|
||||
10
apps/dev/nextjs/app/client.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect } from "react"
|
||||
|
||||
export default function Client({ session }: any) {
|
||||
useEffect(() => {
|
||||
console.log(window.location)
|
||||
})
|
||||
return <div>{JSON.stringify(session)}</div>
|
||||
}
|
||||
3
apps/dev/nextjs/app/dashboard/page.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Page() {
|
||||
return <h1>This page is protected.</h1>
|
||||
}
|
||||
@@ -1,12 +1,54 @@
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
import { auth } from "auth"
|
||||
import Footer from "components/footer"
|
||||
import { Header } from "components/header"
|
||||
import { cookies, headers } from "next/headers"
|
||||
import styles from "components/header.module.css"
|
||||
import "./styles.css"
|
||||
|
||||
export default function RootLayout(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html>
|
||||
<head></head>
|
||||
<body>{children}</body>
|
||||
<body>
|
||||
{/* @ts-expect-error */}
|
||||
<AppHeader />
|
||||
<main>{props.children}</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
||||
function SignIn({ id, ...props }: any) {
|
||||
const $cookies = cookies()
|
||||
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
|
||||
const action = id ? `/api/auth/signin/${id}` : "/api/auth/signin"
|
||||
return (
|
||||
<form action={action} method="post">
|
||||
<button {...props} />
|
||||
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
function SignOut(props: any) {
|
||||
const $cookies = cookies()
|
||||
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
|
||||
return (
|
||||
<form action="/api/auth/signout" method="post">
|
||||
<button {...props} />
|
||||
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export async function AppHeader() {
|
||||
const session = await auth(headers())
|
||||
return (
|
||||
<Header
|
||||
session={session}
|
||||
signIn={<SignIn className={styles.buttonPrimary}>Sign in</SignIn>}
|
||||
signOut={<SignOut className={styles.button}>Sign out</SignOut>}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
17
apps/dev/nextjs/app/page.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { auth } from "auth"
|
||||
import { headers } from "next/headers"
|
||||
import Client from "./client"
|
||||
|
||||
export default async function Page() {
|
||||
const session = await auth(headers())
|
||||
return (
|
||||
<>
|
||||
<Client session={session} />
|
||||
<h1>NextAuth.js Example</h1>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use{" "}
|
||||
<a href="https://nextjs.authjs.dev">NextAuth.js</a> for authentication.
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { auth } from "auth"
|
||||
import { cookies, headers } from "next/headers"
|
||||
|
||||
function SignIn({ id, children }: any) {
|
||||
const $cookies = cookies()
|
||||
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
|
||||
return (
|
||||
<form action={`/api/auth/signin/${id}`} method="post">
|
||||
<button type="submit">{children}</button>
|
||||
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
function SignOut({ children }: any) {
|
||||
const $cookies = cookies()
|
||||
const csrfToken = $cookies.get("next-auth.csrf-token")?.value.split("|")[0]
|
||||
return (
|
||||
<form action="/api/auth/signout" method="post">
|
||||
<button type="submit">{children}</button>
|
||||
<input type="hidden" name="csrfToken" value={csrfToken} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default async function Page() {
|
||||
const session = await auth(headers())
|
||||
if (session) {
|
||||
return (
|
||||
<>
|
||||
<pre>{JSON.stringify(session, null, 2)}</pre>
|
||||
<SignOut>Sign out</SignOut>
|
||||
</>
|
||||
)
|
||||
}
|
||||
return <SignIn id="github">Sign in with github</SignIn>
|
||||
}
|
||||
32
apps/dev/nextjs/app/styles.css
Normal file
@@ -0,0 +1,32 @@
|
||||
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";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
li,
|
||||
p {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
iframe {
|
||||
background: #ccc;
|
||||
border: 1px solid #ccc;
|
||||
height: 10rem;
|
||||
width: 100%;
|
||||
border-radius: 0.5rem;
|
||||
filter: invert(1);
|
||||
}
|
||||
@@ -1,21 +1,31 @@
|
||||
import { NextAuth } from "next-auth"
|
||||
import NextAuth from "@auth/nextjs"
|
||||
import Auth0 from "@auth/core/providers/auth0"
|
||||
import Facebook from "@auth/core/providers/facebook"
|
||||
import GitHub from "@auth/core/providers/github"
|
||||
import Google from "@auth/core/providers/google"
|
||||
import Twitter from "@auth/core/providers/twitter"
|
||||
import Credentials from "@auth/core/providers/credentials"
|
||||
|
||||
export const { handlers, auth } = NextAuth({
|
||||
providers: [GitHub],
|
||||
export const { handlers, auth, getServerSession } = NextAuth({
|
||||
debug: true,
|
||||
providers: [
|
||||
GitHub,
|
||||
Auth0,
|
||||
Facebook,
|
||||
Google,
|
||||
Twitter,
|
||||
Credentials({
|
||||
credentials: { password: { label: "Password", type: "password" } },
|
||||
authorize(c) {
|
||||
if (c.password !== "password") return null
|
||||
return { id: "test", name: "Test User", email: "test@example.com" }
|
||||
},
|
||||
}),
|
||||
],
|
||||
callbacks: {
|
||||
async authorized({ request, auth }) {
|
||||
// if (request.method === "POST") {
|
||||
// const [, token] = request.headers.get("Authorization")?.split(" ")
|
||||
// const valid = validateToken(token)
|
||||
// // If the request has a valid auth token, it is authorized
|
||||
// if (valid) return true
|
||||
// return NextResponse.json("Invalid auth token", { status: 401 })
|
||||
// }
|
||||
|
||||
// Logged in users are authorized, otherwise, will redirect to login
|
||||
// You could also return a custom redirect instead of the sign-in page
|
||||
return !!auth
|
||||
async authorized({ request: { nextUrl }, auth }) {
|
||||
if (nextUrl.pathname === "/dashboard") return !!auth.user
|
||||
return true
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { signIn } from "next-auth/react"
|
||||
import { signIn } from "@auth/nextjs/react"
|
||||
|
||||
export default function AccessDenied() {
|
||||
return (
|
||||
@@ -1,6 +1,6 @@
|
||||
import Link from "next/link"
|
||||
import styles from "./footer.module.css"
|
||||
import packageJSON from "next-auth/package.json"
|
||||
import packageJSON from "@auth/nextjs/package.json"
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
@@ -1,83 +0,0 @@
|
||||
import Link from "next/link"
|
||||
import { useSession } from "next-auth/react"
|
||||
import styles from "./header.module.css"
|
||||
|
||||
// The approach used in this component shows how to built a sign in and sign out
|
||||
// component that works on pages which support both client and server side
|
||||
// rendering, and avoids any flash incorrect content on initial page load.
|
||||
export default function Header() {
|
||||
const { data: session, status } = useSession()
|
||||
|
||||
return (
|
||||
<header>
|
||||
<noscript>
|
||||
<style>{".nojs-show { opacity: 1; top: 0; }"}</style>
|
||||
</noscript>
|
||||
<div className={styles.signedInStatus}>
|
||||
<p
|
||||
className={`nojs-show ${
|
||||
!session && status === "loading" ? styles.loading : styles.loaded
|
||||
}`}
|
||||
>
|
||||
{!session && (
|
||||
<>
|
||||
<span className={styles.notSignedInText}>
|
||||
You are not signed in
|
||||
</span>
|
||||
<a href="/api/auth/signin" className={styles.buttonPrimary}>
|
||||
Sign in
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
{session && (
|
||||
<>
|
||||
{session.user.image && (
|
||||
<img src={session.user.image} className={styles.avatar} />
|
||||
)}
|
||||
<span className={styles.signedInText}>
|
||||
<small>Signed in as</small>
|
||||
<br />
|
||||
<strong>{session.user.email} </strong>
|
||||
{session.user.name ? `(${session.user.name})` : null}
|
||||
</span>
|
||||
<a href="/api/auth/signout" className={styles.button}>
|
||||
Sign out
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<nav>
|
||||
<ul className={styles.navItems}>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/">Home</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/client">Client</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/server">Server</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/protected">Protected</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/protected-ssr">Protected(SSR)</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/api-example">API</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/credentials">Credentials</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/email">Email</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/middleware-protected">Middleware protected</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Set min-height to avoid page reflow while session loading */
|
||||
.signedInStatus {
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 4rem;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -25,16 +26,13 @@
|
||||
|
||||
.signedInText,
|
||||
.notSignedInText {
|
||||
position: absolute;
|
||||
padding-top: 0.8rem;
|
||||
left: 1rem;
|
||||
right: 6.5rem;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: inherit;
|
||||
z-index: 1;
|
||||
line-height: 1.3rem;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.signedInText {
|
||||
@@ -47,6 +45,7 @@
|
||||
float: left;
|
||||
height: 2.8rem;
|
||||
width: 2.8rem;
|
||||
margin-right: 1rem;
|
||||
background-color: white;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
@@ -54,10 +53,11 @@
|
||||
|
||||
.button,
|
||||
.buttonPrimary {
|
||||
float: right;
|
||||
margin-right: -0.4rem;
|
||||
justify-self: end;
|
||||
font-weight: 500;
|
||||
border-radius: 0.3rem;
|
||||
border: none;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
line-height: 1.4rem;
|
||||
|
||||
55
apps/dev/nextjs/components/header.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import Link from "next/link"
|
||||
import styles from "./header.module.css"
|
||||
|
||||
export function Header({ session, signIn, signOut }: any) {
|
||||
return (
|
||||
<header>
|
||||
<div className={styles.signedInStatus}>
|
||||
{!session && (
|
||||
<>
|
||||
<span className={styles.notSignedInText}>
|
||||
You are not signed in
|
||||
</span>
|
||||
{signIn}
|
||||
</>
|
||||
)}
|
||||
{session && (
|
||||
<>
|
||||
{session.user.picture && (
|
||||
<img src={session.user.picture} className={styles.avatar} />
|
||||
)}
|
||||
<span className={styles.signedInText}>
|
||||
<small>Signed in as</small>
|
||||
<br />
|
||||
<strong>{session.user.email} </strong>
|
||||
{session.user.name ? `(${session.user.name})` : null}
|
||||
</span>
|
||||
{signOut}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<nav>
|
||||
<ul className={styles.navItems}>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/">Home (app)</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/dashboard">Dashboard (app)</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/policy">Policy (pages)</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/credentials">Credentials (pages)</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/protected-ssr">getServerSideProps (pages)</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/api/examples/protected">API Route (pages)</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import Header from "components/header"
|
||||
import Footer from "components/footer"
|
||||
|
||||
export default function Layout({ children }) {
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +1 @@
|
||||
// export { auth as default } from "auth"
|
||||
import { auth } from "auth"
|
||||
import { NextResponse } from "next/server"
|
||||
|
||||
export default auth((req) => {
|
||||
if (req.auth) return NextResponse.json(req.auth)
|
||||
return NextResponse.json("Not authorized", { status: 401 })
|
||||
})
|
||||
|
||||
export const config = { matcher: ["/middleware-protected"] }
|
||||
export { auth as default } from "auth"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@auth/core": "workspace:*",
|
||||
"next-auth": "workspace:*",
|
||||
"@auth/nextjs": "workspace:*",
|
||||
"@next-auth/fauna-adapter": "workspace:*",
|
||||
"@next-auth/prisma-adapter": "workspace:*",
|
||||
"@next-auth/supabase-adapter": "workspace:*",
|
||||
@@ -23,7 +23,7 @@
|
||||
"@prisma/client": "^3",
|
||||
"@supabase/supabase-js": "^2.0.5",
|
||||
"faunadb": "^4",
|
||||
"next": "13.3.2-canary.12",
|
||||
"next": "13.4.0",
|
||||
"next-auth": "workspace:*",
|
||||
"nodemailer": "^6",
|
||||
"react": "^18",
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { SessionProvider } from "next-auth/react"
|
||||
import "./styles.css"
|
||||
|
||||
export default function App({ Component, pageProps }) {
|
||||
return (
|
||||
<SessionProvider session={pageProps.session}>
|
||||
<Component {...pageProps} />
|
||||
</SessionProvider>
|
||||
)
|
||||
}
|
||||
39
apps/dev/nextjs/pages/_app.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
SessionProvider,
|
||||
signIn,
|
||||
signOut,
|
||||
useSession,
|
||||
} from "@auth/nextjs/react"
|
||||
import "./styles.css"
|
||||
import { Header } from "components/header"
|
||||
import styles from "components/header.module.css"
|
||||
import Footer from "components/footer"
|
||||
|
||||
export default function App({ Component, pageProps }) {
|
||||
return (
|
||||
<SessionProvider session={pageProps.session}>
|
||||
<PagesHeader />
|
||||
<Component {...pageProps} />
|
||||
<Footer />
|
||||
</SessionProvider>
|
||||
)
|
||||
}
|
||||
|
||||
function PagesHeader() {
|
||||
const { data: session } = useSession()
|
||||
return (
|
||||
<Header
|
||||
session={session}
|
||||
signIn={
|
||||
<button onClick={() => signIn()} className={styles.buttonPrimary}>
|
||||
Sign in
|
||||
</button>
|
||||
}
|
||||
signOut={
|
||||
<button onClick={() => signOut()} className={styles.button}>
|
||||
Sign out
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
// This is an example of to protect an API route
|
||||
import { authConfig } from "../auth-old/[...nextauth]"
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { getServerSession } from "auth"
|
||||
|
||||
export default async (req, res) => {
|
||||
const session = await getServerSession(req, res, authConfig as any)
|
||||
const session = await getServerSession(req, res)
|
||||
|
||||
if (session) {
|
||||
res.send({
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
import * as React from "react"
|
||||
import { signIn, signOut, useSession } from "next-auth/react"
|
||||
import Layout from "components/layout"
|
||||
|
||||
export default function Page() {
|
||||
const [response, setResponse] = React.useState(null)
|
||||
const handleLogin = (options) => async () => {
|
||||
if (options.redirect) {
|
||||
return signIn("credentials", options)
|
||||
}
|
||||
const response = await signIn("credentials", options)
|
||||
setResponse(response)
|
||||
}
|
||||
|
||||
const handleLogout = (options) => async () => {
|
||||
if (options.redirect) {
|
||||
return signOut(options)
|
||||
}
|
||||
const response = await signOut(options)
|
||||
setResponse(response)
|
||||
}
|
||||
|
||||
const { data: session } = useSession()
|
||||
|
||||
if (session) {
|
||||
return (
|
||||
<Layout>
|
||||
<h1>Test different flows for Credentials logout</h1>
|
||||
<span className="spacing">Default:</span>
|
||||
<button onClick={handleLogout({ redirect: true })}>Logout</button>
|
||||
<br />
|
||||
<span className="spacing">No redirect:</span>
|
||||
<button onClick={handleLogout({ redirect: false })}>Logout</button>
|
||||
<br />
|
||||
<p>Response:</p>
|
||||
<pre style={{ background: "#eee", padding: 16 }}>
|
||||
{JSON.stringify(response, null, 2)}
|
||||
</pre>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<h1>Test different flows for Credentials login</h1>
|
||||
<span className="spacing">Default:</span>
|
||||
<button onClick={handleLogin({ redirect: true, password: "password" })}>
|
||||
Login
|
||||
</button>
|
||||
<br />
|
||||
<span className="spacing">No redirect:</span>
|
||||
<button onClick={handleLogin({ redirect: false, password: "password" })}>
|
||||
Login
|
||||
</button>
|
||||
<br />
|
||||
<span className="spacing">No redirect, wrong password:</span>
|
||||
<button onClick={handleLogin({ redirect: false, password: "" })}>
|
||||
Login
|
||||
</button>
|
||||
<p>Response:</p>
|
||||
<pre style={{ background: "#eee", padding: 16 }}>
|
||||
{JSON.stringify(response, null, 2)}
|
||||
</pre>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
67
apps/dev/nextjs/pages/credentials.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import * as React from "react"
|
||||
import { signIn, signOut, useSession } from "@auth/nextjs/react"
|
||||
import { SignInResponse, SignOutResponse } from "@auth/nextjs/lib/client"
|
||||
|
||||
export default function Page() {
|
||||
const [response, setResponse] = React.useState<
|
||||
SignInResponse | SignOutResponse
|
||||
>()
|
||||
|
||||
const { data: session } = useSession()
|
||||
|
||||
if (session) {
|
||||
return (
|
||||
<>
|
||||
<h1>Test different flows for Credentials logout</h1>
|
||||
<span className="spacing">Default: </span>
|
||||
<button onClick={() => signOut()}>Logout</button>
|
||||
<br />
|
||||
<span className="spacing">No redirect: </span>
|
||||
<button onClick={() => signOut({ redirect: false }).then(setResponse)}>
|
||||
Logout
|
||||
</button>
|
||||
<br />
|
||||
<p>{response ? "Response:" : "Session:"}</p>
|
||||
<pre style={{ background: "#eee", padding: 16 }}>
|
||||
{JSON.stringify(response ?? session, null, 2)}
|
||||
</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>Test different flows for Credentials login</h1>
|
||||
<span className="spacing">Default: </span>
|
||||
<button onClick={() => signIn("credentials", { password: "password" })}>
|
||||
Login
|
||||
</button>
|
||||
<br />
|
||||
<span className="spacing">No redirect: </span>
|
||||
<button
|
||||
onClick={() =>
|
||||
signIn("credentials", { redirect: false, password: "password" }).then(
|
||||
setResponse
|
||||
)
|
||||
}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
<br />
|
||||
<span className="spacing">No redirect, wrong password: </span>
|
||||
<button
|
||||
onClick={() =>
|
||||
signIn("credentials", { redirect: false, password: "wrong" }).then(
|
||||
setResponse
|
||||
)
|
||||
}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
<p>Response:</p>
|
||||
<pre style={{ background: "#eee", padding: 16 }}>
|
||||
{JSON.stringify(response, null, 2)}
|
||||
</pre>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import Layout from "components/layout"
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<Layout>
|
||||
<h1>NextAuth.js Example</h1>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use{" "}
|
||||
<a href="https://authjs.dev">NextAuth.js</a> for authentication.
|
||||
</p>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import Layout from "components/layout"
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<Layout>
|
||||
<h1>Page protected by Middleware</h1>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
import Layout from "../components/layout"
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<p>
|
||||
This is an example site to demonstrate how to use{" "}
|
||||
<a href="https://authjs.dev">Auth.js</a> for authentication.
|
||||
@@ -18,15 +16,11 @@ export default function Page() {
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</p>
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>
|
||||
This site uses JSON Web Tokens and an in-memory database which resets
|
||||
every ~2 hours.
|
||||
</p>
|
||||
<p>
|
||||
Data provided to this site is exclusively used to support signing in and
|
||||
is not passed to any third party services, other than via SMTP or OAuth
|
||||
for the purposes of authentication.
|
||||
</p>
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,48 +1,34 @@
|
||||
// This is an example of how to protect content using server rendering
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { authConfig } from "./api/auth-old/[...nextauth]"
|
||||
import Layout from "../components/layout"
|
||||
import AccessDenied from "../components/access-denied"
|
||||
import { getServerSession } from "auth"
|
||||
import AccessDenied from "components/access-denied"
|
||||
|
||||
export default function Page({ content, session }) {
|
||||
// If no session exists, display access denied message
|
||||
if (!session) {
|
||||
return (
|
||||
<Layout>
|
||||
<AccessDenied />
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
if (!session) return <AccessDenied />
|
||||
|
||||
// If session exists, display content
|
||||
return (
|
||||
<Layout>
|
||||
<>
|
||||
<h1>Protected Page</h1>
|
||||
<p>
|
||||
<strong>{content}</strong>
|
||||
</p>
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const session = await getServerSession(context.req, context.res, authConfig)
|
||||
let content = null
|
||||
|
||||
const session = await getServerSession(context.req, context.res)
|
||||
if (session) {
|
||||
// Note usually you don't need to fetch from an API route in getServerSideProps
|
||||
// This is done here to demonstrate how you can fetch from a third-party API
|
||||
// with a valid session. Likely you would also not pass cookies but an `Authorization` header
|
||||
const hostname = process.env.NEXTAUTH_URL || "http://localhost:3000"
|
||||
const options = { headers: { cookie: context.req.headers.cookie } }
|
||||
const res = await fetch(`${hostname}/api/examples/protected`, options)
|
||||
const json = await res.json()
|
||||
if (json.content) {
|
||||
content = json.content
|
||||
}
|
||||
const res = await fetch(`${hostname}/api/examples/protected`, {
|
||||
headers: { cookie: context.req.headers.cookie },
|
||||
})
|
||||
return { props: { session, content: (await res.json()).content } }
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
session,
|
||||
content,
|
||||
},
|
||||
}
|
||||
return { props: {} }
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import Layout from "../components/layout"
|
||||
import { authConfig } from "./api/auth-old/[...nextauth]"
|
||||
|
||||
export default function Page() {
|
||||
// As this page uses Server Side Rendering, the `session` will be already
|
||||
// populated on render without needing to go through a loading stage.
|
||||
// This is possible because of the shared context configured in `_app.js` that
|
||||
// is used by `useSession()`.
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<h1>Server Side Rendering</h1>
|
||||
<p>
|
||||
This page uses the <strong>getServerSession()</strong> method in{" "}
|
||||
<strong>getServerSideProps()</strong>.
|
||||
</p>
|
||||
<p>
|
||||
Using <strong>getServerSession()</strong> in{" "}
|
||||
<strong>getServerSideProps()</strong> is currently the recommended
|
||||
approach, although the API may still change, if you need to support
|
||||
Server Side Rendering with authentication.
|
||||
</p>
|
||||
<p>
|
||||
Using <strong>getSession()</strong> is still recommended on the client.
|
||||
</p>
|
||||
<p>
|
||||
The advantage of Server Side Rendering is this page does not require
|
||||
client side JavaScript.
|
||||
</p>
|
||||
<p>
|
||||
The disadvantage of Server Side Rendering is that this page is slower to
|
||||
render.
|
||||
</p>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
// Export the `session` prop to use sessions with Server Side Rendering
|
||||
export async function getServerSideProps(context) {
|
||||
return {
|
||||
props: {
|
||||
session: await getServerSession(context.req, context.res, authConfig),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,17 @@
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
NEXTAUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.vercel.app/32
|
||||
AUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.vercel.app/32
|
||||
|
||||
AUTH_AUTH0_ID=
|
||||
AUTH_AUTH0_SECRET=
|
||||
AUTH_AUTH0_ISSUER=
|
||||
|
||||
AUTH0_ID=
|
||||
AUTH0_SECRET=
|
||||
AUTH0_ISSUER=
|
||||
AUTH_FACEBOOK_ID=
|
||||
AUTH_FACEBOOK_SECRET=
|
||||
|
||||
FACEBOOK_ID=
|
||||
FACEBOOK_SECRET=
|
||||
AUTH_GITHUB_ID=
|
||||
AUTH_GITHUB_SECRET=
|
||||
|
||||
GITHUB_ID=
|
||||
GITHUB_SECRET=
|
||||
AUTH_GOOGLE_ID=
|
||||
AUTH_GOOGLE_SECRET=
|
||||
|
||||
GOOGLE_ID=
|
||||
GOOGLE_SECRET=
|
||||
|
||||
TWITTER_ID=
|
||||
TWITTER_SECRET=
|
||||
AUTH_TWITTER_ID=
|
||||
AUTH_TWITTER_SECRET=
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import NextAuth from "next-auth"
|
||||
import Auth0 from "@auth/core/providers/github"
|
||||
import Facebook from "@auth/core/providers/facebook"
|
||||
import GitHub from "@auth/core/providers/github"
|
||||
import Google from "@auth/core/providers/google"
|
||||
import Twitter from "@auth/core/providers/twitter"
|
||||
|
||||
export const { handlers, auth } = NextAuth({
|
||||
providers: [GitHub],
|
||||
providers: [GitHub, Auth0, Facebook, Google, Twitter],
|
||||
callbacks: {
|
||||
async authorized({ request, auth }) {
|
||||
// if (request.method === "POST") {
|
||||
|
||||
32
docs/docs/getting-started/upgrade-to-v5.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Upgrade Guide (v5)
|
||||
---
|
||||
|
||||
NextAuth.js version 5 will continue to be shipped as `next-auth` *for the Next.js version only*. We're here to help you upgrade your applications as smoothly as possible. It is possible to upgrade from any version of 4.x to the latest v5 release by following the migration steps below.
|
||||
|
||||
Upgrade to the latest version by running:
|
||||
|
||||
```bash npm2yarn2pnpm
|
||||
npm install next-auth
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Below is a summary of the high-level API changes in `next-auth` v5.
|
||||
|
||||
```
|
||||
| Where | Old | New |
|
||||
| ------------------------- | --------------------------------------------------- | -------------- |
|
||||
| API Route (Node) | getServerSession(req, res, authOptions) | auth() wrapper |
|
||||
| API Route (Edge) | - | auth() wrapper |
|
||||
| getServerSideProps | getServerSession(ctx.req, ctx.res, authOptions) | auth() wrapper |
|
||||
| Middleware | withAuth(middleware, subset of authOptions) wrapper | auth() wrapper |
|
||||
| Route Handler | - | auth() wrapper |
|
||||
| Server Component | getServerSession(authOptions) | auth() call |
|
||||
| Client Component | useSession() hook | useAuth() hook |
|
||||
```
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
We hope this migration goes smoothly for each and every one of you! If you have any questions or get stuck anywhere, feel free to create [a new issue](https://github.com/nextauthjs/next-auth/issues/new) on GitHub.
|
||||
@@ -12,9 +12,10 @@ The API reference is being migrated from the [old documentation page](https://ne
|
||||
|
||||
Here are the _currently_ planned and released packages under the `@auth/*` scope. This is not an exhaustive list, but the set of packages that we would like to focus on to begin with.
|
||||
|
||||
| Feature | Status |
|
||||
| Package | Status |
|
||||
| ------------------- | -------- |
|
||||
| `@auth/nextjs` | Planned |
|
||||
| `next-auth@4 ` | Stable. See [docs](https://next-auth.js.org/) |
|
||||
| `@auth/nextjs` | Experimental, under `next-auth@5`. |
|
||||
| `@auth/*-adapter` | Planned |
|
||||
| `@auth/core` | Experimental |
|
||||
| `@auth/sveltekit` | Experimental |
|
||||
|
||||
@@ -249,7 +249,7 @@ const docusaurusConfig = {
|
||||
plugins: [
|
||||
typedocFramework("core", ["index.ts", "adapters.ts", "errors.ts", "jwt.ts", "types.ts"]),
|
||||
typedocFramework("frameworks-sveltekit", ["lib/index.ts", "lib/client.ts"]),
|
||||
typedocFramework("next-auth", ["index.ts", "react.tsx", "jwt.ts", "adapters.ts", "next.ts", "types.ts", "middleware.ts"]),
|
||||
typedocFramework("frameworks-nextjs", ["index.ts", "react.tsx", "jwt.ts", "adapters.ts", "next.ts", "types.ts", "middleware.ts"]),
|
||||
...(process.env.TYPEDOC_SKIP_ADAPTERS
|
||||
? []
|
||||
: [
|
||||
|
||||
@@ -36,8 +36,8 @@ module.exports = {
|
||||
{
|
||||
type: "category",
|
||||
label: "next-auth",
|
||||
link: { type: "doc", id: "reference/next-auth/index" },
|
||||
items: [{ type: "autogenerated", dirName: "reference/next-auth" }],
|
||||
link: { type: "doc", id: "reference/nextjs/index" },
|
||||
items: [{ type: "autogenerated", dirName: "reference/nextjs" }],
|
||||
},
|
||||
...(process.env.TYPEDOC_SKIP_ADAPTERS
|
||||
? []
|
||||
|
||||
@@ -66,6 +66,16 @@
|
||||
"has": [{ "type": "host", "value": "solid-start.authjs.dev" }],
|
||||
"destination": "https://authjs.dev/reference/solid-start"
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "nextjs.authjs.dev" }],
|
||||
"destination": "https://authjs.dev/reference/nextjs"
|
||||
},
|
||||
{
|
||||
"source": "/v5",
|
||||
"has": [{ "type": "host", "value": "nextjs.authjs.dev" }],
|
||||
"destination": "https://authjs.dev/getting-started/upgrade-to-v5"
|
||||
},
|
||||
{
|
||||
"source": "/:path(.*)",
|
||||
"has": [{ "type": "host", "value": "errors.authjs.dev" }],
|
||||
|
||||
@@ -42,8 +42,6 @@ import type { Adapter, AdapterAccount } from "next-auth/adapters"
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ## Advanced usage
|
||||
*
|
||||
* ### Create the Prisma schema from scratch
|
||||
*
|
||||
* You need to use at least Prisma 2.26.0. Create a schema file in `prisma/schema.prisma` similar to this one:
|
||||
|
||||
@@ -125,7 +125,12 @@ export class MissingSecret extends AuthError {}
|
||||
*/
|
||||
export class OAuthAccountNotLinked extends AuthError {}
|
||||
|
||||
/** @todo */
|
||||
/**
|
||||
* Thrown when an OAuth provider returns an error during the sign in process.
|
||||
* This could happen for example if the user denied access to the application or there was a configuration error.
|
||||
*
|
||||
* For a full list of possible reasons, check out the specification [Authorization Code Grant: Error Response](https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1)
|
||||
*/
|
||||
export class OAuthCallbackError extends AuthError {}
|
||||
|
||||
/** @todo */
|
||||
|
||||
@@ -110,7 +110,6 @@ export async function AuthInternal<
|
||||
if (
|
||||
[
|
||||
"Signin",
|
||||
"OAuthCallback",
|
||||
"OAuthCreateAccount",
|
||||
"EmailCreateAccount",
|
||||
"Callback",
|
||||
|
||||
@@ -89,11 +89,9 @@ export async function handleOAuth(
|
||||
|
||||
/** https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2.1 */
|
||||
if (o.isOAuth2Error(codeGrantParams)) {
|
||||
logger.debug("OAuthCallbackError", {
|
||||
providerId: provider.id,
|
||||
...codeGrantParams,
|
||||
})
|
||||
throw new OAuthCallbackError(codeGrantParams.error)
|
||||
const cause = { providerId: provider.id, ...codeGrantParams }
|
||||
logger.debug("OAuthCallbackError", cause)
|
||||
throw new OAuthCallbackError("OAuth Provider returned an error", cause)
|
||||
}
|
||||
|
||||
const codeVerifier = await checks.pkce.use(cookies, resCookies, options)
|
||||
|
||||
@@ -11,7 +11,7 @@ const signinErrors: Record<
|
||||
default: "Unable to sign in.",
|
||||
signin: "Try signing in with a different account.",
|
||||
oauthsignin: "Try signing in with a different account.",
|
||||
oauthcallback: "Try signing in with a different account.",
|
||||
oauthcallbackerror: "Try signing in with a different account.",
|
||||
oauthcreateaccount: "Try signing in with a different account.",
|
||||
emailcreateaccount: "Try signing in with a different account.",
|
||||
callback: "Try signing in with a different account.",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { OAuthProfileParseError } from "../errors.js"
|
||||
import { merge } from "./utils/merge.js"
|
||||
|
||||
import type {
|
||||
@@ -90,8 +91,10 @@ function normalizeOAuth(
|
||||
* @see https://openid.net/specs/openid-connect-core-1_0.html#UserInfo
|
||||
*/
|
||||
const defaultProfile: ProfileCallback<Profile> = (profile) => {
|
||||
const id = profile.sub ?? profile.id
|
||||
if (!id) throw new OAuthProfileParseError("Missing user id")
|
||||
return stripUndefined({
|
||||
id: profile.sub ?? profile.id,
|
||||
id: id.toString(),
|
||||
name: profile.name ?? profile.nickname ?? profile.preferred_username,
|
||||
email: profile.email,
|
||||
image: profile.picture,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { CallbackRouteError, Verification } from "../../errors.js"
|
||||
import {
|
||||
CallbackRouteError,
|
||||
OAuthCallbackError,
|
||||
Verification,
|
||||
} from "../../errors.js"
|
||||
import { handleLogin } from "../callback-handler.js"
|
||||
import { handleOAuth } from "../oauth/callback.js"
|
||||
import { handleState } from "../oauth/handle-state.js"
|
||||
@@ -368,6 +372,15 @@ export async function callback(params: {
|
||||
cookies,
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof OAuthCallbackError) {
|
||||
logger.error(e)
|
||||
// REVIEW: Should we expose original error= and error_description=
|
||||
// Should we use a different name for error= then, since we already use it for all kind of errors?
|
||||
url.searchParams.set("error", OAuthCallbackError.name)
|
||||
url.pathname += "/signin"
|
||||
return { redirect: url.toString(), cookies }
|
||||
}
|
||||
|
||||
const error = new CallbackRouteError(e as Error, { provider: provider.id })
|
||||
|
||||
logger.debug("callback route error details", { method, query, body })
|
||||
|
||||
@@ -41,7 +41,7 @@ export async function session(
|
||||
user: {
|
||||
name: decodedToken?.name,
|
||||
email: decodedToken?.email,
|
||||
image: decodedToken?.picture,
|
||||
picture: decodedToken?.picture,
|
||||
},
|
||||
expires: newExpires.toISOString(),
|
||||
}
|
||||
@@ -128,7 +128,7 @@ export async function session(
|
||||
user: {
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
image: user.image,
|
||||
picture: user.image,
|
||||
},
|
||||
expires: session.expires.toISOString(),
|
||||
},
|
||||
|
||||
@@ -65,6 +65,7 @@ export interface GitHubProfile {
|
||||
space: number
|
||||
private_repos: number
|
||||
}
|
||||
[claim: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -263,11 +263,9 @@ export type OIDCConfigInternal<Profile> = OAuthConfigInternal<Profile> & {
|
||||
export type OAuthUserConfig<Profile> = Omit<
|
||||
Partial<OAuthConfig<Profile>>,
|
||||
"options" | "type"
|
||||
> &
|
||||
Required<Pick<OAuthConfig<Profile>, "clientId" | "clientSecret">>
|
||||
>
|
||||
|
||||
export type OIDCUserConfig<Profile> = Omit<
|
||||
Partial<OIDCConfig<Profile>>,
|
||||
"options" | "type"
|
||||
> &
|
||||
Required<Pick<OIDCConfig<Profile>, "clientId" | "clientSecret">>
|
||||
>
|
||||
|
||||
@@ -99,6 +99,7 @@ export interface TwitterProfile {
|
||||
text: string
|
||||
}>
|
||||
}
|
||||
[claims: string]: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -141,32 +141,32 @@ export interface Account extends Partial<OpenIDTokenEndpointResponse> {
|
||||
* @see https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
|
||||
*/
|
||||
export interface Profile {
|
||||
sub: string
|
||||
name?: string
|
||||
given_name?: string
|
||||
family_name?: string
|
||||
middle_name?: string
|
||||
nickname?: string
|
||||
preferred_username?: string
|
||||
profile?: string
|
||||
picture?: string
|
||||
website?: string
|
||||
email?: string
|
||||
email_verified?: boolean
|
||||
gender?: string
|
||||
birthdate?: string
|
||||
zoneinfo?: string
|
||||
locale?: string
|
||||
phone_number?: string
|
||||
updated_at?: number
|
||||
sub?: string | null
|
||||
name?: string | null
|
||||
given_name?: string | null
|
||||
family_name?: string | null
|
||||
middle_name?: string | null
|
||||
nickname?: string | null
|
||||
preferred_username?: string | null
|
||||
profile?: string | null
|
||||
picture?: string | null | any
|
||||
website?: string | null
|
||||
email?: string | null
|
||||
email_verified?: boolean | null
|
||||
gender?: string | null
|
||||
birthdate?: string | null
|
||||
zoneinfo?: string | null
|
||||
locale?: string | null
|
||||
phone_number?: string | null
|
||||
updated_at?: Date | string | number | null
|
||||
address?: {
|
||||
formatted?: string
|
||||
street_address?: string
|
||||
locality?: string
|
||||
region?: string
|
||||
postal_code?: string
|
||||
country?: string
|
||||
}
|
||||
formatted?: string | null
|
||||
street_address?: string | null
|
||||
locality?: string | null
|
||||
region?: string | null
|
||||
postal_code?: string | null
|
||||
country?: string | null
|
||||
} | null
|
||||
[claim: string]: unknown
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ export interface CallbacksOptions<P = Profile, A = Account> {
|
||||
* This callback is called whenever a session is checked.
|
||||
* (Eg.: invoking the `/api/session` endpoint, using `useSession` or `getSession`)
|
||||
*
|
||||
* ⚠ By default, only a subset (email, name, image)
|
||||
* ⚠ By default, only a subset (email, name, picture)
|
||||
* of the token is returned for increased security.
|
||||
*
|
||||
* If you want to make something available you added to the token through the `jwt` callback,
|
||||
@@ -337,7 +337,7 @@ export type ErrorPageParam = "Configuration" | "AccessDenied" | "Verification"
|
||||
export type SignInPageErrorParam =
|
||||
| "Signin"
|
||||
| "OAuthSignin"
|
||||
| "OAuthCallback"
|
||||
| "OAuthCallbackError"
|
||||
| "OAuthCreateAccount"
|
||||
| "EmailCreateAccount"
|
||||
| "Callback"
|
||||
@@ -377,7 +377,7 @@ export interface DefaultSession {
|
||||
user?: {
|
||||
name?: string | null
|
||||
email?: string | null
|
||||
image?: string | null
|
||||
picture?: string | null
|
||||
}
|
||||
expires: ISODateString
|
||||
}
|
||||
|
||||
24
packages/frameworks-nextjs/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
<p align="center">
|
||||
<br/>
|
||||
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo/logo-sm.png" /></a>
|
||||
<h3 align="center">NextAuth.js</a></h3>
|
||||
<h4 align="center">Authentication for Next.js.</h4>
|
||||
<p align="center" style="align: center;">
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
|
||||
</a>
|
||||
<a href="https://npm.im/next-auth">
|
||||
<img alt="npm" src="https://img.shields.io/npm/v/next-auth?color=green&label=next-auth&style=flat-square">
|
||||
</a>
|
||||
<a href="https://www.npmtrends.com/next-auth">
|
||||
<img src="https://img.shields.io/npm/dm/next-auth?label=%20downloads&style=flat-square" alt="Downloads" />
|
||||
</a>
|
||||
<a href="https://github.com/nextauthjs/next-auth/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" />
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
Check out the documentation at [nextjs.authjs.dev](https://nextjs.authjs.dev).
|
||||
75
packages/frameworks-nextjs/package.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "@auth/nextjs",
|
||||
"version": "0.0.1",
|
||||
"description": "Authentication for Next.js",
|
||||
"homepage": "https://nextjs.authjs.dev",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
"author": "Balázs Orbán <info@balazsorban.com>",
|
||||
"keywords": [
|
||||
"react",
|
||||
"nodejs",
|
||||
"oauth",
|
||||
"jwt",
|
||||
"oauth2",
|
||||
"authentication",
|
||||
"nextjs",
|
||||
"csrf",
|
||||
"oidc",
|
||||
"nextauth"
|
||||
],
|
||||
"type": "module",
|
||||
"types": "./index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"import": "./index.js"
|
||||
},
|
||||
"./adapters": {
|
||||
"types": "./adapters.d.ts"
|
||||
},
|
||||
"./jwt": {
|
||||
"types": "./jwt.d.ts",
|
||||
"import": "./jwt.js"
|
||||
},
|
||||
"./middleware": {
|
||||
"types": "./middleware.d.ts",
|
||||
"import": "./middleware.js"
|
||||
},
|
||||
"./next": {
|
||||
"types": "./next.d.ts",
|
||||
"import": "./next.js"
|
||||
},
|
||||
"./providers": {
|
||||
"types": "./providers.d.ts"
|
||||
},
|
||||
"./react": {
|
||||
"types": "./react.d.ts",
|
||||
"import": "./react.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc -w",
|
||||
"clean": "rm -rf *.js *.d.ts lib",
|
||||
"build": "pnpm clean && tsc"
|
||||
},
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.d.ts",
|
||||
"lib",
|
||||
"src"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/react": "18.0.37",
|
||||
"typescript": "^4",
|
||||
"next": "13.4.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^13.4.0",
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
}
|
||||
47
packages/frameworks-nextjs/src/adapters.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* :::warning Deprecated
|
||||
* This module is being replaced by [`@auth/core/adapters`](https://authjs.dev/reference/core/adapters) and only kept for backwards compatibility.
|
||||
* :::
|
||||
*
|
||||
* @module adapters
|
||||
*/
|
||||
|
||||
// TODO: remove this file and replace references with `@auth/core/adapters`
|
||||
|
||||
import type {
|
||||
Adapter as CoreAdapter,
|
||||
AdapterAccount as CoreAdapterAccount,
|
||||
AdapterSession as CoreAdapterSession,
|
||||
AdapterUser as CoreAdapterUser,
|
||||
VerificationToken as CoreVerificationToken,
|
||||
} from "@auth/core/adapters"
|
||||
|
||||
/**
|
||||
* @deprecated use `@auth/core/adapters`
|
||||
* Read more at: https://nextjs.authjs.dev/v5
|
||||
*/
|
||||
export type Adapter = CoreAdapter
|
||||
|
||||
/**
|
||||
* @deprecated use `@auth/core/adapters`
|
||||
* Read more at: https://nextjs.authjs.dev/v5
|
||||
*/
|
||||
export type AdapterAccount = CoreAdapterAccount
|
||||
|
||||
/**
|
||||
* @deprecated use `@auth/core/adapters`
|
||||
* Read more at: https://nextjs.authjs.dev/v5
|
||||
*/
|
||||
export type AdapterSession = CoreAdapterSession
|
||||
|
||||
/**
|
||||
* @deprecated use `@auth/core/adapters`
|
||||
* Read more at: https://nextjs.authjs.dev/v5
|
||||
*/
|
||||
export type AdapterUser = CoreAdapterUser
|
||||
|
||||
/**
|
||||
* @deprecated use `@auth/core/adapters`
|
||||
* Read more at: https://nextjs.authjs.dev/v5
|
||||
*/
|
||||
export type VerificationToken = CoreVerificationToken
|
||||
176
packages/frameworks-nextjs/src/index.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
*
|
||||
* :::warning Note
|
||||
* This is the documentation for `next-auth@5`, which is currently **experimental**. For the documentation of the latest stable version, see [next-auth@4](https://next-auth.js.org).
|
||||
* :::
|
||||
*
|
||||
* If you are looking for the migration guide, visit the [`next-auth@5` Migration Guide](https://nextjs.authjs.dev/v5).
|
||||
*
|
||||
* ## Installation
|
||||
*
|
||||
* ```bash npm2yarn2pnpm
|
||||
* npm install next-auth@5 @auth/core
|
||||
* ```
|
||||
*
|
||||
* ## Signing in and signing out
|
||||
*
|
||||
* The App Router embraces Server Actions that can be leveraged to decrease the amount of JavaScript sent to the browser.
|
||||
*
|
||||
* :::info
|
||||
* [Next.js Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions) is **in alpha stage**. In the future, NextAuth.js will integrate with Server Actions and provide first-party APIs.
|
||||
* Until then, here is how you can use NextAuth.js to log in and log out without JavaScript.
|
||||
* :::
|
||||
*
|
||||
* ```ts title="app/auth-components.tsx"
|
||||
* import { auth } from "../auth"
|
||||
* import { cookies, headers } from "next/headers"
|
||||
*
|
||||
* function CSRF() {
|
||||
* const value = cookies().get("next-auth.csrf-token")?.value.split("|")[0]
|
||||
* return <input type="hidden" name="csrfToken" value={value} />
|
||||
* }
|
||||
*
|
||||
* export function SignIn({ provider, ...props }: any) {
|
||||
* return (
|
||||
* <form action={`/api/auth/signin/${provider}`} method="post">
|
||||
* <button {{...props}}/>
|
||||
* <CSRF/>
|
||||
* </form>
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* export function SignOut(props: any) {
|
||||
* return (
|
||||
* <form action="/api/auth/signout" method="post">
|
||||
* <button {...props}/>
|
||||
* <CSRF/>
|
||||
* </form>
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Alternatively, you can create client components, using the `signIn()` and `signOut` methods:
|
||||
*
|
||||
* ```ts title="app/auth-components.tsx"
|
||||
* "use client"
|
||||
* import { signIn, signOut } from "next-auth/react"
|
||||
*
|
||||
* export function SignIn({provider, ...props}: any) {
|
||||
* return <button {...props} onClick={() => signIn(provider)}/>
|
||||
* }
|
||||
*
|
||||
* export function SignOut(props: any) {
|
||||
* return <button {...props} onClick={() => signOut()}/>
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, you could for example use it like this:
|
||||
*
|
||||
* ```ts title=app/page.tsx
|
||||
* import { headers } from "next/headers"
|
||||
* import { SignIn, SignOut } from "./auth-components"
|
||||
*
|
||||
* export default async function Page() {
|
||||
* const session = await auth(headers())
|
||||
* if (session) {
|
||||
* return (
|
||||
* <>
|
||||
* <pre>{JSON.stringify(session, null, 2)}</pre>
|
||||
* <SignOut>Sign out</SignOut>
|
||||
* </>
|
||||
* )
|
||||
* }
|
||||
* return <SignIn id="github">Sign in with github</SignIn>
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @module index
|
||||
*/
|
||||
|
||||
import { Auth } from "@auth/core"
|
||||
import { setEnvDefaults } from "./lib/env.js"
|
||||
import { initAuth } from "./lib/index.js"
|
||||
|
||||
import type { NextRequest } from "next/server"
|
||||
import type { NextAuthConfig } from "./lib/index.js"
|
||||
import { getServerSession } from "./next"
|
||||
|
||||
type AppRouteHandlers = Record<
|
||||
"GET" | "POST",
|
||||
(req: NextRequest) => Promise<Response>
|
||||
>
|
||||
|
||||
export type { NextAuthConfig }
|
||||
|
||||
/**
|
||||
* The result of invoking {@link NextAuth}, initialized with the {@link NextAuthConfig}.
|
||||
* It contains methods to set up and interact with NextAuth.js in your Next.js app.
|
||||
*/
|
||||
export interface NextAuthResult {
|
||||
/**
|
||||
* The NextAuth.js [Route Handler](https://beta.nextjs.org/docs/routing/route-handlers) methods. After initializing NextAuth.js in `auth.ts`,
|
||||
* export these methods from `app/api/auth/[...nextauth]/route.ts`.
|
||||
*
|
||||
* :::note
|
||||
* This is a workaround until we have integrated with [Next.js Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions).
|
||||
* :::
|
||||
*
|
||||
* @example
|
||||
* ```ts title="app/api/auth/[...nextauth]/route.ts"
|
||||
* import { handlers } from "../../../../auth"
|
||||
* export const { GET, POST } = handlers
|
||||
* export const runtime = "edge"
|
||||
* ```
|
||||
*/
|
||||
handlers: AppRouteHandlers
|
||||
/**
|
||||
* A universal method to interact with NextAuth.js in your Next.js app.
|
||||
* After initializing NextAuth.js in `auth.ts`, use this method in Middleware, Route Handlers or React Server Components.
|
||||
*
|
||||
* @example
|
||||
* ```ts title="middleware.ts"
|
||||
* export { auth as middleware } from "./auth"
|
||||
* ```
|
||||
* @example
|
||||
* ```ts title="app/page.ts"
|
||||
* import { auth } from "../auth"
|
||||
* import { headers } from "next/headers"
|
||||
* export default async function Page() {
|
||||
* const { user } = await auth(headers())
|
||||
* return <div>Hello {user?.name}</div>
|
||||
* }
|
||||
* ```
|
||||
* @example
|
||||
* ```ts title="app/api/route.ts"
|
||||
* import { auth } from "../../auth"
|
||||
*
|
||||
* export const POST = auth((req) => {
|
||||
* // req.auth
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
auth: ReturnType<typeof initAuth>
|
||||
/** TODO: document */
|
||||
getServerSession: ReturnType<typeof getServerSession>
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize NextAuth.js.
|
||||
*
|
||||
* @example
|
||||
* ```ts title="auth.ts"
|
||||
* import NextAuth from "next-auth"
|
||||
* import GitHub from "@auth/core/providers/github"
|
||||
*
|
||||
* export const { handlers, auth } = NextAuth({ providers: [GitHub] })
|
||||
* ```
|
||||
*/
|
||||
export default function NextAuth(config: NextAuthConfig): NextAuthResult {
|
||||
setEnvDefaults(config)
|
||||
const httpHandler = (req: NextRequest) => Auth(req, config)
|
||||
return {
|
||||
handlers: { GET: httpHandler, POST: httpHandler } as const,
|
||||
auth: initAuth(config),
|
||||
getServerSession: getServerSession(config),
|
||||
}
|
||||
}
|
||||
@@ -33,10 +33,8 @@ export interface UseSessionOptions<R extends boolean> {
|
||||
onUnauthenticated?: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Util type that matches some strings literally, but allows any other string as well.
|
||||
* @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611
|
||||
*/
|
||||
// Util type that matches some strings literally, but allows any other string as well.
|
||||
// @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611
|
||||
export type LiteralUnion<T extends U, U = string> =
|
||||
| T
|
||||
| (U & Record<never, never>)
|
||||
@@ -67,7 +65,10 @@ export interface SignInResponse {
|
||||
url: string | null
|
||||
}
|
||||
|
||||
/** Match `inputType` of `new URLSearchParams(inputType)` */
|
||||
/**
|
||||
* Match `inputType` of `new URLSearchParams(inputType)`
|
||||
* @internal
|
||||
*/
|
||||
export type SignInAuthorizationParams =
|
||||
| string
|
||||
| string[][]
|
||||
@@ -86,7 +87,12 @@ export interface SignOutParams<R extends boolean = true> {
|
||||
redirect?: R
|
||||
}
|
||||
|
||||
/** [Documentation](https://next-auth.js.org/getting-started/client#options) */
|
||||
/**
|
||||
|
||||
* If you have session expiry times of 30 days (the default) or more, then you probably don't need to change any of the default options.
|
||||
*
|
||||
* However, if you need to customize the session behavior and/or are using short session expiry times, you can pass options to the provider to customize the behavior of the {@link useSession} hook.
|
||||
*/
|
||||
export interface SessionProviderProps {
|
||||
children: React.ReactNode
|
||||
session?: Session | null
|
||||
@@ -2,73 +2,73 @@ import type { AuthConfig } from "@auth/core"
|
||||
import type { OAuthProviderType } from "@auth/core/providers"
|
||||
|
||||
// TODO: Generate this from the available providers
|
||||
export const providersEnv: Record<OAuthProviderType, [string | undefined, string | undefined]> = {
|
||||
"42-school": [process.env.AUTH_42_SCHOOL_ID, process.env.AUTH_42_SCHOOL_SECRET],
|
||||
apple: [process.env.AUTH_APPLE_ID, process.env.AUTH_APPLE_SECRET],
|
||||
asgardeo: [process.env.AUTH_ASGARDEO_ID, process.env.AUTH_ASGARDEO_SECRET],
|
||||
atlassian: [process.env.AUTH_ATLASSIAN_ID, process.env.AUTH_ATLASSIAN_SECRET],
|
||||
auth0: [process.env.AUTH_AUTH0_ID, process.env.AUTH_AUTH0_SECRET],
|
||||
authentik: [process.env.AUTH_AUTHENTIK_ID, process.env.AUTH_AUTHENTIK_SECRET],
|
||||
"azure-ad": [process.env.AUTH_AAD_ID, process.env.AUTH_AAD_SECRET],
|
||||
"azure-ad-b2c": [process.env.AUTH_AAD_B2C_ID, process.env.AUTH_AAD_B2C_SECRET],
|
||||
battlenet: [process.env.AUTH_BATTLENET_ID, process.env.AUTH_BATTLENET_SECRET],
|
||||
beyondidentity: [process.env.AUTH_BEYOND_IDENTITY_ID, process.env.AUTH_BEYOND_IDENTITY_SECRET],
|
||||
box: [process.env.AUTH_BOX_ID, process.env.AUTH_BOX_SECRET],
|
||||
"boxyhq-saml": [process.env.AUTH_BOXYHQ_SAML_ID, process.env.AUTH_BOXYHQ_SAML_SECRET],
|
||||
bungie: [process.env.AUTH_BUNGIE_ID, process.env.AUTH_BUNGIE_SECRET],
|
||||
cognito: [process.env.AUTH_COGNITO_ID, process.env.AUTH_COGNITO_SECRET],
|
||||
coinbase: [process.env.AUTH_COINBASE_ID, process.env.AUTH_COINBASE_SECRET],
|
||||
discord: [process.env.AUTH_DISCORD_ID, process.env.AUTH_DISCORD_SECRET],
|
||||
dropbox: [process.env.AUTH_DROPBOX_ID, process.env.AUTH_DROPBOX_SECRET],
|
||||
"duende-identity-server6": [process.env.AUTH_IDS6_ID, process.env.AUTH_IDS6_SECRET],
|
||||
eveonline: [process.env.AUTH_EVEONLINE_ID, process.env.AUTH_EVEONLINE_SECRET],
|
||||
facebook: [process.env.AUTH_FACEBOOK_ID, process.env.AUTH_FACEBOOK_SECRET],
|
||||
faceit: [process.env.AUTH_FACEIT_ID, process.env.AUTH_FACEIT_SECRET],
|
||||
foursquare: [process.env.AUTH_FOURSQUARE_ID, process.env.AUTH_FOURSQUARE_SECRET],
|
||||
freshbooks: [process.env.AUTH_FRESHBOOKS_ID, process.env.AUTH_FRESHBOOKS_SECRET],
|
||||
fusionauth: [process.env.AUTH_FUSIONAUTH_ID, process.env.AUTH_FUSIONAUTH_SECRET],
|
||||
github: [process.env.AUTH_GITHUB_ID, process.env.AUTH_GITHUB_SECRET],
|
||||
gitlab: [process.env.AUTH_GITLAB_ID, process.env.AUTH_GITLAB_SECRET],
|
||||
google: [process.env.AUTH_GOOGLE_ID, process.env.AUTH_GOOGLE_SECRET],
|
||||
hubspot: [process.env.AUTH_HUBSPOT_ID, process.env.AUTH_HUBSPOT_SECRET],
|
||||
"identity-server4": [process.env.AUTH_IDS4_ID, process.env.AUTH_IDS4_SECRET],
|
||||
instagram: [process.env.AUTH_INSTAGRAM_ID, process.env.AUTH_INSTAGRAM_SECRET],
|
||||
kakao: [process.env.AUTH_KAKAO_ID, process.env.AUTH_KAKAO_SECRET],
|
||||
keycloak: [process.env.AUTH_KEYCLOAK_ID, process.env.AUTH_KEYCLOAK_SECRET],
|
||||
line: [process.env.AUTH_LINE_ID, process.env.AUTH_LINE_SECRET],
|
||||
linkedin: [process.env.AUTH_LINKEDIN_ID, process.env.AUTH_LINKEDIN_SECRET],
|
||||
mailchimp: [process.env.AUTH_MAILCHIMP_ID, process.env.AUTH_MAILCHIMP_SECRET],
|
||||
mailru: [process.env.AUTH_MAILRU_ID, process.env.AUTH_MAILRU_SECRET],
|
||||
mattermost: [process.env.AUTH_MATTERMOST_ID, process.env.AUTH_MATTERMOST_SECRET],
|
||||
medium: [process.env.AUTH_MEDIUM_ID, process.env.AUTH_MEDIUM_SECRET],
|
||||
naver: [process.env.AUTH_NAVER_ID, process.env.AUTH_NAVER_SECRET],
|
||||
netlify: [process.env.AUTH_NETLIFY_ID, process.env.AUTH_NETLIFY_SECRET],
|
||||
notion: [process.env.AUTH_NOTION_ID, process.env.AUTH_NOTION_SECRET],
|
||||
okta: [process.env.AUTH_OKTA_ID, process.env.AUTH_OKTA_SECRET],
|
||||
onelogin: [process.env.AUTH_ONELOGIN_ID, process.env.AUTH_ONELOGIN_SECRET],
|
||||
osso: [process.env.AUTH_OSSO_ID, process.env.AUTH_OSSO_SECRET],
|
||||
osu: [process.env.AUTH_OSU_ID, process.env.AUTH_OSU_SECRET],
|
||||
patreon: [process.env.AUTH_PATREON_ID, process.env.AUTH_PATREON_SECRET],
|
||||
pinterest: [process.env.AUTH_PINTEREST_ID, process.env.AUTH_PINTEREST_SECRET],
|
||||
pipedrive: [process.env.AUTH_PIPEDRIVE_ID, process.env.AUTH_PIPEDRIVE_SECRET],
|
||||
reddit: [process.env.AUTH_REDDIT_ID, process.env.AUTH_REDDIT_SECRET],
|
||||
salesforce: [process.env.AUTH_SALESFORCE_ID, process.env.AUTH_SALESFORCE_SECRET],
|
||||
slack: [process.env.AUTH_SLACK_ID, process.env.AUTH_SLACK_SECRET],
|
||||
spotify: [process.env.AUTH_SPOTIFY_ID, process.env.AUTH_SPOTIFY_SECRET],
|
||||
strava: [process.env.AUTH_STRAVA_ID, process.env.AUTH_STRAVA_SECRET],
|
||||
todoist: [process.env.AUTH_TODOIST_ID, process.env.AUTH_TODOIST_SECRET],
|
||||
trakt: [process.env.AUTH_TRAKT_ID, process.env.AUTH_TRAKT_SECRET],
|
||||
twitch: [process.env.AUTH_TWITCH_ID, process.env.AUTH_TWITCH_SECRET],
|
||||
twitter: [process.env.AUTH_TWITTER_ID, process.env.AUTH_TWITTER_SECRET],
|
||||
"united-effects": [process.env.AUTH_UNITED_EFFECTS_ID, process.env.AUTH_UNITED_EFFECTS_SECRET],
|
||||
vk: [process.env.AUTH_VK_ID, process.env.AUTH_VK_SECRET],
|
||||
wikimedia: [process.env.AUTH_WIKIMEDIA_ID, process.env.AUTH_WIKIMEDIA_SECRET],
|
||||
wordpress: [process.env.AUTH_WORDPRESS_ID, process.env.AUTH_WORDPRESS_SECRET],
|
||||
workos: [process.env.AUTH_WORKOS_ID, process.env.AUTH_WORKOS_SECRET],
|
||||
yandex: [process.env.AUTH_YANDEX_ID, process.env.AUTH_YANDEX_SECRET],
|
||||
zitadel: [process.env.AUTH_ZITADEL_ID, process.env.AUTH_ZITADEL_SECRET],
|
||||
zoho: [process.env.AUTH_ZOHO_ID, process.env.AUTH_ZOHO_SECRET],
|
||||
zoom: [process.env.AUTH_ZOOM_ID, process.env.AUTH_ZOOM_SECRET],
|
||||
export const providersEnv: Record<OAuthProviderType, Array<string | undefined>> = {
|
||||
"42-school": [process.env.AUTH_42_SCHOOL_ID, process.env.AUTH_42_SCHOOL_SECRET, process.env.AUTH_42_SCHOOL_ISSUER],
|
||||
apple: [process.env.AUTH_APPLE_ID, process.env.AUTH_APPLE_SECRET, process.env.AUTH_APPLE_ISSUER],
|
||||
asgardeo: [process.env.AUTH_ASGARDEO_ID, process.env.AUTH_ASGARDEO_SECRET, process.env.AUTH_ASGARDEO_ISSUER],
|
||||
atlassian: [process.env.AUTH_ATLASSIAN_ID, process.env.AUTH_ATLASSIAN_SECRET, process.env.AUTH_ATLASSIAN_ISSUER],
|
||||
auth0: [process.env.AUTH_AUTH0_ID, process.env.AUTH_AUTH0_SECRET, process.env.AUTH_AUTH0_ISSUER],
|
||||
authentik: [process.env.AUTH_AUTHENTIK_ID, process.env.AUTH_AUTHENTIK_SECRET, process.env.AUTH_AUTHENTIK_ISSUER],
|
||||
"azure-ad": [process.env.AUTH_AAD_ID, process.env.AUTH_AAD_SECRET, process.env.AUTH_AAD_ISSUER],
|
||||
"azure-ad-b2c": [process.env.AUTH_AAD_B2C_ID, process.env.AUTH_AAD_B2C_SECRET, process.env.AUTH_AAD_B2C_ISSUER],
|
||||
battlenet: [process.env.AUTH_BATTLENET_ID, process.env.AUTH_BATTLENET_SECRET, process.env.AUTH_BATTLENET_ISSUER],
|
||||
beyondidentity: [process.env.AUTH_BEYOND_IDENTITY_ID, process.env.AUTH_BEYOND_IDENTITY_SECRET, process.env.AUTH_BEYOND_IDENTITY_ISSUER],
|
||||
box: [process.env.AUTH_BOX_ID, process.env.AUTH_BOX_SECRET, process.env.AUTH_BOX_ISSUER],
|
||||
"boxyhq-saml": [process.env.AUTH_BOXYHQ_SAML_ID, process.env.AUTH_BOXYHQ_SAML_SECRET, process.env.AUTH_BOXYHQ_SAML_ISSUER],
|
||||
bungie: [process.env.AUTH_BUNGIE_ID, process.env.AUTH_BUNGIE_SECRET, process.env.AUTH_BUNGIE_ISSUER],
|
||||
cognito: [process.env.AUTH_COGNITO_ID, process.env.AUTH_COGNITO_SECRET, process.env.AUTH_COGNITO_ISSUER],
|
||||
coinbase: [process.env.AUTH_COINBASE_ID, process.env.AUTH_COINBASE_SECRET, process.env.AUTH_COINBASE_ISSUER],
|
||||
discord: [process.env.AUTH_DISCORD_ID, process.env.AUTH_DISCORD_SECRET, process.env.AUTH_DISCORD_ISSUER],
|
||||
dropbox: [process.env.AUTH_DROPBOX_ID, process.env.AUTH_DROPBOX_SECRET, process.env.AUTH_DROPBOX_ISSUER],
|
||||
"duende-identity-server6": [process.env.AUTH_IDS6_ID, process.env.AUTH_IDS6_SECRET, process.env.AUTH_IDS6_ISSUER],
|
||||
eveonline: [process.env.AUTH_EVEONLINE_ID, process.env.AUTH_EVEONLINE_SECRET, process.env.AUTH_EVEONLINE_ISSUER],
|
||||
facebook: [process.env.AUTH_FACEBOOK_ID, process.env.AUTH_FACEBOOK_SECRET, process.env.AUTH_FACEBOOK_ISSUER],
|
||||
faceit: [process.env.AUTH_FACEIT_ID, process.env.AUTH_FACEIT_SECRET, process.env.AUTH_FACEIT_ISSUER],
|
||||
foursquare: [process.env.AUTH_FOURSQUARE_ID, process.env.AUTH_FOURSQUARE_SECRET, process.env.AUTH_FOURSQUARE_ISSUER],
|
||||
freshbooks: [process.env.AUTH_FRESHBOOKS_ID, process.env.AUTH_FRESHBOOKS_SECRET, process.env.AUTH_FRESHBOOKS_ISSUER],
|
||||
fusionauth: [process.env.AUTH_FUSIONAUTH_ID, process.env.AUTH_FUSIONAUTH_SECRET, process.env.AUTH_FUSIONAUTH_ISSUER],
|
||||
github: [process.env.AUTH_GITHUB_ID, process.env.AUTH_GITHUB_SECRET, process.env.AUTH_GITHUB_ISSUER],
|
||||
gitlab: [process.env.AUTH_GITLAB_ID, process.env.AUTH_GITLAB_SECRET, process.env.AUTH_GITLAB_ISSUER],
|
||||
google: [process.env.AUTH_GOOGLE_ID, process.env.AUTH_GOOGLE_SECRET, process.env.AUTH_GOOGLE_ISSUER],
|
||||
hubspot: [process.env.AUTH_HUBSPOT_ID, process.env.AUTH_HUBSPOT_SECRET, process.env.AUTH_HUBSPOT_ISSUER],
|
||||
"identity-server4": [process.env.AUTH_IDS4_ID, process.env.AUTH_IDS4_SECRET, process.env.AUTH_IDS4_ISSUER],
|
||||
instagram: [process.env.AUTH_INSTAGRAM_ID, process.env.AUTH_INSTAGRAM_SECRET, process.env.AUTH_INSTAGRAM_ISSUER],
|
||||
kakao: [process.env.AUTH_KAKAO_ID, process.env.AUTH_KAKAO_SECRET, process.env.AUTH_KAKAO_ISSUER],
|
||||
keycloak: [process.env.AUTH_KEYCLOAK_ID, process.env.AUTH_KEYCLOAK_SECRET, process.env.AUTH_KEYCLOAK_ISSUER],
|
||||
line: [process.env.AUTH_LINE_ID, process.env.AUTH_LINE_SECRET, process.env.AUTH_LINE_ISSUER],
|
||||
linkedin: [process.env.AUTH_LINKEDIN_ID, process.env.AUTH_LINKEDIN_SECRET, process.env.AUTH_LINKEDIN_ISSUER],
|
||||
mailchimp: [process.env.AUTH_MAILCHIMP_ID, process.env.AUTH_MAILCHIMP_SECRET, process.env.AUTH_MAILCHIMP_ISSUER],
|
||||
mailru: [process.env.AUTH_MAILRU_ID, process.env.AUTH_MAILRU_SECRET, process.env.AUTH_MAILRU_ISSUER],
|
||||
mattermost: [process.env.AUTH_MATTERMOST_ID, process.env.AUTH_MATTERMOST_SECRET, process.env.AUTH_MATTERMOST_ISSUER],
|
||||
medium: [process.env.AUTH_MEDIUM_ID, process.env.AUTH_MEDIUM_SECRET, process.env.AUTH_MEDIUM_ISSUER],
|
||||
naver: [process.env.AUTH_NAVER_ID, process.env.AUTH_NAVER_SECRET, process.env.AUTH_NAVER_ISSUER],
|
||||
netlify: [process.env.AUTH_NETLIFY_ID, process.env.AUTH_NETLIFY_SECRET, process.env.AUTH_NETLIFY_ISSUER],
|
||||
notion: [process.env.AUTH_NOTION_ID, process.env.AUTH_NOTION_SECRET, process.env.AUTH_NOTION_ISSUER],
|
||||
okta: [process.env.AUTH_OKTA_ID, process.env.AUTH_OKTA_SECRET, process.env.AUTH_OKTA_ISSUER],
|
||||
onelogin: [process.env.AUTH_ONELOGIN_ID, process.env.AUTH_ONELOGIN_SECRET, process.env.AUTH_ONELOGIN_ISSUER],
|
||||
osso: [process.env.AUTH_OSSO_ID, process.env.AUTH_OSSO_SECRET, process.env.AUTH_OSSO_ISSUER],
|
||||
osu: [process.env.AUTH_OSU_ID, process.env.AUTH_OSU_SECRET, process.env.AUTH_OSU_ISSUER],
|
||||
patreon: [process.env.AUTH_PATREON_ID, process.env.AUTH_PATREON_SECRET, process.env.AUTH_PATREON_ISSUER],
|
||||
pinterest: [process.env.AUTH_PINTEREST_ID, process.env.AUTH_PINTEREST_SECRET, process.env.AUTH_PINTEREST_ISSUER],
|
||||
pipedrive: [process.env.AUTH_PIPEDRIVE_ID, process.env.AUTH_PIPEDRIVE_SECRET, process.env.AUTH_PIPEDRIVE_ISSUER],
|
||||
reddit: [process.env.AUTH_REDDIT_ID, process.env.AUTH_REDDIT_SECRET, process.env.AUTH_REDDIT_ISSUER],
|
||||
salesforce: [process.env.AUTH_SALESFORCE_ID, process.env.AUTH_SALESFORCE_SECRET, process.env.AUTH_SALESFORCE_ISSUER],
|
||||
slack: [process.env.AUTH_SLACK_ID, process.env.AUTH_SLACK_SECRET, process.env.AUTH_SLACK_ISSUER],
|
||||
spotify: [process.env.AUTH_SPOTIFY_ID, process.env.AUTH_SPOTIFY_SECRET, process.env.AUTH_SPOTIFY_ISSUER],
|
||||
strava: [process.env.AUTH_STRAVA_ID, process.env.AUTH_STRAVA_SECRET, process.env.AUTH_STRAVA_ISSUER],
|
||||
todoist: [process.env.AUTH_TODOIST_ID, process.env.AUTH_TODOIST_SECRET, process.env.AUTH_TODOIST_ISSUER],
|
||||
trakt: [process.env.AUTH_TRAKT_ID, process.env.AUTH_TRAKT_SECRET, process.env.AUTH_TRAKT_ISSUER],
|
||||
twitch: [process.env.AUTH_TWITCH_ID, process.env.AUTH_TWITCH_SECRET, process.env.AUTH_TWITCH_ISSUER],
|
||||
twitter: [process.env.AUTH_TWITTER_ID, process.env.AUTH_TWITTER_SECRET, process.env.AUTH_TWITTER_ISSUER],
|
||||
"united-effects": [process.env.AUTH_UNITED_EFFECTS_ID, process.env.AUTH_UNITED_EFFECTS_SECRET, process.env.AUTH_UNITED_EFFECTS_ISSUER],
|
||||
vk: [process.env.AUTH_VK_ID, process.env.AUTH_VK_SECRET, process.env.AUTH_VK_ISSUER],
|
||||
wikimedia: [process.env.AUTH_WIKIMEDIA_ID, process.env.AUTH_WIKIMEDIA_SECRET, process.env.AUTH_WIKIMEDIA_ISSUER],
|
||||
wordpress: [process.env.AUTH_WORDPRESS_ID, process.env.AUTH_WORDPRESS_SECRET, process.env.AUTH_WORDPRESS_ISSUER],
|
||||
workos: [process.env.AUTH_WORKOS_ID, process.env.AUTH_WORKOS_SECRET, process.env.AUTH_WORKOS_ISSUER],
|
||||
yandex: [process.env.AUTH_YANDEX_ID, process.env.AUTH_YANDEX_SECRET, process.env.AUTH_YANDEX_ISSUER],
|
||||
zitadel: [process.env.AUTH_ZITADEL_ID, process.env.AUTH_ZITADEL_SECRET, process.env.AUTH_ZITADEL_ISSUER],
|
||||
zoho: [process.env.AUTH_ZOHO_ID, process.env.AUTH_ZOHO_SECRET, process.env.AUTH_ZOHO_ISSUER],
|
||||
zoom: [process.env.AUTH_ZOOM_ID, process.env.AUTH_ZOOM_SECRET, process.env.AUTH_ZOOM_ISSUER],
|
||||
}
|
||||
|
||||
export function setEnvDefaults(config: AuthConfig) {
|
||||
@@ -79,9 +79,10 @@ export function setEnvDefaults(config: AuthConfig) {
|
||||
if (typeof p !== "function") return p
|
||||
const provider = p()
|
||||
if (provider.type === "oauth" || provider.type === "oidc") {
|
||||
const [clientId, clientSecret] = providersEnv[provider.id] ?? []
|
||||
const [clientId, clientSecret, issuer] = providersEnv[provider.id] ?? []
|
||||
provider.clientId ??= clientId
|
||||
provider.clientSecret ??= clientSecret
|
||||
provider.issuer ??= issuer
|
||||
}
|
||||
return provider
|
||||
})
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Auth, type AuthConfig } from "@auth/core"
|
||||
import { NextResponse } from "next/server"
|
||||
import type { headers as nextHeaders } from "next/headers"
|
||||
|
||||
import type { JWT } from "@auth/core/jwt"
|
||||
import type { Awaitable, CallbacksOptions, User } from "@auth/core/types"
|
||||
import type { Awaitable, CallbacksOptions, Session } from "@auth/core/types"
|
||||
import type { NextFetchEvent, NextMiddleware, NextRequest } from "next/server"
|
||||
import type { AppRouteHandlerFn } from "next/dist/server/future/route-modules/app-route/module"
|
||||
|
||||
export interface NextAuthCallbacks extends Partial<CallbacksOptions> {
|
||||
/**
|
||||
@@ -51,25 +50,24 @@ export interface NextAuthConfig extends AuthConfig {
|
||||
callbacks?: NextAuthCallbacks
|
||||
}
|
||||
|
||||
async function getAuth(
|
||||
headers: Headers | ReturnType<typeof nextHeaders>,
|
||||
config: NextAuthConfig
|
||||
): Promise<AuthData & { expires: string }> {
|
||||
async function runAuth(headers: Headers, config: NextAuthConfig) {
|
||||
const host = headers.get("x-forwarded-host") ?? headers.get("host")
|
||||
const protocol =
|
||||
headers.get("x-forwarded-proto") === "http" ? "http" : "https"
|
||||
// TODO: Handle URL correctly (NEXTAUTH_URL, request host, protocol, custom path, etc.)
|
||||
const req = new Request("http://n/api/auth/session", {
|
||||
const origin = `${protocol}://${host}`
|
||||
const req = new Request(`${origin}/api/auth/session`, {
|
||||
headers: { cookie: headers.get("cookie") ?? "" },
|
||||
})
|
||||
config.trustHost = true
|
||||
config.useSecureCookies ??= headers.get("x-forwarded-proto") === "https"
|
||||
if (config.callbacks) {
|
||||
config.callbacks.session ??= ({ session, user, token }) => ({
|
||||
expires: session.expires,
|
||||
user,
|
||||
token,
|
||||
})
|
||||
}
|
||||
const response = await Auth(req, config)
|
||||
return response.json()
|
||||
config.useSecureCookies ??= protocol === "https"
|
||||
|
||||
// Since we are server-side, we don't need to filter out the session data
|
||||
config.callbacks = Object.assign(config.callbacks as any, {
|
||||
session({ session, user, token }) {
|
||||
return { expires: session.expires, user: user ?? token }
|
||||
},
|
||||
})
|
||||
return Auth(req, config)
|
||||
}
|
||||
|
||||
export interface NextAuthRequest extends NextRequest {
|
||||
@@ -85,70 +83,72 @@ export type WithAuthArgs =
|
||||
| [NextAuthRequest, NextFetchEvent]
|
||||
| [NextAuthMiddleware]
|
||||
| [Headers]
|
||||
| [ReturnType<typeof nextHeaders>]
|
||||
| []
|
||||
|
||||
export function initAuth(config: NextAuthConfig) {
|
||||
return (...args: WithAuthArgs) => {
|
||||
// TODO: use `next/headers` when it's available in Middleware too
|
||||
// if (!args.length) return getAuth($headers(), config)
|
||||
if (!args.length) return getAuth(new Headers(), config)
|
||||
if (args[0] instanceof Headers) return getAuth(args[0], config)
|
||||
if (!args.length)
|
||||
return runAuth(new Headers(), config).then((r) => r.json())
|
||||
if (args[0] instanceof Headers) {
|
||||
return runAuth(args[0], config).then((r) => r.json())
|
||||
}
|
||||
if (args[0] instanceof Request) {
|
||||
// middleare.ts
|
||||
// export { auth as default } from "auth"
|
||||
const req = args[0]
|
||||
const ev = args[1]
|
||||
return handleAuth([req, ev as any], config)
|
||||
}
|
||||
|
||||
// middleare.ts/router.ts
|
||||
// import { auth } from "auth"
|
||||
// export default auth((req) => { console.log(req.auth) }})
|
||||
const userMiddleware = args[0]
|
||||
return async (...args: Parameters<NextAuthMiddleware>) => {
|
||||
// @ts-expect-error instanceof Headers higher up should not let this be a problem
|
||||
return handleAuth(args, config, userMiddleware)
|
||||
const userMiddlewareOrRoute = args[0]
|
||||
return async (
|
||||
...args: Parameters<NextAuthMiddleware | AppRouteHandlerFn>
|
||||
) => {
|
||||
return handleAuth(args, config, userMiddlewareOrRoute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** TODO: structure token similar to User */
|
||||
/** TODO: document */
|
||||
export interface AuthData {
|
||||
token: JWT | null
|
||||
user: User | null
|
||||
user: Session | null
|
||||
}
|
||||
|
||||
async function handleAuth(
|
||||
args: Parameters<NextMiddleware>,
|
||||
args: Parameters<NextMiddleware | AppRouteHandlerFn>,
|
||||
config: NextAuthConfig,
|
||||
userMiddleware?: NextAuthMiddleware
|
||||
userMiddlewareOrRoute?: NextAuthMiddleware | AppRouteHandlerFn
|
||||
) {
|
||||
const request = args[0]
|
||||
// TODO: pass `next/headers` when it's available
|
||||
const {
|
||||
token = null,
|
||||
user = null,
|
||||
expires = null,
|
||||
} = (await getAuth(request.headers, config)) ?? {}
|
||||
const authResponse = await runAuth(request.headers, config)
|
||||
const { user = null, expires = null } = (await authResponse.json()) ?? {}
|
||||
|
||||
const authorized = config.callbacks?.authorized
|
||||
? await config.callbacks.authorized({
|
||||
request,
|
||||
auth: { token, user },
|
||||
expires,
|
||||
})
|
||||
: true
|
||||
const authorized =
|
||||
(await config.callbacks?.authorized?.({
|
||||
request,
|
||||
auth: { user },
|
||||
expires,
|
||||
})) ?? true
|
||||
|
||||
let response: Response = NextResponse.next()
|
||||
|
||||
if (authorized instanceof Response) {
|
||||
// User returned a custom response, like redirecting to a page or 401, respect it
|
||||
response = authorized
|
||||
} else if (userMiddleware) {
|
||||
// Execute user's middleware with the augmented request
|
||||
} else if (userMiddlewareOrRoute) {
|
||||
// Execute user's middleware/handler with the augmented request
|
||||
const augmentedReq: NextAuthRequest = request as any
|
||||
augmentedReq.auth = { token, user }
|
||||
augmentedReq.auth = { user }
|
||||
response =
|
||||
(await userMiddleware(augmentedReq, args[1])) ?? NextResponse.next()
|
||||
// @ts-expect-error
|
||||
(await userMiddlewareOrRoute(augmentedReq, args[1])) ??
|
||||
NextResponse.next()
|
||||
} else if (!authorized) {
|
||||
// Redirect to signin page by default if not authorized
|
||||
// TODO: Support custom signin page
|
||||
@@ -156,14 +156,14 @@ async function handleAuth(
|
||||
response = NextResponse.redirect(request.nextUrl)
|
||||
}
|
||||
|
||||
// We will update the session cookie if it exists,
|
||||
// so that the session expiry is extended
|
||||
// Preserve cookies set by Auth.js Core
|
||||
const finalResponse = new NextResponse(response?.body, response)
|
||||
// TODO: respect config/prefix/chunking etc.
|
||||
const cookiePrefix = request.nextUrl.protocol === "https:" ? "__Secure-" : ""
|
||||
const name = `${cookiePrefix}next-auth.session-token`
|
||||
const val = request.cookies.get(name)?.value
|
||||
// TODO: respect config/prefix/chunking etc.
|
||||
if (val) finalResponse.cookies.set(name, val, { expires: new Date(expires!) })
|
||||
if (authResponse.headers.has("set-cookie")) {
|
||||
finalResponse.headers.set(
|
||||
"set-cookie",
|
||||
authResponse.headers.get("set-cookie")!
|
||||
)
|
||||
}
|
||||
|
||||
return finalResponse
|
||||
}
|
||||
16
packages/frameworks-nextjs/src/middleware.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* :::warning Deprecated
|
||||
* This module is replaced in v5. Read more at: https://nextjs.authjs.dev/v5
|
||||
* :::
|
||||
*
|
||||
* @module middleware
|
||||
*/
|
||||
|
||||
throw new ReferenceError(
|
||||
[
|
||||
'"next-auth/middleware" is deprecated. If you are not ready to migrate, keep using "next-auth@4".',
|
||||
"Read more on https://nextjs.authjs.dev/v5",
|
||||
].join("\n")
|
||||
)
|
||||
|
||||
export {}
|
||||
59
packages/frameworks-nextjs/src/next.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Auth } from "@auth/core"
|
||||
import type { CallbacksOptions, Session } from "@auth/core/types"
|
||||
import type {
|
||||
GetServerSidePropsContext,
|
||||
NextApiRequest,
|
||||
NextApiResponse,
|
||||
} from "next"
|
||||
import { NextAuthConfig } from "./lib"
|
||||
|
||||
type GetServerSessionOptions = Partial<Omit<NextAuthConfig, "callbacks">> & {
|
||||
callbacks?: Omit<NextAuthConfig["callbacks"], "session"> & {
|
||||
session?: (...args: Parameters<CallbacksOptions["session"]>) => any
|
||||
}
|
||||
}
|
||||
|
||||
type GetServerSessionParams =
|
||||
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]]
|
||||
| [NextApiRequest, NextApiResponse]
|
||||
| []
|
||||
|
||||
export function getServerSession(config: NextAuthConfig) {
|
||||
return async <
|
||||
O extends GetServerSessionOptions,
|
||||
R = O["callbacks"] extends { session: (...args: any[]) => infer U }
|
||||
? U
|
||||
: Session
|
||||
>(
|
||||
...args: GetServerSessionParams
|
||||
): Promise<R | null> => {
|
||||
let req, res
|
||||
|
||||
req = args[0]
|
||||
res = args[1]
|
||||
|
||||
const host = req.headers["x-forwarded-host"] ?? req.headers["host"]
|
||||
const protocol =
|
||||
req.headers["x-forwarded-proto"] === "http" ? "http" : "https"
|
||||
const origin = `${protocol}://${host}`
|
||||
const request = new Request(`${origin}/api/auth/session`, {
|
||||
headers: req.headers,
|
||||
})
|
||||
const authResponse = await Auth(request, config)
|
||||
|
||||
const { status = 200 } = authResponse
|
||||
const body = await authResponse.json()
|
||||
|
||||
authResponse.headers?.forEach((v, k) => {
|
||||
if (k === "content-type") return
|
||||
res.setHeader(k, v)
|
||||
})
|
||||
|
||||
if (body && typeof body !== "string" && Object.keys(body).length) {
|
||||
if (status === 200) return body as R
|
||||
throw new Error((body as any).message)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ export type {
|
||||
SignOutParams,
|
||||
}
|
||||
|
||||
export { SessionProviderProps }
|
||||
// This behaviour mirrors the default behaviour for getting the site name that
|
||||
// happens server side in server/index.js
|
||||
// 1. An empty value is legitimate when the code is being invoked client side as
|
||||
@@ -81,8 +82,12 @@ const logger: LoggerInstance = {
|
||||
warn: console.warn,
|
||||
}
|
||||
|
||||
type UpdateSession = (data?: any) => Promise<Session | null>
|
||||
/** @todo Document */
|
||||
export type UpdateSession = (data?: any) => Promise<Session | null>
|
||||
|
||||
/**
|
||||
* useSession() returns an object containing three things: a method called {@link UpdateSession|update}, `data` and `status`.
|
||||
*/
|
||||
export type SessionContextValue<R extends boolean = false> = R extends true
|
||||
?
|
||||
| { update: UpdateSession; data: Session; status: "authenticated" }
|
||||
@@ -100,8 +105,11 @@ export const SessionContext = React.createContext?.<
|
||||
>(undefined)
|
||||
|
||||
/**
|
||||
* React Hook that gives you access
|
||||
* to the logged in user's session data.
|
||||
* React Hook that gives you access to the logged in user's session data and lets you modify it.
|
||||
*
|
||||
* :::info
|
||||
* You will likely not need `useSession` if you are using the [Next.js App Router (`app/`)](https://nextjs.org/blog/next-13-4#nextjs-app-router).
|
||||
* :::
|
||||
*/
|
||||
export function useSession<R extends boolean>(
|
||||
options?: UseSessionOptions<R>
|
||||
@@ -317,9 +325,14 @@ export async function signOut<R extends boolean = true>(
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider to wrap the app in to make session data available globally.
|
||||
* Can also be used to throttle the number of requests to the endpoint
|
||||
* `/api/auth/session`.
|
||||
* [React Context](https://react.dev/learn/passing-data-deeply-with-context) provider to wrap the app (`pages/`) to make session data available anywhere.
|
||||
*
|
||||
* When used, the session state is automatically synchronized across all open tabs/windows and they are all updated whenever they gain or lose focus
|
||||
* or the state changes (e.g. a user signs in or out) when {@link SessionProviderProps.refetchOnWindowFocus} is `true`.
|
||||
*
|
||||
* :::info
|
||||
* You will likely not need `SessionProvider` if you are using the [Next.js App Router (`app/`)](https://nextjs.org/blog/next-13-4#nextjs-app-router).
|
||||
* :::
|
||||
*/
|
||||
export function SessionProvider(props: SessionProviderProps) {
|
||||
if (!SessionContext) {
|
||||
29
packages/frameworks-nextjs/tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"esnext"
|
||||
],
|
||||
"jsx": "react-jsx",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"outDir": ".",
|
||||
"rootDir": "src",
|
||||
"skipDefaultLibCheck": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"stripInternal": true,
|
||||
"declarationMap": true,
|
||||
"declaration": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"*.js",
|
||||
"*.d.ts",
|
||||
]
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export async function signIn<
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"X-Auth-Return-Redirect": "1",
|
||||
},
|
||||
// @ts-expect-error -- ignore
|
||||
// @ts-ignore
|
||||
body: new URLSearchParams({
|
||||
...options,
|
||||
csrfToken,
|
||||
|
||||
@@ -52,7 +52,7 @@ export async function signIn<
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"X-Auth-Return-Redirect": "1",
|
||||
},
|
||||
// @ts-expect-error -- ignore
|
||||
// @ts-ignore
|
||||
body: new URLSearchParams({
|
||||
...options,
|
||||
csrfToken,
|
||||
|
||||
1
packages/next-auth/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||
254
packages/next-auth/README.md
Normal file
@@ -0,0 +1,254 @@
|
||||
<p align="center">
|
||||
<br/>
|
||||
<a href="https://next-auth.js.org" target="_blank"><img width="150px" src="https://next-auth.js.org/img/logo/logo-sm.png" /></a>
|
||||
<h3 align="center">NextAuth.js</h3>
|
||||
<p align="center">Authentication for Next.js</p>
|
||||
<p align="center">
|
||||
Open Source. Full Stack. Own Your Data.
|
||||
</p>
|
||||
<p align="center" style="align: center;">
|
||||
<a href="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml?query=workflow%3ARelease">
|
||||
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg" alt="Release" />
|
||||
</a>
|
||||
<a href="https://packagephobia.com/result?p=next-auth">
|
||||
<img src="https://packagephobia.com/badge?p=next-auth" alt="Bundle Size"/>
|
||||
</a>
|
||||
<a href="https://www.npmtrends.com/next-auth">
|
||||
<img src="https://img.shields.io/npm/dm/next-auth" alt="Downloads" />
|
||||
</a>
|
||||
<a href="https://github.com/nextauthjs/next-auth/stargazers">
|
||||
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth" alt="Github Stars" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/next-auth">
|
||||
<img src="https://img.shields.io/github/v/release/nextauthjs/next-auth?label=latest" alt="Github Stable Release" />
|
||||
</a>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
## Overview
|
||||
|
||||
NextAuth.js is a complete open source authentication solution for [Next.js](http://nextjs.org/) applications.
|
||||
|
||||
It is designed from the ground up to support Next.js and Serverless.
|
||||
|
||||
This is a monorepo containing the following packages / projects:
|
||||
|
||||
1. The primary `next-auth` package
|
||||
2. A development test application
|
||||
3. All `@next-auth/*-adapter` packages
|
||||
4. The documentation site
|
||||
|
||||
## Getting Started
|
||||
|
||||
```
|
||||
npm install next-auth
|
||||
```
|
||||
|
||||
The easiest way to continue getting started, is to follow the [getting started](https://next-auth.js.org/getting-started/example) section in our docs.
|
||||
|
||||
We also have a section of [tutorials](https://next-auth.js.org/tutorials) for those looking for more specific examples.
|
||||
|
||||
See [next-auth.js.org](https://next-auth.js.org) for more information and documentation.
|
||||
|
||||
## Features
|
||||
|
||||
### Flexible and easy to use
|
||||
|
||||
- Designed to work with any OAuth service, it supports OAuth 1.0, 1.0A and 2.0
|
||||
- Built-in support for [many popular sign-in services](https://next-auth.js.org/providers)
|
||||
- Supports email / passwordless authentication
|
||||
- Supports stateless authentication with any backend (Active Directory, LDAP, etc)
|
||||
- Supports both JSON Web Tokens and database sessions
|
||||
- Designed for Serverless but runs anywhere (AWS Lambda, Docker, Heroku, etc…)
|
||||
|
||||
### Own your own data
|
||||
|
||||
NextAuth.js can be used with or without a database.
|
||||
|
||||
- An open source solution that allows you to keep control of your data
|
||||
- Supports Bring Your Own Database (BYOD) and can be used with any database
|
||||
- Built-in support for [MySQL, MariaDB, Postgres, Microsoft SQL Server, MongoDB and SQLite](https://next-auth.js.org/configuration/databases)
|
||||
- Works great with databases from popular hosting providers
|
||||
- Can also be used _without a database_ (e.g. OAuth + JWT)
|
||||
|
||||
### Secure by default
|
||||
|
||||
- Promotes the use of passwordless sign-in mechanisms
|
||||
- Designed to be secure by default and encourage best practices for safeguarding user data
|
||||
- Uses Cross-Site Request Forgery (CSRF) Tokens on POST routes (sign in, sign out)
|
||||
- Default cookie policy aims for the most restrictive policy appropriate for each cookie
|
||||
- When JSON Web Tokens are enabled, they are encrypted by default (JWE) with A256GCM
|
||||
- Auto-generates symmetric signing and encryption keys for developer convenience
|
||||
- Features tab/window syncing and session polling to support short lived sessions
|
||||
- Attempts to implement the latest guidance published by [Open Web Application Security Project](https://owasp.org)
|
||||
|
||||
Advanced options allow you to define your own routines to handle controlling what accounts are allowed to sign in, for encoding and decoding JSON Web Tokens and to set custom cookie security policies and session properties, so you can control who is able to sign in and how often sessions have to be re-validated.
|
||||
|
||||
### TypeScript
|
||||
|
||||
NextAuth.js comes with built-in types. For more information and usage, check out
|
||||
the [TypeScript section](https://next-auth.js.org/getting-started/typescript) in the documentation.
|
||||
|
||||
## Example
|
||||
|
||||
### Add API Route
|
||||
|
||||
```javascript
|
||||
// pages/api/auth/[...nextauth].js
|
||||
import NextAuth from "next-auth"
|
||||
import AppleProvider from "next-auth/providers/apple"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
import EmailProvider from "next-auth/providers/email"
|
||||
|
||||
export default NextAuth({
|
||||
secret: process.env.SECRET,
|
||||
providers: [
|
||||
// OAuth authentication providers
|
||||
AppleProvider({
|
||||
clientId: process.env.APPLE_ID,
|
||||
clientSecret: process.env.APPLE_SECRET,
|
||||
}),
|
||||
GoogleProvider({
|
||||
clientId: process.env.GOOGLE_ID,
|
||||
clientSecret: process.env.GOOGLE_SECRET,
|
||||
}),
|
||||
// Sign in with passwordless email link
|
||||
EmailProvider({
|
||||
server: process.env.MAIL_SERVER,
|
||||
from: "<no-reply@example.com>",
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
### Add React Hook
|
||||
|
||||
The `useSession()` React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
|
||||
|
||||
```javascript
|
||||
import { useSession, signIn, signOut } from "next-auth/react"
|
||||
|
||||
export default function Component() {
|
||||
const { data: session } = useSession()
|
||||
if (session) {
|
||||
return (
|
||||
<>
|
||||
Signed in as {session.user.email} <br />
|
||||
<button onClick={() => signOut()}>Sign out</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
Not signed in <br />
|
||||
<button onClick={() => signIn()}>Sign in</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Share/configure session state
|
||||
|
||||
Use the `<SessionProvider>` to allow instances of `useSession()` to share the session object across components. It also takes care of keeping the session updated and synced between tabs/windows.
|
||||
|
||||
```jsx title="pages/_app.js"
|
||||
import { SessionProvider } from "next-auth/react"
|
||||
|
||||
export default function App({
|
||||
Component,
|
||||
pageProps: { session, ...pageProps },
|
||||
}) {
|
||||
return (
|
||||
<SessionProvider session={session}>
|
||||
<Component {...pageProps} />
|
||||
</SessionProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
If you think you have found a vulnerability (or not sure) in NextAuth.js or any of the related packages (i.e. Adapters), we ask you to have a read of our [Security Policy](https://github.com/nextauthjs/next-auth/blob/main/SECURITY.md) to reach out responsibly. Please do not open Pull Requests/Issues/Discussions before consulting with us.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
[NextAuth.js is made possible thanks to all of its contributors.](https://next-auth.js.org/contributors)
|
||||
|
||||
<a href="https://github.com/nextauthjs/next-auth/graphs/contributors">
|
||||
<img width="500px" src="https://contrib.rocks/image?repo=nextauthjs/next-auth" />
|
||||
</a>
|
||||
<div>
|
||||
<a href="https://vercel.com?utm_source=nextauthjs&utm_campaign=oss"></a>
|
||||
</div>
|
||||
|
||||
### Support
|
||||
|
||||
We're happy to announce we've recently created an [OpenCollective](https://opencollective.com/nextauth) for individuals and companies looking to contribute financially to the project!
|
||||
|
||||
<!--sponsors start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://vercel.com" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/14985020?v=4" alt="Vercel Logo" />
|
||||
</a><br />
|
||||
<div>Vercel</div><br />
|
||||
<sub>🥉 Bronze Financial Sponsor <br /> ☁️ Infrastructure Support</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://prisma.io" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/17219288?v=4" alt="Prisma Logo" />
|
||||
</a><br />
|
||||
<div>Prisma</div><br />
|
||||
<sub>🥉 Bronze Financial Sponsor</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://clerk.com" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/49538330?s=200&v=4" alt="Clerk Logo" />
|
||||
</a><br />
|
||||
<div>Clerk</div><br />
|
||||
<sub>🥉 Bronze Financial Sponsor</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://lowdefy.com" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/47087496?s=200&v=4" alt="Lowdefy Logo" />
|
||||
</a><br />
|
||||
<div>Lowdefy</div><br />
|
||||
<sub>🥉 Bronze Financial Sponsor</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://workos.com" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/47638084?s=200&v=4" alt="WorkOS Logo" />
|
||||
</a><br />
|
||||
<div>WorkOS</div><br />
|
||||
<sub>🥉 Bronze Financial Sponsor</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://checklyhq.com" target="_blank">
|
||||
<img width="128px" src="https://avatars.githubusercontent.com/u/25982255?v=4" alt="Checkly Logo" />
|
||||
</a><br />
|
||||
<div>Checkly</div><br />
|
||||
<sub>☁️ Infrastructure Support</sub>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<a href="https://superblog.ai/" target="_blank">
|
||||
<img width="128px" src="https://d33wubrfki0l68.cloudfront.net/cdc4a3833bd878933fcc131655878dbf226ac1c5/10cd6/images/logo_bolt_small.png" alt="superblog Logo" />
|
||||
</a><br />
|
||||
<div>superblog</div><br />
|
||||
<sub>☁️ Infrastructure Support</sub>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<!--sponsors end-->
|
||||
|
||||
## Contributing
|
||||
|
||||
We're open to all community contributions! If you'd like to contribute in any way, please first read
|
||||
our [Contributing Guide](https://github.com/nextauthjs/.github/blob/main/CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
ISC
|
||||
62
packages/next-auth/config/babel.config.js
Normal file
@@ -0,0 +1,62 @@
|
||||
// @ts-check
|
||||
// We aim to have the same support as Next.js
|
||||
// https://nextjs.org/docs/getting-started#system-requirements
|
||||
// https://nextjs.org/docs/basic-features/supported-browsers-features
|
||||
|
||||
/** @type {import("@babel/core").ConfigFunction} */
|
||||
module.exports = (api) => {
|
||||
const isTest = api.env("test")
|
||||
if (isTest) {
|
||||
return {
|
||||
presets: [
|
||||
"@babel/preset-env",
|
||||
["@babel/preset-react", { runtime: "automatic" }],
|
||||
["@babel/preset-typescript", { isTSX: true, allExtensions: true }],
|
||||
],
|
||||
}
|
||||
}
|
||||
return {
|
||||
presets: [
|
||||
["@babel/preset-env", { targets: { node: 12 } }],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
plugins: [
|
||||
"@babel/plugin-proposal-optional-catch-binding",
|
||||
"@babel/plugin-transform-runtime",
|
||||
],
|
||||
ignore: [
|
||||
"../src/**/__tests__/**",
|
||||
"../src/adapters.ts",
|
||||
"../src/providers/oauth-types.ts",
|
||||
],
|
||||
comments: false,
|
||||
overrides: [
|
||||
{
|
||||
test: [
|
||||
"../src/react/index.tsx",
|
||||
"../src/utils/logger.ts",
|
||||
"../src/core/errors.ts",
|
||||
"../src/client/**",
|
||||
],
|
||||
presets: [
|
||||
["@babel/preset-env", { targets: { ie: 11 } }],
|
||||
["@babel/preset-react", { runtime: "automatic" }],
|
||||
],
|
||||
},
|
||||
{
|
||||
test: ["../src/core/pages/*.tsx"],
|
||||
presets: ["preact"],
|
||||
plugins: [
|
||||
[
|
||||
"jsx-pragmatic",
|
||||
{
|
||||
module: "preact",
|
||||
export: "h",
|
||||
import: "h",
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
18
packages/next-auth/config/generate-providers.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const path = require("path")
|
||||
const fs = require("fs")
|
||||
|
||||
const providersPath = path.join(process.cwd(), "src/providers")
|
||||
|
||||
const files = fs.readdirSync(providersPath, "utf8")
|
||||
|
||||
const providers = files.map((file) => {
|
||||
const strippedProviderName = file.substring(0, file.indexOf("."))
|
||||
return `"${strippedProviderName}"`
|
||||
})
|
||||
|
||||
const result = `
|
||||
// THIS FILE IS AUTOGENERATED. DO NOT EDIT.
|
||||
export type OAuthProviderType =
|
||||
| ${providers.join("\n | ")}`
|
||||
|
||||
fs.writeFileSync(path.join(providersPath, "oauth-types.ts"), result)
|
||||
3
packages/next-auth/config/jest-setup.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import "regenerator-runtime/runtime"
|
||||
import "@testing-library/jest-dom"
|
||||
import "whatwg-fetch"
|
||||
43
packages/next-auth/config/jest.config.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const swcConfig = require("./swc.config")
|
||||
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
projects: [
|
||||
{
|
||||
displayName: "core",
|
||||
testMatch: ["<rootDir>/tests/**/*.test.ts"],
|
||||
rootDir: ".",
|
||||
transform: {
|
||||
"\\.(js|jsx|ts|tsx)$": ["@swc/jest", swcConfig],
|
||||
},
|
||||
coveragePathIgnorePatterns: ["tests"],
|
||||
testEnvironment: "@edge-runtime/jest-environment",
|
||||
transformIgnorePatterns: ["node_modules/(?!uuid)/"],
|
||||
/** @type {import("@edge-runtime/vm").EdgeVMOptions} */
|
||||
testEnvironmentOptions: {
|
||||
codeGeneration: {
|
||||
strings: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: "client",
|
||||
testMatch: ["<rootDir>/src/client/**/*.test.js"],
|
||||
setupFilesAfterEnv: ["./config/jest-setup.js"],
|
||||
rootDir: ".",
|
||||
transform: {
|
||||
"\\.(js|jsx|ts|tsx)$": ["@swc/jest", swcConfig],
|
||||
},
|
||||
testEnvironment: "jsdom",
|
||||
coveragePathIgnorePatterns: ["__tests__"],
|
||||
},
|
||||
],
|
||||
watchPlugins: [
|
||||
"jest-watch-typeahead/filename",
|
||||
"jest-watch-typeahead/testname",
|
||||
],
|
||||
collectCoverage: true,
|
||||
coverageDirectory: "../coverage",
|
||||
coverageReporters: ["html", "text-summary"],
|
||||
collectCoverageFrom: ["src/**/*.(js|jsx|ts|tsx)"],
|
||||
}
|
||||
7
packages/next-auth/config/postcss.config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer'),
|
||||
require('postcss-nested'),
|
||||
require('cssnano')({ preset: 'default' })
|
||||
]
|
||||
}
|
||||
18
packages/next-auth/config/swc.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/** @type {import("@swc/core").Config} */
|
||||
module.exports = {
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: "typescript",
|
||||
tsx: true,
|
||||
},
|
||||
transform: {
|
||||
react: {
|
||||
runtime: "automatic",
|
||||
pragma: "React.createElement",
|
||||
pragmaFrag: "React.Fragment",
|
||||
throwIfNamespace: true,
|
||||
useBuiltins: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
17
packages/next-auth/config/wrap-css.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// Serverless target in Next.js does not work if you try to read in files at runtime
|
||||
// that are not JavaScript or JSON (e.g. CSS files).
|
||||
// https://github.com/nextauthjs/next-auth/issues/281
|
||||
//
|
||||
// To work around this issue, this script is a manual step that wraps CSS in a
|
||||
// JavaScript file that has the compiled CSS embedded in it, and exports only
|
||||
// a function that returns the CSS as a string.
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
|
||||
const pathToCss = path.join(__dirname, "../css/index.css")
|
||||
const css = fs.readFileSync(pathToCss, "utf8")
|
||||
const cssWithEscapedQuotes = css.replace(/"/gm, '\\"')
|
||||
|
||||
const js = `module.exports = function() { return "${cssWithEscapedQuotes}" }`
|
||||
const pathToCssJs = path.join(__dirname, "../css/index.js")
|
||||
fs.writeFileSync(pathToCssJs, js)
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "next-auth",
|
||||
"version": "4.22.1",
|
||||
"description": "Authentication for Next.js",
|
||||
"homepage": "https://nextjs.authjs.dev",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
"author": "Iain Collins <me@iaincollins.com>",
|
||||
"contributors": [
|
||||
@@ -11,6 +11,9 @@
|
||||
"Lluis Agusti <hi@llu.lu>",
|
||||
"Thang Huu Vu <thvu@hey.com>"
|
||||
],
|
||||
"main": "index.js",
|
||||
"module": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"keywords": [
|
||||
"react",
|
||||
"nodejs",
|
||||
@@ -23,59 +26,104 @@
|
||||
"oidc",
|
||||
"nextauth"
|
||||
],
|
||||
"type": "module",
|
||||
"types": "./index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"import": "./index.js"
|
||||
},
|
||||
"./adapters": {
|
||||
"types": "./adapters.d.ts"
|
||||
},
|
||||
"./jwt": {
|
||||
"types": "./jwt.d.ts",
|
||||
"import": "./jwt.js"
|
||||
},
|
||||
"./middleware": {
|
||||
"types": "./middleware.d.ts",
|
||||
"import": "./middleware.js"
|
||||
},
|
||||
"./next": {
|
||||
"types": "./next.d.ts",
|
||||
"import": "./next.js"
|
||||
},
|
||||
"./providers": {
|
||||
"types": "./providers.d.ts"
|
||||
},
|
||||
"./react": {
|
||||
"types": "./react.d.ts",
|
||||
"import": "./react.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
".": "./index.js",
|
||||
"./jwt": "./jwt/index.js",
|
||||
"./react": "./react/index.js",
|
||||
"./core": "./core/index.js",
|
||||
"./next": "./next/index.js",
|
||||
"./middleware": "./middleware.js",
|
||||
"./client/_utils": "./client/_utils.js",
|
||||
"./providers/*": "./providers/*.js"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "tsc -w",
|
||||
"clean": "rm -rf *.js *.d.ts lib",
|
||||
"build": "pnpm clean && tsc"
|
||||
"build": "pnpm clean && pnpm build:js && pnpm build:css",
|
||||
"build:js": "pnpm clean && pnpm generate-providers && pnpm tsc --project tsconfig.json && babel --config-file ./config/babel.config.js src --out-dir . --extensions \".tsx,.ts,.js,.jsx\"",
|
||||
"clean": "rm -rf coverage client css utils providers core jwt react next index.d.ts index.js adapters.d.ts middleware.d.ts middleware.js",
|
||||
"build:css": "postcss --config config/postcss.config.js src/**/*.css --base src --dir . && node config/wrap-css.js",
|
||||
"dev": "pnpm clean && pnpm generate-providers && concurrently \"pnpm watch:css\" \"pnpm watch:ts\"",
|
||||
"watch:ts": "pnpm tsc --project tsconfig.dev.json",
|
||||
"watch:css": "postcss --config config/postcss.config.js --watch src/**/*.css --base src --dir .",
|
||||
"test": "jest --config ./config/jest.config.js",
|
||||
"prepublishOnly": "pnpm build",
|
||||
"generate-providers": "node ./config/generate-providers.js",
|
||||
"lint": "eslint src config tests"
|
||||
},
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.d.ts",
|
||||
"client",
|
||||
"core",
|
||||
"css",
|
||||
"jwt",
|
||||
"lib",
|
||||
"src"
|
||||
"next",
|
||||
"providers",
|
||||
"react",
|
||||
"src",
|
||||
"utils",
|
||||
"*.d.ts*",
|
||||
"*.js"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/react": "18.0.37",
|
||||
"typescript": "^4",
|
||||
"next": "13.3.3"
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@auth/core": "workspace:*"
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@panva/hkdf": "^1.0.2",
|
||||
"cookie": "^0.5.0",
|
||||
"jose": "^4.11.4",
|
||||
"oauth": "^0.9.15",
|
||||
"openid-client": "^5.4.0",
|
||||
"preact": "^10.6.3",
|
||||
"preact-render-to-string": "^5.1.19",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^13.3.3",
|
||||
"react": "^18.2.0"
|
||||
"next": "^12.2.5 || ^13",
|
||||
"nodemailer": "^6.6.5",
|
||||
"react": "^17.0.2 || ^18",
|
||||
"react-dom": "^17.0.2 || ^18"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"nodemailer": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.17.10",
|
||||
"@babel/core": "^7.18.2",
|
||||
"@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
|
||||
"@babel/plugin-transform-runtime": "^7.18.2",
|
||||
"@babel/preset-env": "^7.18.2",
|
||||
"@babel/preset-react": "^7.17.12",
|
||||
"@babel/preset-typescript": "^7.17.12",
|
||||
"@edge-runtime/jest-environment": "1.1.0-beta.35",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@swc/core": "^1.2.198",
|
||||
"@swc/jest": "^0.2.21",
|
||||
"@testing-library/dom": "^8.13.0",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
"@testing-library/react-hooks": "^8.0.0",
|
||||
"@testing-library/user-event": "^14.2.0",
|
||||
"@types/jest": "^28.1.3",
|
||||
"@types/node": "^17.0.42",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/oauth": "^0.9.1",
|
||||
"@types/react": "18.0.37",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"babel-plugin-jsx-pragmatic": "^1.0.2",
|
||||
"babel-preset-preact": "^2.0.0",
|
||||
"concurrently": "^7",
|
||||
"cssnano": "^5.1.11",
|
||||
"jest": "^28.1.1",
|
||||
"jest-environment-jsdom": "^28.1.1",
|
||||
"jest-watch-typeahead": "^1.1.0",
|
||||
"msw": "^0.42.3",
|
||||
"next": "13.3.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss-cli": "^9.1.0",
|
||||
"postcss-nested": "^5.0.6",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"whatwg-fetch": "^3.6.2"
|
||||
}
|
||||
}
|
||||
|
||||
4
packages/next-auth/provider-logos/apple-dark.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="4 32 376.4 449.4" width="32" height="32">
|
||||
<title>Apple icon</title>
|
||||
<path fill="#fff" d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 588 B |
4
packages/next-auth/provider-logos/apple.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="4 32 376.4 449.4" width="32" height="32">
|
||||
<title>Apple icon</title>
|
||||
<path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 576 B |
8
packages/next-auth/provider-logos/atlassian-dark.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg viewBox="0.29136862699701993 -41.138268758326056 145.22149045698177 186.73799623391153" xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||
<linearGradient id="a" gradientTransform="matrix(1 0 0 -1 0 228)" gradientUnits="userSpaceOnUse" x1="62.57" x2="25.03" y1="150.13" y2="85.11">
|
||||
<stop offset="0" stop-color="#0052cc"/>
|
||||
<stop offset=".92" stop-color="#2684ff"/>
|
||||
</linearGradient>
|
||||
<path d="M43 67a4.14 4.14 0 0 0-5.79-.78A4.29 4.29 0 0 0 36 67.73L.45 138.85a4.25 4.25 0 0 0 1.9 5.7 4.18 4.18 0 0 0 1.9.45h49.53a4.08 4.08 0 0 0 3.8-2.35C68.27 120.57 61.79 87 43 67z" fill="url(#a)"/>
|
||||
<path d="M69.13 2.28a93.82 93.82 0 0 0-5.48 92.61l23.88 47.76a4.25 4.25 0 0 0 3.8 2.35h49.52a4.24 4.24 0 0 0 4.25-4.25 4.31 4.31 0 0 0-.44-1.9L76.36 2.26a4 4 0 0 0-7.23 0z" fill="#2684ff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 810 B |
4
packages/next-auth/provider-logos/atlassian.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg viewBox="0.29136862699701993 -41.138268758326056 145.22149045698177 186.73799623391153" xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||
<path d="M43 67a4.14 4.14 0 0 0-5.79-.78A4.29 4.29 0 0 0 36 67.73L.45 138.85a4.25 4.25 0 0 0 1.9 5.7 4.18 4.18 0 0 0 1.9.45h49.53a4.08 4.08 0 0 0 3.8-2.35C68.27 120.57 61.79 87 43 67z" fill="#fff"/>
|
||||
<path d="M69.13 2.28a93.82 93.82 0 0 0-5.48 92.61l23.88 47.76a4.25 4.25 0 0 0 3.8 2.35h49.52a4.24 4.24 0 0 0 4.25-4.25 4.31 4.31 0 0 0-.44-1.9L76.36 2.26a4 4 0 0 0-7.23 0z" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 549 B |
12
packages/next-auth/provider-logos/auth0-dark.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg width="32" height="32" viewBox="0 0 41 45" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M35.3018 0H20.5L25.0737 14.076H39.8755L27.9009 22.4701L32.4746 36.6253C40.1827 31.081 42.7027 22.6883 39.8755 14.076L35.3018 0Z" fill="white"/>
|
||||
<path d="M1.12504 14.076H15.9268L20.5005 0H5.69875L1.12504 14.076C-1.70213 22.6898 0.8178 31.081 8.52592 36.6253L13.0996 22.4701L1.12504 14.076Z" fill="white"/>
|
||||
<path d="M8.52539 36.6251L20.5 44.9998L32.4746 36.6251L20.5 28.1084L8.52539 36.6251Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="41" height="45" fill="none"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 677 B |
3
packages/next-auth/provider-logos/auth0.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 256 287" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet">
|
||||
<path d="M203.24 231.531l-28.73-88.434 75.208-54.64h-92.966L128.019.025l-.009-.024h92.98l28.74 88.446.002-.002.024-.013c16.69 51.31-.5 109.67-46.516 143.098zm-150.45 0l-.023.017 75.228 54.655 75.245-54.67-75.221-54.656-75.228 54.654zM6.295 88.434c-17.57 54.088 2.825 111.4 46.481 143.108l.007-.028 28.735-88.429-75.192-54.63h92.944L128.004.024 128.01 0H35.025L6.294 88.434z" fill="#EB5424"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 523 B |
3
packages/next-auth/provider-logos/azure-dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 59.242 47.271" width="32" height="32" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m32.368 0-17.468 15.145-14.9 26.75h13.437zm2.323 3.543-7.454 21.008 14.291 17.956-27.728 4.764h45.442z" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 228 B |
3
packages/next-auth/provider-logos/azure.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 59.242 47.271" width="32" height="32" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m32.368 0-17.468 15.145-14.9 26.75h13.437zm2.323 3.543-7.454 21.008 14.291 17.956-27.728 4.764h45.442z" fill="#0072c6"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 231 B |
3
packages/next-auth/provider-logos/battlenet-dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 580.44" width="32" height="32">
|
||||
<path d="M473.49,197.63c-75.94-35.11-185.08-57.42-287.78-49.11,5.15-34,17.85-57.69,38.7-62.68,28.69-6.88,60,12,89.84,46.35,19.55,2.53,42.73,7,58.86,10.71C318.7,40.56,245.72-16.8,190.21,4.36,148,20.47,126.39,78.59,129,156.69c-55,11.7-97.87,32.49-125.31,62.39-1.39,1.61-4.53,5.67-3.41,7.61.85,1.47,3.65-.18,4.85-1,31.83-22.26,72.58-34.31,125.66-41.89,7.56,83.32,42.81,189,101.36,273.78-32,12.56-58.89,13.39-73.64-2.17-20.29-21.41-19.61-57.95-4.77-101-7.58-18.2-15.31-40.51-20.15-56.34C72.12,396.41,58.93,488.29,105,525.78c35.07,28.52,96.18,18.15,162.54-23.12,37.64,41.79,77.07,68.51,116.69,77.33,2.09.39,7.17,1.09,8.29-.85.85-1.47-2-3.08-3.28-3.71-35.19-16.44-66-45.71-99.1-87.88C358.53,439.34,432.42,356,476.57,262.88c26.9,21.47,41,44.3,34.94,64.85-8.4,28.29-40.38,46-85.06,54.63C414.48,398,399,415.86,387.74,428c115.84,4,202-30.47,211.43-89.12,7.17-44.64-32.37-92.38-101.3-129.21,17.38-53.49,20.8-101,8.63-139.72-.71-2-2.64-6.76-4.88-6.76-1.7,0-1.68,3.26-1.58,4.7C503.41,106.55,493.47,147.88,473.49,197.63ZM260.21,444.33c-49-78.61-77.24-171.21-77.06-264.84h0C275.71,176.39,370,198.2,451,245.17h0c-43.59,81.71-109.64,152.49-190.82,199.15Z" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
3
packages/next-auth/provider-logos/battlenet.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 580.44" width="32" height="32">
|
||||
<path d="M473.49,197.63c-75.94-35.11-185.08-57.42-287.78-49.11,5.15-34,17.85-57.69,38.7-62.68,28.69-6.88,60,12,89.84,46.35,19.55,2.53,42.73,7,58.86,10.71C318.7,40.56,245.72-16.8,190.21,4.36,148,20.47,126.39,78.59,129,156.69c-55,11.7-97.87,32.49-125.31,62.39-1.39,1.61-4.53,5.67-3.41,7.61.85,1.47,3.65-.18,4.85-1,31.83-22.26,72.58-34.31,125.66-41.89,7.56,83.32,42.81,189,101.36,273.78-32,12.56-58.89,13.39-73.64-2.17-20.29-21.41-19.61-57.95-4.77-101-7.58-18.2-15.31-40.51-20.15-56.34C72.12,396.41,58.93,488.29,105,525.78c35.07,28.52,96.18,18.15,162.54-23.12,37.64,41.79,77.07,68.51,116.69,77.33,2.09.39,7.17,1.09,8.29-.85.85-1.47-2-3.08-3.28-3.71-35.19-16.44-66-45.71-99.1-87.88C358.53,439.34,432.42,356,476.57,262.88c26.9,21.47,41,44.3,34.94,64.85-8.4,28.29-40.38,46-85.06,54.63C414.48,398,399,415.86,387.74,428c115.84,4,202-30.47,211.43-89.12,7.17-44.64-32.37-92.38-101.3-129.21,17.38-53.49,20.8-101,8.63-139.72-.71-2-2.64-6.76-4.88-6.76-1.7,0-1.68,3.26-1.58,4.7C503.41,106.55,493.47,147.88,473.49,197.63ZM260.21,444.33c-49-78.61-77.24-171.21-77.06-264.84h0C275.71,176.39,370,198.2,451,245.17h0c-43.59,81.71-109.64,152.49-190.82,199.15Z" fill="#148eff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
6
packages/next-auth/provider-logos/box-dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 444.893 245.414">
|
||||
<g fill="#fff">
|
||||
<path d="M239.038 72.43c-33.081 0-61.806 18.6-76.322 45.904-14.516-27.305-43.24-45.902-76.32-45.902-19.443 0-37.385 6.424-51.821 17.266V16.925h-.008C34.365 7.547 26.713 0 17.286 0 7.858 0 .208 7.547.008 16.925H0v143.333h.036c.768 47.051 39.125 84.967 86.359 84.967 33.08 0 61.805-18.603 76.32-45.908 14.517 27.307 43.241 45.906 76.321 45.906 47.715 0 86.396-38.684 86.396-86.396.001-47.718-38.682-86.397-86.394-86.397zM86.395 210.648c-28.621 0-51.821-23.201-51.821-51.82 0-28.623 23.201-51.823 51.821-51.823 28.621 0 51.822 23.2 51.822 51.823 0 28.619-23.201 51.82-51.822 51.82zm152.643 0c-28.622 0-51.821-23.201-51.821-51.822 0-28.623 23.2-51.821 51.821-51.821 28.619 0 51.822 23.198 51.822 51.821-.001 28.621-23.203 51.822-51.822 51.822z"/>
|
||||
<path d="M441.651 218.033l-44.246-59.143 44.246-59.144-.008-.007c5.473-7.62 3.887-18.249-3.652-23.913-7.537-5.658-18.187-4.221-23.98 3.157l-.004-.002-38.188 51.047-38.188-51.047-.006.009c-5.793-7.385-16.441-8.822-23.981-3.16-7.539 5.664-9.125 16.293-3.649 23.911l-.008.005 44.245 59.144-44.245 59.143.008.005c-5.477 7.62-3.89 18.247 3.649 23.909 7.54 5.664 18.188 4.225 23.981-3.155l.006.007 38.188-51.049 38.188 51.049.004-.002c5.794 7.377 16.443 8.814 23.98 3.154 7.539-5.662 9.125-16.291 3.652-23.91l.008-.008z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
6
packages/next-auth/provider-logos/box.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 444.893 245.414">
|
||||
<g fill="#0075C9">
|
||||
<path d="M239.038 72.43c-33.081 0-61.806 18.6-76.322 45.904-14.516-27.305-43.24-45.902-76.32-45.902-19.443 0-37.385 6.424-51.821 17.266V16.925h-.008C34.365 7.547 26.713 0 17.286 0 7.858 0 .208 7.547.008 16.925H0v143.333h.036c.768 47.051 39.125 84.967 86.359 84.967 33.08 0 61.805-18.603 76.32-45.908 14.517 27.307 43.241 45.906 76.321 45.906 47.715 0 86.396-38.684 86.396-86.396.001-47.718-38.682-86.397-86.394-86.397zM86.395 210.648c-28.621 0-51.821-23.201-51.821-51.82 0-28.623 23.201-51.823 51.821-51.823 28.621 0 51.822 23.2 51.822 51.823 0 28.619-23.201 51.82-51.822 51.82zm152.643 0c-28.622 0-51.821-23.201-51.821-51.822 0-28.623 23.2-51.821 51.821-51.821 28.619 0 51.822 23.198 51.822 51.821-.001 28.621-23.203 51.822-51.822 51.822z"/>
|
||||
<path d="M441.651 218.033l-44.246-59.143 44.246-59.144-.008-.007c5.473-7.62 3.887-18.249-3.652-23.913-7.537-5.658-18.187-4.221-23.98 3.157l-.004-.002-38.188 51.047-38.188-51.047-.006.009c-5.793-7.385-16.441-8.822-23.981-3.16-7.539 5.664-9.125 16.293-3.649 23.911l-.008.005 44.245 59.144-44.245 59.143.008.005c-5.477 7.62-3.89 18.247 3.649 23.909 7.54 5.664 18.188 4.225 23.981-3.155l.006.007 38.188-51.049 38.188 51.049.004-.002c5.794 7.377 16.443 8.814 23.98 3.154 7.539-5.662 9.125-16.291 3.652-23.91l.008-.008z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
10
packages/next-auth/provider-logos/cognito.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="32" height="32" viewBox="0 0 256 299" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid">
|
||||
<path d="M208.752 58.061l25.771-6.636.192.283.651 155.607-.843.846-5.31.227-20.159-3.138-.302-.794V58.061M59.705 218.971l.095.007 68.027 19.767.173.133.296.236-.096 59.232-.2.252-68.295-33.178v-46.449" fill="#7A3E65"/>
|
||||
<path d="M208.752 204.456l-80.64 19.312-40.488-9.773-27.919 4.976L128 238.878l105.405-28.537 1.118-2.18-25.771-3.705" fill="#CFB2C1"/>
|
||||
<path d="M196.295 79.626l-.657-.749-66.904-19.44-.734.283-.672-.343L22.052 89.734l-.575.703.845.463 24.075 3.53.851-.289 80.64-19.311 40.488 9.773 27.919-4.977" fill="#512843"/>
|
||||
<path d="M47.248 240.537l-25.771 6.221-.045-.149-1.015-155.026 1.06-1.146 25.771 3.704v146.396" fill="#C17B9E"/>
|
||||
<path d="M82.04 180.403l45.96 5.391.345-.515.187-71.887-.532-.589-45.96 5.392v62.208" fill="#7A3E65"/>
|
||||
<path d="M173.96 180.403L128 185.794v-72.991l45.96 5.392v62.208M196.295 79.626L128 59.72V0l68.295 33.177v46.449" fill="#C17B9E"/>
|
||||
<path d="M128 0L0 61.793v175.011l21.477 9.954V90.437L128 59.72V0" fill="#7A3E65"/>
|
||||
<path d="M234.523 51.425v156.736L128 238.878v59.72l128-61.794V61.793l-21.477-10.368" fill="#C17B9E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
3
packages/next-auth/provider-logos/discord-dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 256 293" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid">
|
||||
<path d="M226.011 0H29.99C13.459 0 0 13.458 0 30.135v197.778c0 16.677 13.458 30.135 29.989 30.135h165.888l-7.754-27.063 18.725 17.408 17.7 16.384L256 292.571V30.135C256 13.458 242.542 0 226.011 0zm-56.466 191.05s-5.266-6.291-9.655-11.85c19.164-5.413 26.478-17.408 26.478-17.408-5.998 3.95-11.703 6.73-16.823 8.63-7.314 3.073-14.336 5.12-21.211 6.291-14.044 2.633-26.917 1.902-37.888-.146-8.339-1.61-15.507-3.95-21.504-6.29-3.365-1.317-7.022-2.926-10.68-4.974-.438-.293-.877-.439-1.316-.732-.292-.146-.439-.292-.585-.438-2.633-1.463-4.096-2.487-4.096-2.487s7.022 11.703 25.6 17.261c-4.388 5.56-9.801 12.142-9.801 12.142-32.33-1.024-44.617-22.235-44.617-22.235 0-47.104 21.065-85.285 21.065-85.285 21.065-15.799 41.106-15.36 41.106-15.36l1.463 1.756C80.75 77.53 68.608 89.088 68.608 89.088s3.218-1.755 8.63-4.242c15.653-6.876 28.088-8.777 33.208-9.216.877-.147 1.609-.293 2.487-.293a123.776 123.776 0 0 1 29.55-.292c13.896 1.609 28.818 5.705 44.031 14.043 0 0-11.556-10.971-36.425-18.578l2.048-2.34s20.041-.44 41.106 15.36c0 0 21.066 38.18 21.066 85.284 0 0-12.435 21.211-44.764 22.235zm-68.023-68.316c-8.338 0-14.92 7.314-14.92 16.237 0 8.924 6.728 16.238 14.92 16.238 8.339 0 14.921-7.314 14.921-16.238.147-8.923-6.582-16.237-14.92-16.237m53.394 0c-8.339 0-14.922 7.314-14.922 16.237 0 8.924 6.73 16.238 14.922 16.238 8.338 0 14.92-7.314 14.92-16.238 0-8.923-6.582-16.237-14.92-16.237" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
3
packages/next-auth/provider-logos/discord.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 256 293" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid">
|
||||
<path d="M226.011 0H29.99C13.459 0 0 13.458 0 30.135v197.778c0 16.677 13.458 30.135 29.989 30.135h165.888l-7.754-27.063 18.725 17.408 17.7 16.384L256 292.571V30.135C256 13.458 242.542 0 226.011 0zm-56.466 191.05s-5.266-6.291-9.655-11.85c19.164-5.413 26.478-17.408 26.478-17.408-5.998 3.95-11.703 6.73-16.823 8.63-7.314 3.073-14.336 5.12-21.211 6.291-14.044 2.633-26.917 1.902-37.888-.146-8.339-1.61-15.507-3.95-21.504-6.29-3.365-1.317-7.022-2.926-10.68-4.974-.438-.293-.877-.439-1.316-.732-.292-.146-.439-.292-.585-.438-2.633-1.463-4.096-2.487-4.096-2.487s7.022 11.703 25.6 17.261c-4.388 5.56-9.801 12.142-9.801 12.142-32.33-1.024-44.617-22.235-44.617-22.235 0-47.104 21.065-85.285 21.065-85.285 21.065-15.799 41.106-15.36 41.106-15.36l1.463 1.756C80.75 77.53 68.608 89.088 68.608 89.088s3.218-1.755 8.63-4.242c15.653-6.876 28.088-8.777 33.208-9.216.877-.147 1.609-.293 2.487-.293a123.776 123.776 0 0 1 29.55-.292c13.896 1.609 28.818 5.705 44.031 14.043 0 0-11.556-10.971-36.425-18.578l2.048-2.34s20.041-.44 41.106 15.36c0 0 21.066 38.18 21.066 85.284 0 0-12.435 21.211-44.764 22.235zm-68.023-68.316c-8.338 0-14.92 7.314-14.92 16.237 0 8.924 6.728 16.238 14.92 16.238 8.339 0 14.921-7.314 14.921-16.238.147-8.923-6.582-16.237-14.92-16.237m53.394 0c-8.339 0-14.922 7.314-14.922 16.237 0 8.924 6.73 16.238 14.922 16.238 8.338 0 14.92-7.314 14.92-16.238 0-8.923-6.582-16.237-14.92-16.237" fill="#7289DA"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
4
packages/next-auth/provider-logos/facebook-dark.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" width="32" height="32" image-rendering="optimizeQuality" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" viewBox="6702.77 18309.17 6561.66 6561.660000000007" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9983.6 18309.17c1811.95 0 3280.83 1468.88 3280.83 3280.83s-1468.88 3280.83-3280.83 3280.83S6702.77 23401.95 6702.77 21590s1468.88-3280.83 3280.83-3280.83z" fill="#fff"/>
|
||||
<path d="M10409.89 24843.29v-2534.17h714.43l94.7-891.91h-809.13l1.2-446.44c0-232.63 22.1-357.22 356.24-357.22h446.68v-892.06h-714.59c-858.35 0-1160.42 432.65-1160.42 1160.34v535.45h-535.07v891.99H9339v2498.09c208.45 41.53 423.95 63.47 644.6 63.47a3310.9 3310.9 0 0 0 426.29-27.54z" fill="#006aff" fill-rule="nonzero"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 774 B |
8
packages/next-auth/provider-logos/facebook.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" width="32" height="32" image-rendering="optimizeQuality" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" viewBox="6702.77 18309.17 6561.66 6561.660000000007" xmlns="http://www.w3.org/2000/svg">
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="9983.6" x2="9983.6" y1="18249.39" y2="25150.62">
|
||||
<stop offset="0" stop-color="#00b2ff"/>
|
||||
<stop offset="1" stop-color="#006aff"/>
|
||||
</linearGradient>
|
||||
<path d="M9983.6 18309.17c1811.95 0 3280.83 1468.88 3280.83 3280.83s-1468.88 3280.83-3280.83 3280.83S6702.77 23401.95 6702.77 21590s1468.88-3280.83 3280.83-3280.83z" fill="url(#a)"/>
|
||||
<path d="M10409.89 24843.29v-2534.17h714.43l94.7-891.91h-809.13l1.2-446.44c0-232.63 22.1-357.22 356.24-357.22h446.68v-892.06h-714.59c-858.35 0-1160.42 432.65-1160.42 1160.34v535.45h-535.07v891.99H9339v2498.09c208.45 41.53 423.95 63.47 644.6 63.47a3310.9 3310.9 0 0 0 426.29-27.54z" fill="#fff" fill-rule="nonzero"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 991 B |
18
packages/next-auth/provider-logos/foursquare-dark.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 275.9 275.9" style="enable-background:new 0 0 275.9 275.9;">
|
||||
<style type="text/css">
|
||||
.st0{enable-background:new ;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<rect x="0.1" y="0.3" width="275.4" height="275.6"/>
|
||||
<g class="st0">
|
||||
<path class="st1" d="M69.2,50.1H121v8.5H77.8v23.8h38.4v8.5H77.8v34.4h-8.6C69.2,125.2,69.2,50.1,69.2,50.1z"/>
|
||||
<path class="st1" d="M67.7,198.8l8.4-1.9c1.5,10.4,8.7,16.6,20.4,16.6c10.5,0,18.8-4.9,18.8-12.9c0-5.7-4.2-10.5-20.6-15.4
|
||||
c-18.6-5.3-24.8-12.1-24.8-22.1c0-12.9,10.4-19.8,25.5-19.8c16.9,0,24.4,8.6,27,20.4l-8.4,1.9c-2.1-9.7-8.7-13.8-18.9-13.8
|
||||
c-9.6,0-16.4,3.6-16.4,10.5c0,5.6,4.4,9.9,19.6,14.7c18.1,5.6,25.9,11.7,25.9,23.3c0,14.4-12.1,21.9-27.5,21.9
|
||||
C80.6,222.1,69.6,213.8,67.7,198.8z"/>
|
||||
<path class="st1" d="M134.5,182.9c0-22.3,14.6-39.7,37-39.7c22.3,0,36.7,17.5,36.7,39.7c0,11.1-3.7,20.7-9.9,27.7
|
||||
c3,3,5.9,6,8.8,9.2l-6.2,6c-3-3.2-6.1-6.4-9.2-9.5c-5.7,3.7-12.5,5.8-20.2,5.8C149.9,222.1,134.5,205.6,134.5,182.9z M185.2,209.9
|
||||
c-2.9-2.8-5.8-5.5-8.8-8.1l6-6.1c3.2,2.8,6.4,5.7,9.4,8.6c4.5-5.4,7.2-12.8,7.2-21.5c0-17.6-10.7-31-27.5-31s-27.6,13.4-27.6,31
|
||||
c0,18.1,11.7,30.8,27.6,30.8C176.6,213.6,181.2,212.4,185.2,209.9z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
18
packages/next-auth/provider-logos/foursquare.svg
Normal file
@@ -0,0 +1,18 @@
|
||||
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 275.9 275.9" style="enable-background:new 0 0 275.9 275.9;">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{enable-background:new ;}
|
||||
</style>
|
||||
<rect x="0.1" y="0.3" class="st0" width="275.4" height="275.6"/>
|
||||
<g class="st1">
|
||||
<path d="M69.2,50.1H121v8.5H77.8v23.8h38.4v8.5H77.8v34.4h-8.6C69.2,125.2,69.2,50.1,69.2,50.1z"/>
|
||||
<path d="M67.7,198.8l8.4-1.9c1.5,10.4,8.7,16.6,20.4,16.6c10.5,0,18.8-4.9,18.8-12.9c0-5.7-4.2-10.5-20.6-15.4
|
||||
c-18.6-5.3-24.8-12.1-24.8-22.1c0-12.9,10.4-19.8,25.5-19.8c16.9,0,24.4,8.6,27,20.4l-8.4,1.9c-2.1-9.7-8.7-13.8-18.9-13.8
|
||||
c-9.6,0-16.4,3.6-16.4,10.5c0,5.6,4.4,9.9,19.6,14.7c18.1,5.6,25.9,11.7,25.9,23.3c0,14.4-12.1,21.9-27.5,21.9
|
||||
C80.6,222.1,69.6,213.8,67.7,198.8z"/>
|
||||
<path d="M134.5,182.9c0-22.3,14.6-39.7,37-39.7c22.3,0,36.7,17.5,36.7,39.7c0,11.1-3.7,20.7-9.9,27.7c3,3,5.9,6,8.8,9.2l-6.2,6
|
||||
c-3-3.2-6.1-6.4-9.2-9.5c-5.7,3.7-12.5,5.8-20.2,5.8C149.9,222.1,134.5,205.6,134.5,182.9z M185.2,209.9c-2.9-2.8-5.8-5.5-8.8-8.1
|
||||
l6-6.1c3.2,2.8,6.4,5.7,9.4,8.6c4.5-5.4,7.2-12.8,7.2-21.5c0-17.6-10.7-31-27.5-31s-27.6,13.4-27.6,31c0,18.1,11.7,30.8,27.6,30.8
|
||||
C176.6,213.6,181.2,212.4,185.2,209.9z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
3
packages/next-auth/provider-logos/freshbooks-dark.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox=".99522558 .9999996 253.69877442 253.6940004" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m107.948 1a106.948 106.948 0 0 0 -106.948 106.966v146.728h146.727c59.067 0 106.955-47.88 106.967-106.948v-146.746zm86.724 43.635a34.6 34.6 0 0 1 -10.164 24.51 34.768 34.768 0 0 1 -24.562 10.152h-37.242v29.73h50.314v34.796h-50.065v71.663h-41.233v-179.891h40.983v32.625c1.072-18.32 16.275-32.625 34.668-32.625h37.358z" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 467 B |
3
packages/next-auth/provider-logos/freshbooks.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox=".99522558 .9999996 253.69877442 253.6940004" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m107.948 1a106.948 106.948 0 0 0 -106.948 106.966v146.728h146.727c59.067 0 106.955-47.88 106.967-106.948v-146.746zm86.724 43.635a34.6 34.6 0 0 1 -10.164 24.51 34.768 34.768 0 0 1 -24.562 10.152h-37.242v29.73h50.314v34.796h-50.065v71.663h-41.233v-179.891h40.983v32.625c1.072-18.32 16.275-32.625 34.668-32.625h37.358z" fill="#0075dd"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 470 B |
4
packages/next-auth/provider-logos/github-dark.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub icon</title>
|
||||
<path fill="#fff" d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 859 B |
4
packages/next-auth/provider-logos/github.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub dark icon</title>
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 852 B |
8
packages/next-auth/provider-logos/gitlab-dark.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" viewBox="93.97 97.52 192.05 184.95">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#fff;}</style>
|
||||
</defs>
|
||||
<g id="LOGO">
|
||||
<path class="cls-1" d="M282.83,170.73l-.27-.69-26.14-68.22a6.81,6.81,0,0,0-2.69-3.24,7,7,0,0,0-8,.43,7,7,0,0,0-2.32,3.52l-17.65,54H154.29l-17.65-54A6.86,6.86,0,0,0,134.32,99a7,7,0,0,0-8-.43,6.87,6.87,0,0,0-2.69,3.24L97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82,19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91,40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 591 B |
11
packages/next-auth/provider-logos/gitlab.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg" viewBox="93.97 97.52 192.05 184.99">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style>
|
||||
</defs>
|
||||
<g>
|
||||
<path class="cls-1" d="M282.83,170.73l-.27-.69-26.14-68.22a6.81,6.81,0,0,0-2.69-3.24,7,7,0,0,0-8,.43,7,7,0,0,0-2.32,3.52l-17.65,54H154.29l-17.65-54A6.86,6.86,0,0,0,134.32,99a7,7,0,0,0-8-.43,6.87,6.87,0,0,0-2.69,3.24L97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82,19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91,40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/>
|
||||
<path class="cls-2" d="M282.83,170.73l-.27-.69a88.3,88.3,0,0,0-35.15,15.8L190,229.25c19.55,14.79,36.57,27.64,36.57,27.64l40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/>
|
||||
<path class="cls-3" d="M153.43,256.89l19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91S209.55,244,190,229.25C170.45,244,153.43,256.89,153.43,256.89Z"/>
|
||||
<path class="cls-2" d="M132.58,185.84A88.19,88.19,0,0,0,97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82s17-12.85,36.57-27.64Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
7
packages/next-auth/provider-logos/google.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="32" height="32" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Google icon</title>
|
||||
<path fill="#EA4335 " d="M5.26620003,9.76452941 C6.19878754,6.93863203 8.85444915,4.90909091 12,4.90909091 C13.6909091,4.90909091 15.2181818,5.50909091 16.4181818,6.49090909 L19.9090909,3 C17.7818182,1.14545455 15.0545455,0 12,0 C7.27006974,0 3.1977497,2.69829785 1.23999023,6.65002441 L5.26620003,9.76452941 Z"/>
|
||||
<path fill="#34A853" d="M16.0407269,18.0125889 C14.9509167,18.7163016 13.5660892,19.0909091 12,19.0909091 C8.86648613,19.0909091 6.21911939,17.076871 5.27698177,14.2678769 L1.23746264,17.3349879 C3.19279051,21.2936293 7.26500293,24 12,24 C14.9328362,24 17.7353462,22.9573905 19.834192,20.9995801 L16.0407269,18.0125889 Z"/>
|
||||
<path fill="#4A90E2" d="M19.834192,20.9995801 C22.0291676,18.9520994 23.4545455,15.903663 23.4545455,12 C23.4545455,11.2909091 23.3454545,10.5272727 23.1818182,9.81818182 L12,9.81818182 L12,14.4545455 L18.4363636,14.4545455 C18.1187732,16.013626 17.2662994,17.2212117 16.0407269,18.0125889 L19.834192,20.9995801 Z"/>
|
||||
<path fill="#FBBC05" d="M5.27698177,14.2678769 C5.03832634,13.556323 4.90909091,12.7937589 4.90909091,12 C4.90909091,11.2182781 5.03443647,10.4668121 5.26620003,9.76452941 L1.23999023,6.65002441 C0.43658717,8.26043162 0,10.0753848 0,12 C0,13.9195484 0.444780743,15.7301709 1.23746264,17.3349879 L5.27698177,14.2678769 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |