mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
4 Commits
@auth/core
...
feat/token
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6266aa461f | ||
|
|
c3110dc8dd | ||
|
|
c206959637 | ||
|
|
f0a1ffa551 |
2
.github/ISSUE_TEMPLATE/1_bug_framework.yml
vendored
2
.github/ISSUE_TEMPLATE/1_bug_framework.yml
vendored
@@ -11,7 +11,7 @@ body:
|
||||
|
||||
### Important :exclamation:
|
||||
|
||||
_Providing incorrect/insufficient information or skipping steps to reproduce the issue will result in closing the issue and/or converting to a discussion without further explanation._
|
||||
_Providing incorrect/insufficient information or skipping steps to reproduce the issue may result in closing the issue or converting to a discussion without further explanation._
|
||||
|
||||
If you have a generic question specific to your project, it is best asked in Discussions under the [Questions category](https://github.com/nextauthjs/next-auth/discussions/new?category=Questions)
|
||||
# Let's wait with this until adoption in other frameworks.
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/2_bug_provider.yml
vendored
3
.github/ISSUE_TEMPLATE/2_bug_provider.yml
vendored
@@ -31,12 +31,10 @@ body:
|
||||
- "Authentik"
|
||||
- "Azure Active Directory"
|
||||
- "Azure Active Directory B2C"
|
||||
- "Azure DevOps"
|
||||
- "Battlenet"
|
||||
- "Beyond Identity"
|
||||
- "Box"
|
||||
- "Bungie"
|
||||
- "ClickUp"
|
||||
- "Cognito"
|
||||
- "Coinbase"
|
||||
- "Descope"
|
||||
@@ -59,7 +57,6 @@ body:
|
||||
- "LinkedIn"
|
||||
- "Mailchimp"
|
||||
- "Mail.ru"
|
||||
- "Mastodon"
|
||||
- "Medium"
|
||||
- "Naver"
|
||||
- "Netlify"
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/3_bug_adapter.yml
vendored
1
.github/ISSUE_TEMPLATE/3_bug_adapter.yml
vendored
@@ -24,6 +24,7 @@ body:
|
||||
- "@auth/dgraph-adapter"
|
||||
- "@auth/drizzle-adapter"
|
||||
- "@auth/dynamodb-adapter"
|
||||
- "@auth/drizzle-adapter"
|
||||
- "@auth/fauna-adapter"
|
||||
- "@auth/firebase-adapter"
|
||||
- "@auth/kysely-adapter"
|
||||
|
||||
@@ -59,10 +59,6 @@ WIKIMEDIA_SECRET=
|
||||
YANDEX_ID=
|
||||
YANDEX_SECRET=
|
||||
|
||||
# ClickUp OAuth. https://clickup.com/api/
|
||||
CLICK_UP_ID=
|
||||
CLICK_UP_SECRET=
|
||||
|
||||
# Example configuration for a Gmail account (will need SMTP enabled)
|
||||
EMAIL_SERVER=smtps://user@gmail.com:password@smtp.gmail.com:465
|
||||
EMAIL_FROM=user@gmail.com
|
||||
|
||||
238
apps/dev/nextjs/lib/db.ts
Normal file
238
apps/dev/nextjs/lib/db.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
// Copy from RedisUpstashAdapter
|
||||
import type {
|
||||
Adapter,
|
||||
AdapterUser,
|
||||
AdapterAccount,
|
||||
AdapterSession,
|
||||
} from "@auth/core/adapters"
|
||||
|
||||
export interface AdapterOptions {
|
||||
/**
|
||||
* The base prefix for your keys
|
||||
*/
|
||||
baseKeyPrefix?: string
|
||||
/**
|
||||
* The prefix for the `account` key
|
||||
*/
|
||||
accountKeyPrefix?: string
|
||||
/**
|
||||
* The prefix for the `accountByUserId` key
|
||||
*/
|
||||
accountByUserIdPrefix?: string
|
||||
/**
|
||||
* The prefix for the `emailKey` key
|
||||
*/
|
||||
emailKeyPrefix?: string
|
||||
/**
|
||||
* The prefix for the `sessionKey` key
|
||||
*/
|
||||
sessionKeyPrefix?: string
|
||||
/**
|
||||
* The prefix for the `sessionByUserId` key
|
||||
*/
|
||||
sessionByUserIdKeyPrefix?: string
|
||||
/**
|
||||
* The prefix for the `user` key
|
||||
*/
|
||||
userKeyPrefix?: string
|
||||
/**
|
||||
* The prefix for the `verificationToken` key
|
||||
*/
|
||||
verificationTokenKeyPrefix?: string
|
||||
}
|
||||
|
||||
export const defaultOptions = {
|
||||
baseKeyPrefix: "",
|
||||
accountKeyPrefix: "user:account:",
|
||||
accountByUserIdPrefix: "user:account:by-user-id:",
|
||||
emailKeyPrefix: "user:email:",
|
||||
sessionKeyPrefix: "user:session:",
|
||||
sessionByUserIdKeyPrefix: "user:session:by-user-id:",
|
||||
userKeyPrefix: "user:",
|
||||
verificationTokenKeyPrefix: "user:token:",
|
||||
}
|
||||
|
||||
const isoDateRE =
|
||||
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
|
||||
function isDate(value: any) {
|
||||
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
|
||||
}
|
||||
|
||||
export function hydrateDates(text: string) {
|
||||
return Object.entries(JSON.parse(text)).reduce((acc, [key, val]) => {
|
||||
acc[key] = isDate(val) ? new Date(val as string) : val
|
||||
return acc
|
||||
}, {} as any)
|
||||
}
|
||||
|
||||
export function TestAdapter(
|
||||
client: {
|
||||
getItem: (key: string) => Promise<string | null>
|
||||
setItem: (key: string, value: string) => Promise<void>
|
||||
deleteItems: (...keys: string[]) => Promise<void>
|
||||
},
|
||||
options: AdapterOptions = {}
|
||||
): Adapter {
|
||||
const mergedOptions = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
}
|
||||
|
||||
const { baseKeyPrefix } = mergedOptions
|
||||
const accountKeyPrefix = baseKeyPrefix + mergedOptions.accountKeyPrefix
|
||||
const accountByUserIdPrefix =
|
||||
baseKeyPrefix + mergedOptions.accountByUserIdPrefix
|
||||
const emailKeyPrefix = baseKeyPrefix + mergedOptions.emailKeyPrefix
|
||||
const sessionKeyPrefix = baseKeyPrefix + mergedOptions.sessionKeyPrefix
|
||||
const sessionByUserIdKeyPrefix =
|
||||
baseKeyPrefix + mergedOptions.sessionByUserIdKeyPrefix
|
||||
const userKeyPrefix = baseKeyPrefix + mergedOptions.userKeyPrefix
|
||||
const verificationTokenKeyPrefix =
|
||||
baseKeyPrefix + mergedOptions.verificationTokenKeyPrefix
|
||||
|
||||
const setObjectAsJson = async (key: string, obj: any) =>
|
||||
await client.setItem(key, JSON.stringify(obj))
|
||||
|
||||
const setAccount = async (id: string, account: AdapterAccount) => {
|
||||
const accountKey = accountKeyPrefix + id
|
||||
await setObjectAsJson(accountKey, account)
|
||||
await client.setItem(accountByUserIdPrefix + account.userId, accountKey)
|
||||
return account
|
||||
}
|
||||
|
||||
const getAccount = async (id: string) => {
|
||||
const account = await client.getItem(accountKeyPrefix + id)
|
||||
if (!account) return null
|
||||
return hydrateDates(account)
|
||||
}
|
||||
|
||||
const setSession = async (
|
||||
id: string,
|
||||
session: AdapterSession
|
||||
): Promise<AdapterSession> => {
|
||||
const sessionKey = sessionKeyPrefix + id
|
||||
await setObjectAsJson(sessionKey, session)
|
||||
await client.setItem(sessionByUserIdKeyPrefix + session.userId, sessionKey)
|
||||
return session
|
||||
}
|
||||
|
||||
const getSession = async (id: string) => {
|
||||
const session = await client.getItem(sessionKeyPrefix + id)
|
||||
if (!session) return null
|
||||
return hydrateDates(session)
|
||||
}
|
||||
|
||||
const setUser = async (
|
||||
id: string,
|
||||
user: AdapterUser
|
||||
): Promise<AdapterUser> => {
|
||||
await setObjectAsJson(userKeyPrefix + id, user)
|
||||
await client.setItem(`${emailKeyPrefix}${user.email as string}`, id)
|
||||
return user
|
||||
}
|
||||
|
||||
const getUser = async (id: string) => {
|
||||
const user = await client.getItem(userKeyPrefix + id)
|
||||
if (!user) return null
|
||||
return hydrateDates(user)
|
||||
}
|
||||
|
||||
return {
|
||||
async createUser(user) {
|
||||
const id = crypto.randomUUID()
|
||||
// TypeScript thinks the emailVerified field is missing
|
||||
// but all fields are copied directly from user, so it's there
|
||||
return await setUser(id, { ...user, id })
|
||||
},
|
||||
getUser,
|
||||
async getUserByTokenId(email) {
|
||||
const userId = await client.getItem(emailKeyPrefix + email)
|
||||
if (!userId) {
|
||||
return null
|
||||
}
|
||||
return await getUser(userId)
|
||||
},
|
||||
async getUserByAccount(account) {
|
||||
const dbAccount = await getAccount(
|
||||
`${account.provider}:${account.providerAccountId}`
|
||||
)
|
||||
if (!dbAccount) return null
|
||||
return await getUser(dbAccount.userId)
|
||||
},
|
||||
async updateUser(updates) {
|
||||
const userId = updates.id as string
|
||||
const user = await getUser(userId)
|
||||
return await setUser(userId, { ...(user as AdapterUser), ...updates })
|
||||
},
|
||||
async linkAccount(account) {
|
||||
const id = `${account.provider}:${account.providerAccountId}`
|
||||
return await setAccount(id, { ...account, id })
|
||||
},
|
||||
createSession: (session) => setSession(session.sessionToken, session),
|
||||
async getSessionAndUser(sessionToken) {
|
||||
const session = await getSession(sessionToken)
|
||||
if (!session) return null
|
||||
const user = await getUser(session.userId)
|
||||
if (!user) return null
|
||||
return { session, user }
|
||||
},
|
||||
async updateSession(updates) {
|
||||
const session = await getSession(updates.sessionToken)
|
||||
if (!session) return null
|
||||
return await setSession(updates.sessionToken, { ...session, ...updates })
|
||||
},
|
||||
async deleteSession(sessionToken) {
|
||||
await client.deleteItems(sessionKeyPrefix + sessionToken)
|
||||
},
|
||||
async createVerificationToken(verificationToken) {
|
||||
await setObjectAsJson(
|
||||
verificationTokenKeyPrefix +
|
||||
verificationToken.identifier +
|
||||
":" +
|
||||
verificationToken.token,
|
||||
verificationToken
|
||||
)
|
||||
return verificationToken
|
||||
},
|
||||
async useVerificationToken(verificationToken) {
|
||||
const tokenKey =
|
||||
verificationTokenKeyPrefix +
|
||||
verificationToken.identifier +
|
||||
":" +
|
||||
verificationToken.token
|
||||
|
||||
const token = await client.getItem(tokenKey)
|
||||
if (!token) return null
|
||||
|
||||
await client.deleteItems(tokenKey)
|
||||
return hydrateDates(token)
|
||||
// return reviveFromJson(token)
|
||||
},
|
||||
async unlinkAccount(account) {
|
||||
const id = `${account.provider}:${account.providerAccountId}`
|
||||
const dbAccount = await getAccount(id)
|
||||
if (!dbAccount) return
|
||||
const accountKey = `${accountKeyPrefix}${id}`
|
||||
await client.deleteItems(
|
||||
accountKey,
|
||||
`${accountByUserIdPrefix} + ${dbAccount.userId as string}`
|
||||
)
|
||||
},
|
||||
async deleteUser(userId) {
|
||||
const user = await getUser(userId)
|
||||
if (!user) return
|
||||
const accountByUserKey = accountByUserIdPrefix + userId
|
||||
const accountKey = await client.getItem(accountByUserKey)
|
||||
const sessionByUserIdKey = sessionByUserIdKeyPrefix + userId
|
||||
const sessionKey = await client.getItem(sessionByUserIdKey)
|
||||
await client.deleteItems(
|
||||
userKeyPrefix + userId,
|
||||
`${emailKeyPrefix}${user.email as string}`,
|
||||
accountKey as string,
|
||||
accountByUserKey,
|
||||
sessionKey as string,
|
||||
sessionByUserIdKey
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import Credentials from "@auth/core/providers/credentials"
|
||||
import Descope from "@auth/core/providers/descope"
|
||||
import Discord from "@auth/core/providers/discord"
|
||||
import DuendeIDS6 from "@auth/core/providers/duende-identity-server6"
|
||||
// import Email from "@auth/core/providers/email"
|
||||
import SmtpEmail from "@auth/core/providers/email-smtp"
|
||||
import Facebook from "@auth/core/providers/facebook"
|
||||
import Foursquare from "@auth/core/providers/foursquare"
|
||||
import Freshbooks from "@auth/core/providers/freshbooks"
|
||||
@@ -39,7 +39,10 @@ import Yandex from "@auth/core/providers/yandex"
|
||||
import Vk from "@auth/core/providers/vk"
|
||||
import Wikimedia from "@auth/core/providers/wikimedia"
|
||||
import WorkOS from "@auth/core/providers/workos"
|
||||
import ClickUp from '@auth/core/providers/click-up'
|
||||
import { AdapterUser } from "next-auth/adapters"
|
||||
import Token from "@auth/core/providers/token"
|
||||
import { TestAdapter } from "lib/db"
|
||||
|
||||
// // Prisma
|
||||
// import { PrismaClient } from "@prisma/client"
|
||||
// import { PrismaAdapter } from "@auth/prisma-adapter"
|
||||
@@ -71,8 +74,22 @@ import ClickUp from '@auth/core/providers/click-up'
|
||||
// secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
|
||||
// })
|
||||
|
||||
const db = {}
|
||||
|
||||
export const authConfig: AuthConfig = {
|
||||
// adapter,
|
||||
adapter: TestAdapter({
|
||||
getItem(key) {
|
||||
return db[key]
|
||||
},
|
||||
setItem: function (key: string, value: string): Promise<void> {
|
||||
db[key] = value
|
||||
return Promise.resolve()
|
||||
},
|
||||
deleteItems: function (...keys: string[]): Promise<void> {
|
||||
keys.forEach((key) => delete db[key])
|
||||
return Promise.resolve()
|
||||
},
|
||||
}),
|
||||
debug: process.env.NODE_ENV !== "production",
|
||||
theme: {
|
||||
logo: "https://next-auth.js.org/img/logo/logo-sm.png",
|
||||
@@ -131,18 +148,25 @@ export const authConfig: AuthConfig = {
|
||||
Vk({ clientId: process.env.VK_ID, clientSecret: process.env.VK_SECRET }),
|
||||
Wikimedia({ clientId: process.env.WIKIMEDIA_ID, clientSecret: process.env.WIKIMEDIA_SECRET }),
|
||||
WorkOS({ clientId: process.env.WORKOS_ID, clientSecret: process.env.WORKOS_SECRET }),
|
||||
ClickUp({ clientId: process.env.CLICK_UP_ID, clientSecret: process.env.CLICK_UP_SECRET })
|
||||
],
|
||||
// debug: process.env.NODE_ENV !== "production",
|
||||
}
|
||||
|
||||
if (authConfig.adapter) {
|
||||
// TODO:
|
||||
// authOptions.providers.unshift(
|
||||
// // NOTE: You can start a fake e-mail server with `pnpm email`
|
||||
// // and then go to `http://localhost:1080` in the browser
|
||||
// Email({ server: "smtp://127.0.0.1:1025?tls.rejectUnauthorized=false" })
|
||||
// )
|
||||
authConfig.providers.unshift(
|
||||
// NOTE: You can start a fake e-mail server with `pnpm email`
|
||||
// and then go to `http://localhost:1080` in the browser
|
||||
// SmtpEmail({ server: "smtp://127.0.0.1:1025?tls.rejectUnauthorized=false" }),
|
||||
Token({
|
||||
id: "token",
|
||||
name: "Token",
|
||||
type: "token",
|
||||
async sendVerificationRequest(params) {
|
||||
console.log({ verificationUrl: params.url })
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: move to next-auth/edge
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"@sveltejs/kit": "next",
|
||||
"svelte": "3.55.0",
|
||||
"svelte-check": "2.10.2",
|
||||
"typescript": "5.2.2",
|
||||
"typescript": "4.9.4",
|
||||
"vite": "4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import NextAuth from "next-auth/next"
|
||||
import { config } from "auth"
|
||||
|
||||
const handler = NextAuth(config)
|
||||
export { handler as GET, handler as POST }
|
||||
@@ -1,294 +0,0 @@
|
||||
import type { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from "next"
|
||||
import type { NextAuthOptions as NextAuthConfig } from "next-auth"
|
||||
import { getServerSession } from "next-auth"
|
||||
|
||||
import Apple from "next-auth/providers/apple"
|
||||
import Atlassian from "next-auth/providers/atlassian"
|
||||
import Auth0 from "next-auth/providers/auth0"
|
||||
import Authentik from "next-auth/providers/authentik"
|
||||
import AzureAD from "next-auth/providers/azure-ad"
|
||||
import AzureB2C from "next-auth/providers/azure-ad-b2c"
|
||||
import Battlenet from "next-auth/providers/battlenet"
|
||||
import Box from "next-auth/providers/box"
|
||||
import BoxyHQSAML from "next-auth/providers/boxyhq-saml"
|
||||
import Bungie from "next-auth/providers/bungie"
|
||||
import Cognito from "next-auth/providers/cognito"
|
||||
import Coinbase from "next-auth/providers/coinbase"
|
||||
import Discord from "next-auth/providers/discord"
|
||||
import Dropbox from "next-auth/providers/dropbox"
|
||||
import DuendeIDS6 from "next-auth/providers/duende-identity-server6"
|
||||
import Eveonline from "next-auth/providers/eveonline"
|
||||
import Facebook from "next-auth/providers/facebook"
|
||||
import Faceit from "next-auth/providers/faceit"
|
||||
import FortyTwoSchool from "next-auth/providers/42-school"
|
||||
import Foursquare from "next-auth/providers/foursquare"
|
||||
import Freshbooks from "next-auth/providers/freshbooks"
|
||||
import Fusionauth from "next-auth/providers/fusionauth"
|
||||
import GitHub from "next-auth/providers/github"
|
||||
import Gitlab from "next-auth/providers/gitlab"
|
||||
import Google from "next-auth/providers/google"
|
||||
import Hubspot from "next-auth/providers/hubspot"
|
||||
import Instagram from "next-auth/providers/instagram"
|
||||
import Kakao from "next-auth/providers/kakao"
|
||||
import Keycloak from "next-auth/providers/keycloak"
|
||||
import Line from "next-auth/providers/line"
|
||||
import LinkedIn from "next-auth/providers/linkedin"
|
||||
import Mailchimp from "next-auth/providers/mailchimp"
|
||||
import Mailru from "next-auth/providers/mailru"
|
||||
import Medium from "next-auth/providers/medium"
|
||||
import Naver from "next-auth/providers/naver"
|
||||
import Netlify from "next-auth/providers/netlify"
|
||||
import Okta from "next-auth/providers/okta"
|
||||
import Onelogin from "next-auth/providers/onelogin"
|
||||
import Osso from "next-auth/providers/osso"
|
||||
import Osu from "next-auth/providers/osu"
|
||||
import Passage from "next-auth/providers/passage"
|
||||
import Patreon from "next-auth/providers/patreon"
|
||||
import Pinterest from "next-auth/providers/pinterest"
|
||||
import Pipedrive from "next-auth/providers/pipedrive"
|
||||
import Reddit from "next-auth/providers/reddit"
|
||||
import Salesforce from "next-auth/providers/salesforce"
|
||||
import Slack from "next-auth/providers/slack"
|
||||
import Spotify from "next-auth/providers/spotify"
|
||||
import Strava from "next-auth/providers/strava"
|
||||
import Todoist from "next-auth/providers/todoist"
|
||||
import Trakt from "next-auth/providers/trakt"
|
||||
import Twitch from "next-auth/providers/twitch"
|
||||
import Twitter from "next-auth/providers/twitter"
|
||||
import UnitedEffects from "next-auth/providers/united-effects"
|
||||
import Vk from "next-auth/providers/vk"
|
||||
import Wikimedia from "next-auth/providers/wikimedia"
|
||||
import Wordpress from "next-auth/providers/wordpress"
|
||||
import WorkOS from "next-auth/providers/workos"
|
||||
import Yandex from "next-auth/providers/yandex"
|
||||
import Zitadel from "next-auth/providers/zitadel"
|
||||
import Zoho from "next-auth/providers/zoho"
|
||||
import Zoom from "next-auth/providers/zoom"
|
||||
|
||||
// Read more at: https://next-auth.js.org/getting-started/typescript#module-augmentation
|
||||
declare module "next-auth/jwt" {
|
||||
interface JWT {
|
||||
/** The user's role. */
|
||||
userRole?: "admin"
|
||||
}
|
||||
}
|
||||
|
||||
export const config = {
|
||||
// https://next-auth.js.org/configuration/providers/oauth
|
||||
providers: [
|
||||
Apple({ clientId: process.env.AUTH_APPLE_ID, clientSecret: process.env.AUTH_APPLE_SECRET }),
|
||||
Atlassian({ clientId: process.env.AUTH_ATLASSIAN_ID, clientSecret: process.env.AUTH_ATLASSIAN_SECRET }),
|
||||
Auth0({ clientId: process.env.AUTH_AUTH0_ID, clientSecret: process.env.AUTH_AUTH0_SECRET, issuer: process.env.AUTH_AUTH0_ISSUER }),
|
||||
Authentik({ clientId: process.env.AUTH_AUTHENTIK_ID, clientSecret: process.env.AUTH_AUTHENTIK_SECRET }),
|
||||
AzureAD({ clientId: process.env.AUTH_AZUREAD_ID, clientSecret: process.env.AUTH_AZUREAD_SECRET }),
|
||||
AzureB2C({ clientId: process.env.AUTH_AZUREB2C_ID, clientSecret: process.env.AUTH_AZUREB2C_SECRET }),
|
||||
Battlenet({ clientId: process.env.AUTH_BN_ID, clientSecret: process.env.AUTH_BN_SECRET, issuer: process.env.AUTH_BN_ISSUER }),
|
||||
Box({ clientId: process.env.AUTH_BOX_ID, clientSecret: process.env.AUTH_BOX_SECRET }),
|
||||
BoxyHQSAML({ clientId: process.env.AUTH_BOXYHQ_ID, clientSecret: process.env.AUTH_BOXYHQ_SECRET, issuer: process.env.AUTH_BOXYHQ_ISSUER }),
|
||||
Bungie({ clientId: process.env.AUTH_BUNGIE_ID, clientSecret: process.env.AUTH_BUNGIE_SECRET }),
|
||||
Cognito({ clientId: process.env.AUTH_COGNITO_ID, clientSecret: process.env.AUTH_COGNITO_SECRET }),
|
||||
Coinbase({ clientId: process.env.AUTH_COINBASE_ID, clientSecret: process.env.AUTH_COINBASE_SECRET }),
|
||||
Discord({ clientId: process.env.AUTH_DISCORD_ID, clientSecret: process.env.AUTH_DISCORD_SECRET }),
|
||||
Dropbox({ clientId: process.env.AUTH_DROPBOX_ID, clientSecret: process.env.AUTH_DROPBOX_SECRET }),
|
||||
DuendeIDS6({ clientId: process.env.AUTH_DUENDEIDS6_ID, clientSecret: process.env.AUTH_DUENDEIDS6_SECRET }),
|
||||
Eveonline({ clientId: process.env.AUTH_EVEONLINE_ID, clientSecret: process.env.AUTH_EVEONLINE_SECRET }),
|
||||
Facebook({ clientId: process.env.AUTH_FACEBOOK_ID, clientSecret: process.env.AUTH_FACEBOOK_SECRET }),
|
||||
Faceit({ clientId: process.env.AUTH_FACEIT_ID, clientSecret: process.env.AUTH_FACEIT_SECRET }),
|
||||
FortyTwoSchool({ clientId: process.env.AUTH_FORTYTWOSCHOOL_ID, clientSecret: process.env.AUTH_FORTYTWOSCHOOL_SECRET }),
|
||||
Foursquare({ clientId: process.env.AUTH_FOURSQUARE_ID, clientSecret: process.env.AUTH_FOURSQUARE_SECRET }),
|
||||
Freshbooks({ clientId: process.env.AUTH_FRESHBOOKS_ID, clientSecret: process.env.AUTH_FRESHBOOKS_SECRET }),
|
||||
Fusionauth({ clientId: process.env.AUTH_FUSIONAUTH_ID, clientSecret: process.env.AUTH_FUSIONAUTH_SECRET }),
|
||||
GitHub({ clientId: process.env.AUTH_GITHUB_ID, clientSecret: process.env.AUTH_GITHUB_SECRET }),
|
||||
Gitlab({ clientId: process.env.AUTH_GITLAB_ID, clientSecret: process.env.AUTH_GITLAB_SECRET }),
|
||||
Google({ clientId: process.env.AUTH_GOOGLE_ID, clientSecret: process.env.AUTH_GOOGLE_SECRET }),
|
||||
Hubspot({ clientId: process.env.AUTH_HUBSPOT_ID, clientSecret: process.env.AUTH_HUBSPOT_SECRET }),
|
||||
Instagram({ clientId: process.env.AUTH_INSTAGRAM_ID, clientSecret: process.env.AUTH_INSTAGRAM_SECRET }),
|
||||
Kakao({ clientId: process.env.AUTH_KAKAO_ID, clientSecret: process.env.AUTH_KAKAO_SECRET }),
|
||||
Keycloak({ clientId: process.env.AUTH_KEYCLOAK_ID, clientSecret: process.env.AUTH_KEYCLOAK_SECRET }),
|
||||
Line({ clientId: process.env.AUTH_LINE_ID, clientSecret: process.env.AUTH_LINE_SECRET }),
|
||||
LinkedIn({ clientId: process.env.AUTH_LINKEDIN_ID, clientSecret: process.env.AUTH_LINKEDIN_SECRET }),
|
||||
Mailchimp({ clientId: process.env.AUTH_MAILCHIMP_ID, clientSecret: process.env.AUTH_MAILCHIMP_SECRET }),
|
||||
Mailru({ clientId: process.env.AUTH_MAILRU_ID, clientSecret: process.env.AUTH_MAILRU_SECRET }),
|
||||
Medium({ clientId: process.env.AUTH_MEDIUM_ID, clientSecret: process.env.AUTH_MEDIUM_SECRET }),
|
||||
Naver({ clientId: process.env.AUTH_NAVER_ID, clientSecret: process.env.AUTH_NAVER_SECRET }),
|
||||
Netlify({ clientId: process.env.AUTH_NETLIFY_ID, clientSecret: process.env.AUTH_NETLIFY_SECRET }),
|
||||
Okta({ clientId: process.env.AUTH_OKTA_ID, clientSecret: process.env.AUTH_OKTA_SECRET }),
|
||||
Onelogin({ clientId: process.env.AUTH_ONELOGIN_ID, clientSecret: process.env.AUTH_ONELOGIN_SECRET }),
|
||||
Osso({ clientId: process.env.AUTH_OSSO_ID, clientSecret: process.env.AUTH_OSSO_SECRET, issuer: process.env.AUTH_OSSO_ISSUER }),
|
||||
Osu({ clientId: process.env.AUTH_OSU_ID, clientSecret: process.env.AUTH_OSU_SECRET }),
|
||||
Passage({ clientId: process.env.AUTH_PASSAGE_ID, clientSecret: process.env.AUTH_PASSAGE_SECRET, issuer: process.env.AUTH_PASSAGE_ISSUER }),
|
||||
Patreon({ clientId: process.env.AUTH_PATREON_ID, clientSecret: process.env.AUTH_PATREON_SECRET }),
|
||||
Pinterest({ clientId: process.env.AUTH_PINTEREST_ID, clientSecret: process.env.AUTH_PINTEREST_SECRET }),
|
||||
Pipedrive({ clientId: process.env.AUTH_PIPEDRIVE_ID, clientSecret: process.env.AUTH_PIPEDRIVE_SECRET }),
|
||||
Reddit({ clientId: process.env.AUTH_REDDIT_ID, clientSecret: process.env.AUTH_REDDIT_SECRET }),
|
||||
Salesforce({ clientId: process.env.AUTH_SALESFORCE_ID, clientSecret: process.env.AUTH_SALESFORCE_SECRET }),
|
||||
Slack({ clientId: process.env.AUTH_SLACK_ID, clientSecret: process.env.AUTH_SLACK_SECRET }),
|
||||
Spotify({ clientId: process.env.AUTH_SPOTIFY_ID, clientSecret: process.env.AUTH_SPOTIFY_SECRET }),
|
||||
Strava({ clientId: process.env.AUTH_STRAVA_ID, clientSecret: process.env.AUTH_STRAVA_SECRET }),
|
||||
Todoist({ clientId: process.env.AUTH_TODOIST_ID, clientSecret: process.env.AUTH_TODOIST_SECRET }),
|
||||
Trakt({ clientId: process.env.AUTH_TRAKT_ID, clientSecret: process.env.AUTH_TRAKT_SECRET }),
|
||||
Twitch({ clientId: process.env.AUTH_TWITCH_ID, clientSecret: process.env.AUTH_TWITCH_SECRET }),
|
||||
Twitter({ clientId: process.env.AUTH_TWITTER_ID, clientSecret: process.env.AUTH_TWITTER_SECRET, version: "2.0" }),
|
||||
UnitedEffects({ clientId: process.env.AUTH_UE_ID, clientSecret: process.env.AUTH_UE_SECRET, issuer: process.env.AUTH_UE_ISSUER }),
|
||||
Vk({ clientId: process.env.AUTH_VK_ID, clientSecret: process.env.AUTH_VK_SECRET }),
|
||||
Wikimedia({ clientId: process.env.AUTH_WIKIMEDIA_ID, clientSecret: process.env.AUTH_WIKIMEDIA_SECRET }),
|
||||
Wordpress({ clientId: process.env.AUTH_WORDPRESS_ID, clientSecret: process.env.AUTH_WORDPRESS_SECRET }),
|
||||
WorkOS({ clientId: process.env.AUTH_WORKOS_ID, clientSecret: process.env.AUTH_WORKOS_SECRET }),
|
||||
Yandex({ clientId: process.env.AUTH_YANDEX_ID, clientSecret: process.env.AUTH_YANDEX_SECRET }),
|
||||
Zitadel({ clientId: process.env.AUTH_ZITADEL_ID, clientSecret: process.env.AUTH_ZITADEL_SECRET }),
|
||||
Zoho({ clientId: process.env.AUTH_ZOHO_ID, clientSecret: process.env.AUTH_ZOHO_SECRET }),
|
||||
Zoom({ clientId: process.env.AUTH_ZOOM_ID, clientSecret: process.env.AUTH_ZOOM_SECRET }),
|
||||
],
|
||||
callbacks: {
|
||||
async jwt({ token }) {
|
||||
token.userRole = "admin"
|
||||
return token
|
||||
},
|
||||
},
|
||||
} satisfies NextAuthConfig
|
||||
|
||||
// Helper function to get session without passing config every time
|
||||
// https://next-auth.js.org/configuration/nextjs#getserversession
|
||||
export function auth(...args: [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]] | [NextApiRequest, NextApiResponse] | []) {
|
||||
return getServerSession(...args, config)
|
||||
}
|
||||
|
||||
// We recommend doing your own environment variable validation
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
export interface ProcessEnv {
|
||||
NEXTAUTH_SECRET: string
|
||||
|
||||
AUTH_APPLE_ID: string
|
||||
AUTH_APPLE_SECRET: string
|
||||
AUTH_ATLASSIAN_ID: string
|
||||
AUTH_ATLASSIAN_SECRET: string
|
||||
AUTH_AUTH0_ID: string
|
||||
AUTH_AUTH0_ISSUER: string
|
||||
AUTH_AUTH0_SECRET: string
|
||||
AUTH_AUTHENTIK_ID: string
|
||||
AUTH_AUTHENTIK_SECRET: string
|
||||
AUTH_AZUREAD_ID: string
|
||||
AUTH_AZUREAD_SECRET: string
|
||||
AUTH_AZUREB2C_ID: string
|
||||
AUTH_AZUREB2C_SECRET: string
|
||||
AUTH_BN_ID: string
|
||||
AUTH_BN_ISSUER: any
|
||||
AUTH_BN_SECRET: string
|
||||
AUTH_BOX_ID: string
|
||||
AUTH_BOX_SECRET: string
|
||||
AUTH_BOXYHQ_ID: string
|
||||
AUTH_BOXYHQ_ISSUER: string
|
||||
AUTH_BOXYHQ_SECRET: string
|
||||
AUTH_BUNGIE_ID: string
|
||||
AUTH_BUNGIE_SECRET: string
|
||||
AUTH_COGNITO_ID: string
|
||||
AUTH_COGNITO_SECRET: string
|
||||
AUTH_COINBASE_ID: string
|
||||
AUTH_COINBASE_SECRET: string
|
||||
AUTH_DISCORD_ID: string
|
||||
AUTH_DISCORD_SECRET: string
|
||||
AUTH_DROPBOX_ID: string
|
||||
AUTH_DROPBOX_SECRET: string
|
||||
AUTH_DUENDEIDS6_ID: string
|
||||
AUTH_DUENDEIDS6_SECRET: string
|
||||
AUTH_EVEONLINE_ID: string
|
||||
AUTH_EVEONLINE_SECRET: string
|
||||
AUTH_FACEBOOK_ID: string
|
||||
AUTH_FACEBOOK_SECRET: string
|
||||
AUTH_FACEIT_ID: string
|
||||
AUTH_FACEIT_SECRET: string
|
||||
AUTH_FORTYTWOSCHOOL_ID: string
|
||||
AUTH_FORTYTWOSCHOOL_SECRET: string
|
||||
AUTH_FOURSQUARE_ID: string
|
||||
AUTH_FOURSQUARE_SECRET: string
|
||||
AUTH_FRESHBOOKS_ID: string
|
||||
AUTH_FRESHBOOKS_SECRET: string
|
||||
AUTH_FUSIONAUTH_ID: string
|
||||
AUTH_FUSIONAUTH_SECRET: string
|
||||
AUTH_GITHUB_ID: string
|
||||
AUTH_GITHUB_SECRET: string
|
||||
AUTH_GITLAB_ID: string
|
||||
AUTH_GITLAB_SECRET: string
|
||||
AUTH_GOOGLE_ID: string
|
||||
AUTH_GOOGLE_SECRET: string
|
||||
AUTH_HUBSPOT_ID: string
|
||||
AUTH_HUBSPOT_SECRET: string
|
||||
AUTH_INSTAGRAM_ID: string
|
||||
AUTH_INSTAGRAM_SECRET: string
|
||||
AUTH_KAKAO_ID: string
|
||||
AUTH_KAKAO_SECRET: string
|
||||
AUTH_KEYCLOAK_ID: string
|
||||
AUTH_KEYCLOAK_SECRET: string
|
||||
AUTH_LINE_ID: string
|
||||
AUTH_LINE_SECRET: string
|
||||
AUTH_LINKEDIN_ID: string
|
||||
AUTH_LINKEDIN_SECRET: string
|
||||
AUTH_MAILCHIMP_ID: string
|
||||
AUTH_MAILCHIMP_SECRET: string
|
||||
AUTH_MAILRU_ID: string
|
||||
AUTH_MAILRU_SECRET: string
|
||||
AUTH_MEDIUM_ID: string
|
||||
AUTH_MEDIUM_SECRET: string
|
||||
AUTH_NAVER_ID: string
|
||||
AUTH_NAVER_SECRET: string
|
||||
AUTH_NETLIFY_ID: string
|
||||
AUTH_NETLIFY_SECRET: string
|
||||
AUTH_OKTA_ID: string
|
||||
AUTH_OKTA_SECRET: string
|
||||
AUTH_ONELOGIN_ID: string
|
||||
AUTH_ONELOGIN_SECRET: string
|
||||
AUTH_OSSO_ID: string
|
||||
AUTH_OSSO_ISSUER: string
|
||||
AUTH_OSSO_SECRET: string
|
||||
AUTH_OSU_ID: string
|
||||
AUTH_OSU_SECRET: string
|
||||
AUTH_PASSAGE_ID: string
|
||||
AUTH_PASSAGE_ISSUER: string
|
||||
AUTH_PASSAGE_SECRET: string
|
||||
AUTH_PATREON_ID: string
|
||||
AUTH_PATREON_SECRET: string
|
||||
AUTH_PINTEREST_ID: string
|
||||
AUTH_PINTEREST_SECRET: string
|
||||
AUTH_PIPEDRIVE_ID: string
|
||||
AUTH_PIPEDRIVE_SECRET: string
|
||||
AUTH_REDDIT_ID: string
|
||||
AUTH_REDDIT_SECRET: string
|
||||
AUTH_SALESFORCE_ID: string
|
||||
AUTH_SALESFORCE_SECRET: string
|
||||
AUTH_SLACK_ID: string
|
||||
AUTH_SLACK_SECRET: string
|
||||
AUTH_SPOTIFY_ID: string
|
||||
AUTH_SPOTIFY_SECRET: string
|
||||
AUTH_STRAVA_ID: string
|
||||
AUTH_STRAVA_SECRET: string
|
||||
AUTH_TODOIST_ID: string
|
||||
AUTH_TODOIST_SECRET: string
|
||||
AUTH_TRAKT_ID: string
|
||||
AUTH_TRAKT_SECRET: string
|
||||
AUTH_TWITCH_ID: string
|
||||
AUTH_TWITCH_SECRET: string
|
||||
AUTH_TWITTER_ID: string
|
||||
AUTH_TWITTER_SECRET: string
|
||||
AUTH_UE_ID: string
|
||||
AUTH_UE_ISSUER: string
|
||||
AUTH_UE_SECRET: string
|
||||
AUTH_VK_ID: string
|
||||
AUTH_VK_SECRET: string
|
||||
AUTH_WIKIMEDIA_ID: string
|
||||
AUTH_WIKIMEDIA_SECRET: string
|
||||
AUTH_WORDPRESS_ID: string
|
||||
AUTH_WORDPRESS_SECRET: string
|
||||
AUTH_WORKOS_ID: string
|
||||
AUTH_WORKOS_SECRET: string
|
||||
AUTH_YANDEX_ID: string
|
||||
AUTH_YANDEX_SECRET: string
|
||||
AUTH_ZITADEL_ID: string
|
||||
AUTH_ZITADEL_SECRET: string
|
||||
AUTH_ZOHO_ID: string
|
||||
AUTH_ZOHO_SECRET: string
|
||||
AUTH_ZOOM_ID: string
|
||||
AUTH_ZOOM_SECRET: string
|
||||
}
|
||||
}
|
||||
}
|
||||
10
apps/examples/nextjs/next-auth.d.ts
vendored
Normal file
10
apps/examples/nextjs/next-auth.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import "next-auth/jwt"
|
||||
|
||||
// Read more at: https://next-auth.js.org/getting-started/typescript#module-augmentation
|
||||
|
||||
declare module "next-auth/jwt" {
|
||||
interface JWT {
|
||||
/** The user's role. */
|
||||
userRole?: "admin"
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,6 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.16.2",
|
||||
"@types/react": "^18.2.0",
|
||||
"typescript": "5.2.2"
|
||||
"typescript": "^5.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
44
apps/examples/nextjs/pages/api/auth/[...nextauth].ts
Normal file
44
apps/examples/nextjs/pages/api/auth/[...nextauth].ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import NextAuth, { NextAuthOptions } from "next-auth"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
import FacebookProvider from "next-auth/providers/facebook"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
import TwitterProvider from "next-auth/providers/twitter"
|
||||
import Auth0Provider from "next-auth/providers/auth0"
|
||||
|
||||
// For more information on each option (and a full list of options) go to
|
||||
// https://next-auth.js.org/configuration/options
|
||||
export const authOptions: NextAuthOptions = {
|
||||
// https://next-auth.js.org/configuration/providers/oauth
|
||||
providers: [
|
||||
Auth0Provider({
|
||||
clientId: process.env.AUTH0_ID,
|
||||
clientSecret: process.env.AUTH0_SECRET,
|
||||
issuer: process.env.AUTH0_ISSUER,
|
||||
}),
|
||||
FacebookProvider({
|
||||
clientId: process.env.FACEBOOK_ID,
|
||||
clientSecret: process.env.FACEBOOK_SECRET,
|
||||
}),
|
||||
GithubProvider({
|
||||
clientId: process.env.GITHUB_ID,
|
||||
clientSecret: process.env.GITHUB_SECRET,
|
||||
}),
|
||||
GoogleProvider({
|
||||
clientId: process.env.GOOGLE_ID,
|
||||
clientSecret: process.env.GOOGLE_SECRET,
|
||||
}),
|
||||
TwitterProvider({
|
||||
clientId: process.env.TWITTER_ID,
|
||||
clientSecret: process.env.TWITTER_SECRET,
|
||||
version: "2.0",
|
||||
}),
|
||||
],
|
||||
callbacks: {
|
||||
async jwt({ token }) {
|
||||
token.userRole = "admin"
|
||||
return token
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default NextAuth(authOptions)
|
||||
@@ -1,13 +1,14 @@
|
||||
// This is an example of to protect an API route
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
import { auth } from "auth"
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await auth(req, res)
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
|
||||
if (session) {
|
||||
return res.send({
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// This is an example of how to access a session from an API route
|
||||
import { getServerSession } from "next-auth"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
import { auth } from "auth"
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await auth(req, res)
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
res.send(JSON.stringify(session, null, 2))
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { auth } from "auth"
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "./api/auth/[...nextauth]"
|
||||
import Layout from "../components/layout"
|
||||
|
||||
import type { GetServerSidePropsContext } from "next"
|
||||
@@ -35,5 +36,9 @@ export default function ServerSidePage() {
|
||||
|
||||
// Export the `session` prop to use sessions with Server Side Rendering
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
return { props: { session: await auth(context.req, context.res) } }
|
||||
return {
|
||||
props: {
|
||||
session: await getServerSession(context.req, context.res, authOptions),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
18
apps/examples/nextjs/process.d.ts
vendored
Normal file
18
apps/examples/nextjs/process.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
declare namespace NodeJS {
|
||||
export interface ProcessEnv {
|
||||
NEXTAUTH_URL: string
|
||||
NEXTAUTH_SECRET: string
|
||||
GITHUB_ID: string
|
||||
GITHUB_SECRET: string
|
||||
FACEBOOK_ID: string
|
||||
FACEBOOK_SECRET: string
|
||||
TWITTER_ID: string
|
||||
TWITTER_SECRET: string
|
||||
GOOGLE_ID: string
|
||||
GOOGLE_SECRET: string
|
||||
AUTH0_ID: string
|
||||
AUTH0_SECRET: string
|
||||
DESCOPE_ID: string
|
||||
DESCOPE_SECRET: string
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
@@ -17,22 +13,14 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
"incremental": true
|
||||
},
|
||||
"include": [
|
||||
"process.d.ts",
|
||||
"next-env.d.ts",
|
||||
"next-auth.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
"**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"solid-start-node": "^0.2.9",
|
||||
"solid-start-vercel": "^0.2.9",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "5.2.2",
|
||||
"typescript": "^4.8.3",
|
||||
"vite": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"@sveltejs/kit": "next",
|
||||
"svelte": "3.55.0",
|
||||
"svelte-check": "2.10.2",
|
||||
"typescript": "5.2.2",
|
||||
"typescript": "4.9.4",
|
||||
"vite": "4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
title: Credentials authentication
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
|
||||
Auth.js is built in a way that is flexible to integrate it with any authentication back-end you or your company may already have.
|
||||
|
||||
This library has been designed to handle the user session client-wise, to support multiple authentication methods (OAuth, Email, etc...) so that you're not forced to run your own authentication service.
|
||||
@@ -19,49 +16,34 @@ The functionality provided for credentials based authentication is intentionally
|
||||
|
||||
Integrating the Credentials Provider is as simple as initializing it in the Auth.js configuration file:
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
import CredentialsProvider from "next-auth/providers/credentials"
|
||||
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
import CredentialsProvider from "next-auth/providers/credentials"
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
async authorize(credentials) {
|
||||
const authResponse = await fetch("/users/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
})
|
||||
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
async authorize(credentials) {
|
||||
const authResponse = await fetch("/users/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
})
|
||||
if (!authResponse.ok) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (!authResponse.ok) {
|
||||
return null
|
||||
}
|
||||
const user = await authResponse.json()
|
||||
|
||||
const user = await authResponse.json()
|
||||
|
||||
return user
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
return user
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
:::note
|
||||
Check the [Credentials Provider options](/reference/core/providers_credentials) for further customization
|
||||
|
||||
@@ -7,8 +7,6 @@ import startPageImg from "./img/email-tutorial-start.png"
|
||||
import checkPageImg from "./img/email-tutorial-check.png"
|
||||
import mailboxImg from "./img/email-tutorial-mailbox.png"
|
||||
import loggedInImg from "./img/email-tutorial-logged.png"
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
|
||||
Aside from authenticating users in Auth.js via [OAuth](/getting-started/oauth-tutorial), you can also enable the option to authenticate them via "magic links". These are links that are sent to the user's email and when clicking on them they'll sign up the user automatically.
|
||||
|
||||
@@ -66,43 +64,26 @@ Note that we're also specifying from which domain email are going to be sent fro
|
||||
|
||||
Nice! We're getting there. Now we need to read supply this values as the configuration for our Email Provider. Open `pages/api/auth/[...nextauth].ts` and do the following:
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
import Email from "next-auth/providers/email"
|
||||
|
||||
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
import Email from "next-auth/providers/email"
|
||||
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
Email({
|
||||
server: {
|
||||
host: process.env.SMTP_HOST,
|
||||
port: Number(process.env.SMTP_PORT),
|
||||
auth: {
|
||||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PASSWORD,
|
||||
},
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
Email({
|
||||
server: {
|
||||
host: process.env.SMTP_HOST,
|
||||
port: Number(process.env.SMTP_PORT),
|
||||
auth: {
|
||||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PASSWORD,
|
||||
},
|
||||
from: process.env.EMAIL_FROM,
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
},
|
||||
from: process.env.EMAIL_FROM,
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## 3. Setting up an adapter
|
||||
|
||||
@@ -158,46 +139,30 @@ export default clientPromise
|
||||
|
||||
And now let's reference this new adapter from our Auth.js configuration file:
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
```diff title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
import EmailProvider from "next-auth/providers/email"
|
||||
+ import { MongoDBAdapter } from "@auth/mongodb-adapter"
|
||||
+ import clientPromise from "../../../lib/mongodb/client"
|
||||
|
||||
export default NextAuth({
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
+ adapter: MongoDBAdapter(clientPromise),
|
||||
providers: [
|
||||
EmailProvider({
|
||||
server: {
|
||||
host: process.env.EMAIL_SERVER_HOST,
|
||||
port: process.env.EMAIL_SERVER_PORT,
|
||||
auth: {
|
||||
user: process.env.EMAIL_SERVER_USER,
|
||||
pass: process.env.EMAIL_SERVER_PASSWORD
|
||||
}
|
||||
},
|
||||
from: process.env.EMAIL_FROM
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
```diff title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
import EmailProvider from "next-auth/providers/email"
|
||||
+ import { MongoDBAdapter } from "@auth/mongodb-adapter"
|
||||
+ import clientPromise from "../../../lib/mongodb/client"
|
||||
|
||||
export default NextAuth({
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
+ adapter: MongoDBAdapter(clientPromise),
|
||||
providers: [
|
||||
EmailProvider({
|
||||
server: {
|
||||
host: process.env.EMAIL_SERVER_HOST,
|
||||
port: process.env.EMAIL_SERVER_PORT,
|
||||
auth: {
|
||||
user: process.env.EMAIL_SERVER_USER,
|
||||
pass: process.env.EMAIL_SERVER_PASSWORD
|
||||
}
|
||||
},
|
||||
from: process.env.EMAIL_FROM
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
## 4. Wiring all together
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ NextAuth.js provides [`useSession()`](/reference/react/#usesession) - a [React H
|
||||
|
||||
```ts title="pages/_app.tsx"
|
||||
import { SessionProvider } from "next-auth/react"
|
||||
import type { AppProps } from "next/app"
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
export default function App({
|
||||
Component,
|
||||
@@ -182,127 +182,7 @@ export default async function listMovies(req, res) {
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
|
||||
:::warning
|
||||
`@auth/sveltekit` is currently experimental. The API _will_ change in the future.
|
||||
:::
|
||||
|
||||
### Prerequisites
|
||||
|
||||
This tutorial assumes you have a SvelteKit application set up. If you don't, you can follow the [SvelteKit tutorial](https://kit.svelte.dev/docs/creating-a-project) to get started.
|
||||
|
||||
### Installing Auth.js
|
||||
|
||||
```bash npm2yarn
|
||||
npm install @auth/core @auth/sveltekit
|
||||
```
|
||||
|
||||
### Create server hook
|
||||
|
||||
Create the following [Server hook](https://kit.svelte.dev/docs/hooks) file. This route contains the necessary configuration for Auth.js, as well as the dynamic route handler:
|
||||
|
||||
```ts title="src/hooks.server.ts"
|
||||
import { SvelteKitAuth } from "@auth/sveltekit"
|
||||
import GitHub from "@auth/core/providers/github"
|
||||
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private"
|
||||
*
|
||||
export const handle = SvelteKitAuth({
|
||||
providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],
|
||||
})
|
||||
```
|
||||
|
||||
:::info
|
||||
|
||||
Behind the scenes, this creates all the relevant OAuth API routes within `/api/auth/*` so that auth API requests to:
|
||||
|
||||
- [GET `/api/auth/signin`](https://authjs.dev/reference/rest-api#get--apiauthsignin)
|
||||
- [POST `/api/auth/signin/:provider`](https://authjs.dev/reference/rest-api#post--apiauthsigninprovider)
|
||||
- [GET/POST `/api/auth/callback/:provider`](https://authjs.dev/reference/rest-api#get--post--apiauthcallbackprovider)
|
||||
- [GET `/api/auth/signout`](https://authjs.dev/reference/rest-api#get--apiauthsignout)
|
||||
- [POST `/api/auth/signout`](https://authjs.dev/reference/rest-api#post--apiauthsignout)
|
||||
- [GET `/api/auth/session`](https://authjs.dev/reference/rest-api#get--apiauthsession)
|
||||
- [GET `/api/auth/csrf`](https://authjs.dev/reference/rest-api#get--apiauthcsrf)
|
||||
- [GET `/api/auth/providers`](https://authjs.dev/reference/rest-api#get--apiauthproviders)
|
||||
|
||||
can be handled by Auth.js. In this way, Auth.js stays in charge of the whole application's authentication request/response flow.
|
||||
|
||||
Auth.js is fully customizable - [our guides section](/guides/overview) teaches you how to set it up to handle auth in different ways. All the possible configuration options are [listed here](/reference/configuration/auth-config).
|
||||
:::
|
||||
|
||||
### Adding environment variables
|
||||
|
||||
You may notice we are using environment variables in the code example above. We take the value of `GITHUB_ID` and `GITHUB_SECRET` from the GitHub Developer OAuth Portal. See [Configuring OAuth Provider](/getting-started/oauth-tutorial#2-configuring-oauth-provider) section on how to get those.
|
||||
|
||||
In your project root, create a `.env.local` file and add the `AUTH_SECRET` environment variable:
|
||||
|
||||
```title=".env.local"
|
||||
AUTH_SECRET="This is an example"
|
||||
```
|
||||
|
||||
`AUTH_SECRET` is a random string used by the library to encrypt tokens and email verification hashes, and **it's mandatory to keep things secure**! 🔥 🔐 . You can use:
|
||||
|
||||
```
|
||||
$ openssl rand -base64 32
|
||||
```
|
||||
|
||||
or https://generate-secret.vercel.app/32 to generate a random value for it.
|
||||
|
||||
### Exposing the session via page store
|
||||
|
||||
Auth.js provides us a getSession, function to access the session data and status, to call from the `event.locals` variable. We can now just call it and add it to our `$page` store.
|
||||
|
||||
```ts
|
||||
import type { LayoutServerLoad } from './$types';
|
||||
*
|
||||
export const load: LayoutServerLoad = async (event) => {
|
||||
return {
|
||||
session: await event.locals.getSession()
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Consuming the session via page store
|
||||
|
||||
You can use the `$page.data.session` variable from anywhere on your page. Learn more about SvelteKit's page store in the [SvelteKit docs](https://learn.svelte.dev/tutorial/page-store).
|
||||
|
||||
```ts title="route/+page.svelte"
|
||||
<script>
|
||||
import { signIn, signOut } from '@auth/sveltekit/client'
|
||||
import { page } from '$app/stores'
|
||||
</script>
|
||||
|
||||
{#if $page.data.session?.user}
|
||||
<p>Signed in as {$page.data.session.user.email}</p>
|
||||
<button on:click={signOut}>Sign out</button>
|
||||
<img src="https://cdn.pixabay.com/photo/2017/08/11/19/36/vw-2632486_1280.png" />
|
||||
{:else}
|
||||
<p>Not signed in.</p>
|
||||
<button on:click={() => signIn('github')}>Sign in</button>
|
||||
{/if}
|
||||
```
|
||||
|
||||
### Protecting API Routes
|
||||
|
||||
To protect your API Routes (blocking unauthorized access to resources), you can use `locals.getSessions()` just like in the layouts file to know whether a session exists or not:
|
||||
|
||||
```ts title="routes/api/movies/+server.ts"
|
||||
import { json, error } from "@sveltejs/kit";
|
||||
import type { RequestEvent } from "./$types";
|
||||
|
||||
export async function GET({ locals }: RequestEvent) {
|
||||
const session = await locals.getSession()
|
||||
if (!session?.user) {
|
||||
throw error(401, "You must sign in to view movies.");
|
||||
}
|
||||
|
||||
return json({
|
||||
movies: [
|
||||
{ title: "Alien vs Predator", id: 1 },
|
||||
{ title: "Reservoir Dogs", id: 2 },
|
||||
]
|
||||
})
|
||||
}
|
||||
```
|
||||
TODO: SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO: SolidStart
|
||||
@@ -338,7 +218,7 @@ The callback URL we insert should have the following pattern:
|
||||
|
||||
In this case, given we want to try our authentication working locally on our machine and we're using **GitHub** as our OAuth provider, it'll be:
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<Tabs groupId="frameworks">
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
```
|
||||
@@ -394,7 +274,7 @@ Note that, for each provider, the configuration process will be similar to what
|
||||
2. Create create your OAuth application within it
|
||||
3. Set the callback URL
|
||||
4. Get the Client ID and Generate a Client Secret
|
||||
:::
|
||||
:::
|
||||
|
||||
## 3. Wiring all together
|
||||
|
||||
@@ -409,7 +289,7 @@ GITHUB_SECRET=67890
|
||||
|
||||
Here is our server configuration file again:
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<Tabs groupId="frameworks">
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
@@ -434,24 +314,7 @@ $ npm run next dev
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
|
||||
```ts title="src/hooks.server.ts"
|
||||
import { SvelteKitAuth } from "@auth/sveltekit"
|
||||
import GitHub from "@auth/core/providers/github"
|
||||
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private"
|
||||
*
|
||||
export const handle = SvelteKitAuth({
|
||||
providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],
|
||||
})
|
||||
```
|
||||
|
||||
Great! We're now ready to run our application locally. Start the Svelte app by running on your terminal the following command and navigating to [`http://localhost:5173`](http://localhost:5173):
|
||||
|
||||
```
|
||||
$ npm run vite dev
|
||||
```
|
||||
|
||||
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
|
||||
@@ -9,9 +9,6 @@ https://github.com/nextauthjs/next-auth-example
|
||||
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
|
||||
## Adapters
|
||||
|
||||
If you're writing your own custom Adapter, you can take advantage of the types to make sure your implementation conforms to what's expected:
|
||||
@@ -49,45 +46,30 @@ This will work in code editors with a strong TypeScript integration like VSCode
|
||||
|
||||
Let's look at `Session`:
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
```ts title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
export default NextAuth({
|
||||
callbacks: {
|
||||
session({ session, token, user }) {
|
||||
return session // The return type will match the one returned in `useSession()`
|
||||
},
|
||||
export default NextAuth({
|
||||
callbacks: {
|
||||
session({ session, token, user }) {
|
||||
return session // The return type will match the one returned in `useSession()`
|
||||
},
|
||||
})
|
||||
```
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
```ts title="pages/index.ts"
|
||||
import { useSession } from "next-auth/react"
|
||||
```ts title="pages/index.ts"
|
||||
import { useSession } from "next-auth/react"
|
||||
|
||||
export default function IndexPage() {
|
||||
// `session` will match the returned value of `callbacks.session()` from `NextAuth()`
|
||||
const { data: session } = useSession()
|
||||
export default function IndexPage() {
|
||||
// `session` will match the returned value of `callbacks.session()` from `NextAuth()`
|
||||
const { data: session } = useSession()
|
||||
|
||||
return (
|
||||
// Your component
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
return (
|
||||
// Your component
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
To extend/augment this type, create a `types/next-auth.d.ts` file in your project:
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ An **Adapter** in Auth.js connects your application to whatever database or back
|
||||
When using a database, you can still use JWT for session handling for fast access. See the [`session.strategy`](/reference/configuration/auth-config#session) option. Read about the trade-offs of JWT in the [FAQ](/concepts/faq#json-web-tokens).
|
||||
:::
|
||||
|
||||
We have a list of official adapters that are distributed as their own packages under the `@auth/{name}-adapter` namespace. Their source code is available in their various adapters package directories at [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth/tree/main/packages):
|
||||
We have a list of official adapters that are distributed as their own packages under the `@next-auth/{name}-adapter` namespace. Their source code is available in their various adapters package directories at [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth/tree/main/packages):
|
||||
|
||||
- [All available adapters](/reference/adapters)
|
||||
|
||||
@@ -12,7 +12,7 @@ If you want to pass data such as an Access Token or User ID to the browser when
|
||||
|
||||
You can specify a handler for any of the callbacks below.
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"s
|
||||
callbacks: {
|
||||
async signIn({ user, account, profile, email, credentials }) {
|
||||
return true
|
||||
@@ -35,7 +35,7 @@ The documentation below shows how to implement each callback, their default beha
|
||||
|
||||
Use the `signIn()` callback to control if a user is allowed to sign in.
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
callbacks: {
|
||||
async signIn({ user, account, profile, email, credentials }) {
|
||||
const isAllowedToSignIn = true
|
||||
@@ -79,7 +79,7 @@ By default only URLs on the same URL as the site are allowed, you can use the re
|
||||
|
||||
The default redirect callback looks like this:
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
callbacks: {
|
||||
async redirect({ url, baseUrl }) {
|
||||
// Allows relative callback URLs
|
||||
@@ -107,7 +107,7 @@ Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`,
|
||||
|
||||
The contents _user_, _account_, _profile_ and _isNewUser_ will vary depending on the provider and on if you are using a database or not. You can persist data such as User ID, OAuth Access Token in this token. To make it available in the browser, check out the [`session()` callback](#session-callback) as well.
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
callbacks: {
|
||||
async jwt({ token, account }) {
|
||||
// Persist the OAuth access_token to the token right after signin
|
||||
@@ -132,7 +132,7 @@ e.g. `getSession()`, `useSession()`, `/api/auth/session`
|
||||
- When using database sessions, the User object is passed as an argument.
|
||||
- When using JSON Web Tokens for sessions, the JWT payload is provided instead.
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
callbacks: {
|
||||
async session({ session, token, user }) {
|
||||
// Send properties to the client, like an access_token from a provider.
|
||||
|
||||
@@ -2,14 +2,6 @@
|
||||
title: Custom Initialization
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
|
||||
In Next.js, you can define an API route that will catch all requests that begin with a certain path. Conveniently, this is called [Catch all API routes](https://nextjs.org/docs/api-routes/dynamic-api-routes#catch-all-api-routes).
|
||||
|
||||
When you define a `/pages/api/auth/[...nextauth]` JS/TS file, you instruct Auth.js that every API request beginning with `/api/auth/*` should be handled by the code written in the `[...nextauth]` file.
|
||||
@@ -128,15 +120,3 @@ This way of initializing `NextAuth` is very powerful, but should be used sparing
|
||||
:::warning
|
||||
Changing parts of the request that is essential to `NextAuth` to do it's job - like messing with the [default cookies](/reference/configuration/auth-config#cookies) - can have unforeseen consequences, and have the potential to introduce security holes if done incorrectly. Only change those if you understand consequences.
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -2,16 +2,13 @@
|
||||
title: Pages
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
|
||||
Auth.js automatically creates simple, unbranded authentication pages for handling Sign in, Sign out, Email Verification and displaying error messages.
|
||||
|
||||
The options displayed on the sign-up page are automatically generated based on the providers specified in the options passed to Auth.js.
|
||||
|
||||
To add a custom login page, you can use the `pages` option:
|
||||
|
||||
```javascript title="auth.js"
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
...
|
||||
pages: {
|
||||
signIn: '/auth/signin',
|
||||
@@ -79,11 +76,6 @@ In addition, you can define the background color and text color of the button wi
|
||||
|
||||
In order to get the available authentication providers and the URLs to use for them, you can make a request to the API endpoint `/api/auth/providers`:
|
||||
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
|
||||
```jsx title="pages/auth/signin.js"
|
||||
import { getProviders, signIn } from "next-auth/react"
|
||||
|
||||
@@ -108,18 +100,6 @@ export async function getServerSideProps(context) {
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
There is another, more fully styled example signin page available [here](https://github.com/ndom91/next-auth-example-sign-in-page).
|
||||
|
||||
@@ -127,10 +107,6 @@ There is another, more fully styled example signin page available [here](https:/
|
||||
|
||||
If you create a custom sign in form for email sign in, you will need to submit both fields for the **email** address and **csrfToken** from **/api/auth/csrf** in a POST request to **/api/auth/signin/email**.
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
|
||||
```jsx title="pages/auth/email-signin.js"
|
||||
import { getCsrfToken } from "next-auth/react"
|
||||
|
||||
@@ -155,18 +131,6 @@ export async function getServerSideProps(context) {
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
You can also use the `signIn()` function which will handle obtaining the CSRF token for you:
|
||||
|
||||
```js
|
||||
@@ -177,10 +141,6 @@ signIn("email", { email: "jsmith@example.com" })
|
||||
|
||||
If you create a sign in form for credentials based authentication, you will need to pass a **csrfToken** from **/api/auth/csrf** in a `POST` request to **/api/auth/callback/credentials**.
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js" default>
|
||||
|
||||
|
||||
```jsx title="pages/auth/credentials-signin.js"
|
||||
import { getCsrfToken } from "next-auth/react"
|
||||
|
||||
@@ -210,18 +170,6 @@ export async function getServerSideProps(context) {
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)">
|
||||
TODO Core
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
You can also use the `signIn()` function which will handle obtaining the CSRF token for you:
|
||||
|
||||
```js
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
title: Refresh token rotation
|
||||
---
|
||||
|
||||
import Tabs from "@theme/Tabs"
|
||||
import TabItem from "@theme/TabItem"
|
||||
|
||||
Refresh token rotation is the practice of updating an `access_token` on behalf of the user, without requiring interaction (eg.: re-sign in). `access_token`s are usually issued for a limited time. After they expire, the service verifying them will ignore the value. Instead of asking the user to sign in again to obtain a new `access_token`, certain providers support exchanging a `refresh_token` for a new `access_token`, renewing the expiry time. Let's see how this can be achieved.
|
||||
|
||||
:::note
|
||||
@@ -29,20 +26,6 @@ Using the [jwt](../../reference/core/types#jwt) and [session](../../reference/co
|
||||
|
||||
Below is a sample implementation using Google's Identity Provider. Please note that the OAuth 2.0 request in the `refreshAccessToken()` function will vary between different providers, but the core logic should remain similar.
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js">
|
||||
|
||||
TODO Next.js
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)" default>
|
||||
|
||||
```ts
|
||||
import { Auth } from "@auth/core"
|
||||
import { type TokenSet } from "@auth/core/types"
|
||||
@@ -126,27 +109,10 @@ declare module "@auth/core/jwt" {
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
#### Database strategy
|
||||
|
||||
Using the database strategy is very similar, but instead of preserving the `access_token` and `refresh_token`, we save it, well, in the database.
|
||||
|
||||
<Tabs groupId="frameworks" queryString>
|
||||
<TabItem value="next" label="Next.js">
|
||||
|
||||
What
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="sveltekit" label="SvelteKit">
|
||||
TODO SvelteKit
|
||||
</TabItem>
|
||||
<TabItem value="solidstart" label="SolidStart">
|
||||
TODO SolidStart
|
||||
</TabItem>
|
||||
<TabItem value="core" label="Vanilla (No Framework)" default>
|
||||
|
||||
```ts
|
||||
import { Auth } from "@auth/core"
|
||||
import { type TokenSet } from "@auth/core/types"
|
||||
@@ -229,8 +195,6 @@ declare module "@auth/core/jwt" {
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Client Side
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ This can be done by simply returning a `200` response on `HEAD` requests at the
|
||||
|
||||
For example
|
||||
|
||||
```jsx title="auth.js"
|
||||
```jsx title="/pages/api/auth/[...nextauth].js"
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
import NextAuth from "next-auth"
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ index 77161bd..1082fba 100644
|
||||
|
||||
var _openidClient = require("openid-client");
|
||||
|
||||
+import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
+var HttpsProxyAgent = require("https-proxy-agent");
|
||||
+
|
||||
async function openidClient(options) {
|
||||
const provider = options.provider;
|
||||
|
||||
@@ -7,7 +7,11 @@ The Credentials provider allows you to handle signing in with arbitrary credenti
|
||||
|
||||
It is intended to support use cases where you have an existing system you need to authenticate users against.
|
||||
|
||||
It comes with the constraint that users authenticated in this manner are not persisted in the database by default, and consequently, that the Credentials provider can only be used if JSON Web Tokens are enabled for sessions.
|
||||
It comes with the constraint that users authenticated in this manner are not persisted in the database, and consequently that the Credentials provider can only be used if JSON Web Tokens are enabled for sessions.
|
||||
|
||||
:::warning
|
||||
The functionality provided for credentials-based authentication is intentionally limited to discourage the use of passwords due to the inherent security risks associated with them and the additional complexity associated with supporting usernames and passwords.
|
||||
:::
|
||||
|
||||
## Options
|
||||
|
||||
@@ -19,33 +23,19 @@ You can override any of the options to suit your own use case.
|
||||
|
||||
## Example - Username / Password
|
||||
|
||||
:::caution
|
||||
The functionality provided for credentials-based authentication is intentionally limited to discourage the use of passwords due to the inherent security risks of the username-password model.
|
||||
The Credentials provider is specified like other providers, except that you need to define a handler for `authorize()` that accepts credentials submitted via HTTP POST as input and returns either:
|
||||
|
||||
OAuth providers spend significant amounts of money, time, and engineering effort to build:
|
||||
1. A `user` object, which indicates the credentials are valid.
|
||||
|
||||
- bot-protection
|
||||
- rate-limiting
|
||||
- password management
|
||||
- data security
|
||||
If you return an object it will be persisted to the JSON Web Token and the user will be signed in, unless a custom `signIn()` callback is configured that subsequently rejects it.
|
||||
|
||||
and much more for authentication solutions. It is likely that your application would benefit from leveraging these battle-tested solutions rather than try to rebuild them from scratch.
|
||||
2. If you return `null` then an error will be displayed advising the user to check their details.
|
||||
|
||||
If you'd still like to build password-based authentication for your application despite these risks, Auth.js gives you full control to do so.
|
||||
3. If you throw an Error, the user will be sent to the error page with the error message as a query parameter.
|
||||
|
||||
:::
|
||||
The Credentials provider's `authorize()` method also provides the request object as the second parameter (see the example below).
|
||||
|
||||
The Credentials provider is specified like other providers, except that you need to define a handler for `authorize()` that accepts credentials submitted via HTTP POST as input and returns a `user` object, which indicates the credentials are valid.
|
||||
|
||||
If you return an object it will be persisted to the JSON Web Token and the user will be signed in (unless a custom `signIn()` callback is configured that subsequently rejects it).
|
||||
|
||||
- If you return `null` then an error will be displayed advising the user to check their details.
|
||||
|
||||
- If you throw an Error, the user will be sent to the error page with the error message as a query parameter.
|
||||
|
||||
The Credentials provider's `authorize()` method also provides the request object as the second parameter. Here's an example that handles these concerns.
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import CredentialsProvider from "next-auth/providers/credentials";
|
||||
...
|
||||
providers: [
|
||||
@@ -79,50 +69,7 @@ providers: [
|
||||
...
|
||||
```
|
||||
|
||||
See the [callbacks documentation](/reference/configuration/auth-config#callbacks) for more information on how to interact with the token. For example, you can add additional information to the token by returning an object from the `jwt()` callback:
|
||||
|
||||
```js
|
||||
callbacks: {
|
||||
async jwt(token, user, account, profile, isNewUser) {
|
||||
if (user) {
|
||||
token.id = user.id
|
||||
}
|
||||
return token
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using a database
|
||||
|
||||
You can also use the `authorize()` callback to interact with your database to regain some of the functionality from [more powerful providers](reference/core/providers):
|
||||
|
||||
```js
|
||||
...
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
...
|
||||
async authorize(credentials, req) {
|
||||
let user = null
|
||||
|
||||
const saltedPasswordToCheck = passwordToSalt(credentials.password)
|
||||
user = await getUserFromDb(credentials.username, credentials.password)
|
||||
|
||||
if (!user) {
|
||||
const saltedPassword = passwordToSalt(credentials.password)
|
||||
user = await addUserToDb(credentials.username, saltedPassword)
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
throw new Error("User was not found and could not be created.")
|
||||
}
|
||||
|
||||
return user
|
||||
|
||||
}
|
||||
})
|
||||
]
|
||||
...
|
||||
```
|
||||
See the [callbacks documentation](/reference/configuration/auth-config#callbacks) for more information on how to interact with the token.
|
||||
|
||||
## Example - Web3 / Signin With Ethereum
|
||||
|
||||
@@ -131,8 +78,8 @@ The credentials provider can also be used to integrate with a service like [Sign
|
||||
For more information, check out the links below:
|
||||
|
||||
- [Tutorial](https://docs.login.xyz/integrations/Auth.js)
|
||||
- [Example App Repo](https://github.com/spruceid/siwe-next-auth-example)
|
||||
- [Example App Demo](https://siwe-next-auth-example2.vercel.app/)
|
||||
- [Example App Repo](https://github.com/spruceid/siwe-next-auth-example).
|
||||
- [Example App Demo](https://siwe-next-auth-example2.vercel.app/).
|
||||
|
||||
## Multiple providers
|
||||
|
||||
|
||||
@@ -17,15 +17,15 @@ We will also refer to the [Prisma Adapter](/reference/adapter/prisma). A [databa
|
||||
|
||||
## Setup
|
||||
|
||||
First, if you do not have a project using Auth.js, clone and set up a basic Auth.js project like the one [provided in our example repo](https://github.com/nextauthjs/next-auth-example).
|
||||
First, if you do not have a project using Auth.js, clone and set up a basic Auth.js project like the one [provided in](https://github.com/nextauthjs/next-auth-example.git) our example repo](https://github.com/nextauthjs/next-auth-example.git).
|
||||
|
||||
- Install the [Prisma Adapter](/reference/adapter/prisma)
|
||||
- Generate an API key from your cloud Email provider of choice and add it to your `.env.*` file. For example, mine is going to be called `SENDGRID_API`
|
||||
- Add the following configuration to your configuration file:
|
||||
|
||||
```js title="auth.ts"
|
||||
```js title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth, { NextAuthOptions } from "next-auth"
|
||||
import { PrismaAdapter } from "@auth/prisma-adapter"
|
||||
import { PrismaAdapter } from "@next-auth/prisma-adapter"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
@@ -42,15 +42,16 @@ export const authOptions: NextAuthOptions = {
|
||||
],
|
||||
}
|
||||
|
||||
export default NextAuth(authOptions)
|
||||
```
|
||||
|
||||
Next, all that's left to do is call the HTTP endpoint from our cloud email provider and pass it the required metadata like the `to` address, the email `body`, and any other fields we may need to include.
|
||||
|
||||
As mentioned earlier, we're going to be using SendGrid in this example, so the appropriate endpoint is `https://api.sendgrid.com/v3/mail/send` ([more info](https://docs.sendgrid.com/for-developers/sending-email/api-getting-started)). Therefore, we're going to pull out some of the important information from the `params` argument and use it in a `fetch()` call to the previously mentioned SendGrid API.
|
||||
|
||||
```js title="auth.ts"
|
||||
```js title="pages/api/auth/[...nextauth].ts"
|
||||
import NextAuth, { NextAuthOptions } from "next-auth"
|
||||
import { PrismaAdapter } from "@auth/prisma-adapter"
|
||||
import { PrismaAdapter } from "@next-auth/prisma-adapter"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
@@ -46,7 +46,7 @@ Create an `.env` file to the root of your project and add the connection string
|
||||
|
||||
Now you can add the email provider like this:
|
||||
|
||||
```js {3} title="auth.js"
|
||||
```js {3} title="pages/api/auth/[...nextauth].js"
|
||||
import EmailProvider from "next-auth/providers/email";
|
||||
...
|
||||
providers: [
|
||||
@@ -71,7 +71,7 @@ EMAIL_FROM=noreply@example.com
|
||||
|
||||
Now you can add the provider settings to the NextAuth options object in the Email Provider.
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import EmailProvider from "next-auth/providers/email";
|
||||
...
|
||||
providers: [
|
||||
@@ -101,7 +101,7 @@ You can fully customize the sign in email that is sent by passing a custom funct
|
||||
|
||||
e.g.
|
||||
|
||||
```js {3} title="auth.js"
|
||||
```js {3} title="pages/api/auth/[...nextauth].js"
|
||||
import EmailProvider from "next-auth/providers/email";
|
||||
...
|
||||
providers: [
|
||||
@@ -206,7 +206,7 @@ If you want to generate great looking email client compatible HTML with React, c
|
||||
|
||||
By default, we are generating a random verification token. You can define a `generateVerificationToken` method in your provider options if you want to override it:
|
||||
|
||||
```js title="auth.js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
providers: [
|
||||
EmailProvider({
|
||||
async generateVerificationToken() {
|
||||
|
||||
@@ -213,25 +213,7 @@ const docusaurusConfig = {
|
||||
breadcrumbs: false,
|
||||
routeBasePath: "/",
|
||||
sidebarPath: require.resolve("./sidebars.js"),
|
||||
/**
|
||||
*
|
||||
* @param {{
|
||||
* version: string;
|
||||
* versionDocsDirPath: string;
|
||||
* docPath: string;
|
||||
* permalink: string;
|
||||
* locale: string;
|
||||
*}} params
|
||||
*/
|
||||
editUrl({ docPath }) {
|
||||
// TODO: support other packages, fix directory links like "providers"
|
||||
if (docPath.includes("reference/core")) {
|
||||
const file = docPath.split("reference/core/")[1].replace(".md", ".ts").replace("_", "/")
|
||||
const base = `https://github.com/nextauthjs/next-auth/edit/main/packages/core/src/${file}`
|
||||
return base
|
||||
}
|
||||
return "https://github.com/nextauthjs/next-auth/edit/main/docs"
|
||||
},
|
||||
editUrl: "https://github.com/nextauthjs/next-auth/edit/main/docs",
|
||||
lastVersion: "current",
|
||||
showLastUpdateAuthor: true,
|
||||
showLastUpdateTime: true,
|
||||
|
||||
@@ -27,15 +27,15 @@
|
||||
"styled-components": "5.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/core": "2.4.1",
|
||||
"@docusaurus/eslint-plugin": "2.4.1",
|
||||
"@docusaurus/module-type-aliases": "2.4.1",
|
||||
"@docusaurus/preset-classic": "2.4.1",
|
||||
"@docusaurus/theme-common": "2.4.1",
|
||||
"@docusaurus/theme-mermaid": "2.4.1",
|
||||
"@docusaurus/types": "2.4.1",
|
||||
"@docusaurus/core": "2.3.1",
|
||||
"@docusaurus/eslint-plugin": "2.3.1",
|
||||
"@docusaurus/module-type-aliases": "2.3.1",
|
||||
"@docusaurus/preset-classic": "2.3.1",
|
||||
"@docusaurus/theme-common": "2.3.1",
|
||||
"@docusaurus/theme-mermaid": "2.3.1",
|
||||
"@docusaurus/types": "2.3.1",
|
||||
"docusaurus-plugin-typedoc": "1.0.0-next.5",
|
||||
"typedoc": "^0.24.8",
|
||||
"typedoc": "^0.24.4",
|
||||
"typedoc-plugin-markdown": "4.0.0-next.6"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
27
docs/static/img/providers/click-up.svg
vendored
27
docs/static/img/providers/click-up.svg
vendored
@@ -1,27 +0,0 @@
|
||||
<svg width="185" height="185" viewBox="0 0 185 185" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d)">
|
||||
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
|
||||
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M55.8789 105.714L69.3974 95.3593C76.5762 104.732 84.1998 109.051 92.6948 109.051C101.143 109.051 108.557 104.781 115.414 95.4832L129.119 105.59C119.232 118.996 106.932 126.079 92.6948 126.079C78.5049 126.079 66.0907 119.046 55.8789 105.714Z" fill="url(#paint0_linear)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M92.6491 60.7078L68.5883 81.4406L57.4727 68.5407L92.6969 38.1885L127.647 68.5644L116.477 81.417L92.6491 60.7078Z" fill="url(#paint1_linear)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d" x="0" y="0" width="185" height="185" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dy="10"/>
|
||||
<feGaussianBlur stdDeviation="15"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.117647 0 0 0 0 0.211765 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear" x1="55.8789" y1="116.251" x2="129.119" y2="116.251" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#8930FD"/>
|
||||
<stop offset="1" stop-color="#49CCF9"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="57.4727" y1="67.6025" x2="127.647" y2="67.6025" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF02F0"/>
|
||||
<stop offset="1" stop-color="#FFC800"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
10
docs/static/img/providers/mastodon.svg
vendored
10
docs/static/img/providers/mastodon.svg
vendored
@@ -1,10 +0,0 @@
|
||||
<svg width="75" height="79" viewBox="0 0 75 79" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M73.8393 17.4898C72.6973 9.00165 65.2994 2.31235 56.5296 1.01614C55.05 0.797115 49.4441 0 36.4582 0H36.3612C23.3717 0 20.585 0.797115 19.1054 1.01614C10.5798 2.27644 2.79399 8.28712 0.904997 16.8758C-0.00358524 21.1056 -0.100549 25.7949 0.0682394 30.0965C0.308852 36.2651 0.355538 42.423 0.91577 48.5665C1.30307 52.6474 1.97872 56.6957 2.93763 60.6812C4.73325 68.042 12.0019 74.1676 19.1233 76.6666C26.7478 79.2728 34.9474 79.7055 42.8039 77.9162C43.6682 77.7151 44.5217 77.4817 45.3645 77.216C47.275 76.6092 49.5123 75.9305 51.1571 74.7385C51.1797 74.7217 51.1982 74.7001 51.2112 74.6753C51.2243 74.6504 51.2316 74.6229 51.2325 74.5948V68.6416C51.2321 68.6154 51.2259 68.5896 51.2142 68.5661C51.2025 68.5426 51.1858 68.522 51.1651 68.5058C51.1444 68.4896 51.1204 68.4783 51.0948 68.4726C51.0692 68.4669 51.0426 68.467 51.0171 68.4729C45.9835 69.675 40.8254 70.2777 35.6502 70.2682C26.7439 70.2682 24.3486 66.042 23.6626 64.2826C23.1113 62.762 22.7612 61.1759 22.6212 59.5646C22.6197 59.5375 22.6247 59.5105 22.6357 59.4857C22.6466 59.4609 22.6633 59.4391 22.6843 59.422C22.7053 59.4048 22.73 59.3929 22.7565 59.3871C22.783 59.3813 22.8104 59.3818 22.8367 59.3886C27.7864 60.5826 32.8604 61.1853 37.9522 61.1839C39.1768 61.1839 40.3978 61.1839 41.6224 61.1516C46.7435 61.008 52.1411 60.7459 57.1796 59.7621C57.3053 59.7369 57.431 59.7154 57.5387 59.6831C65.4861 58.157 73.0493 53.3672 73.8178 41.2381C73.8465 40.7606 73.9184 36.2364 73.9184 35.7409C73.9219 34.0569 74.4606 23.7949 73.8393 17.4898Z" fill="url(#paint0_linear_549_34)"/>
|
||||
<path d="M61.2484 27.0263V48.114H52.8916V27.6475C52.8916 23.3388 51.096 21.1413 47.4437 21.1413C43.4287 21.1413 41.4177 23.7409 41.4177 28.8755V40.0782H33.1111V28.8755C33.1111 23.7409 31.0965 21.1413 27.0815 21.1413C23.4507 21.1413 21.6371 23.3388 21.6371 27.6475V48.114H13.2839V27.0263C13.2839 22.7176 14.384 19.2946 16.5843 16.7572C18.8539 14.2258 21.8311 12.926 25.5264 12.926C29.8036 12.926 33.0357 14.5705 35.1905 17.8559L37.2698 21.346L39.3527 17.8559C41.5074 14.5705 44.7395 12.926 49.0095 12.926C52.7013 12.926 55.6784 14.2258 57.9553 16.7572C60.1531 19.2922 61.2508 22.7152 61.2484 27.0263Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_549_34" x1="37.0692" y1="0" x2="37.0692" y2="79" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6364FF"/>
|
||||
<stop offset="1" stop-color="#563ACC"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"build:app": "turbo run build --filter=next-auth-app",
|
||||
"build:docs": "turbo run build --filter=docs",
|
||||
"build": "turbo run build --filter=next-auth --filter=@auth/* --no-deps",
|
||||
"build": "turbo run build --filter=next-auth --filter=@next-auth/* --filter=@auth/* --no-deps",
|
||||
"test": "turbo run test --concurrency=1 --filter=[HEAD^1] --filter=./packages/* --filter=!@*upstash* --filter=!*dynamodb-* --filter=!*app*",
|
||||
"clean": "turbo run clean --no-cache",
|
||||
"dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...",
|
||||
@@ -44,12 +44,12 @@
|
||||
"prettier": "2.8.1",
|
||||
"prettier-plugin-svelte": "^2.8.1",
|
||||
"turbo": "^1.10.12",
|
||||
"typescript": "5.2.2"
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13.0 || ^18.12.0"
|
||||
},
|
||||
"packageManager": "pnpm@8.7.1",
|
||||
"packageManager": "pnpm@7.23.0",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -249,7 +249,6 @@
|
||||
{
|
||||
"files": [
|
||||
"apps/dev/nextjs/pages/api/auth/[...nextauth].ts",
|
||||
"apps/examples/nextjs/auth.ts",
|
||||
"docs/{sidebars,docusaurus.config}.js"
|
||||
],
|
||||
"options": {
|
||||
|
||||
@@ -41,13 +41,13 @@
|
||||
"test": "./tests/test.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/node-fetch": "^2.5.11",
|
||||
"jest": "^27.4.3",
|
||||
"ts-jest": "^27.0.3",
|
||||
"typescript": "5.2.2",
|
||||
"undici": "5.22.1"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -55,6 +55,6 @@
|
||||
"jsonwebtoken": "^8.5.1"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,7 +313,7 @@ export function DgraphAdapter(
|
||||
|
||||
return format.from<any>(result)
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const [user] = await c.run<any>(
|
||||
/* GraphQL */ `
|
||||
query ($email: String = "") {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DgraphAdapter, format } from "../src"
|
||||
import { client as dgraphClient } from "../src/lib/client"
|
||||
import * as fragments from "../src/lib/graphql/fragments"
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/better-sqlite3": "^7.6.4",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"better-sqlite3": "^8.4.0",
|
||||
@@ -60,6 +60,6 @@
|
||||
"postgres": "^3.3.4"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ export function mySqlDrizzleAdapter(
|
||||
|
||||
return thing
|
||||
},
|
||||
async getUserByEmail(data) {
|
||||
async getUserByTokenId(data) {
|
||||
const user =
|
||||
(await client
|
||||
.select()
|
||||
|
||||
@@ -89,7 +89,7 @@ export function pgDrizzleAdapter(
|
||||
.where(eq(users.id, data))
|
||||
.then((res) => res[0] ?? null)
|
||||
},
|
||||
async getUserByEmail(data) {
|
||||
async getUserByTokenId(data) {
|
||||
return await client
|
||||
.select()
|
||||
.from(users)
|
||||
|
||||
@@ -84,7 +84,7 @@ export function SQLiteDrizzleAdapter(
|
||||
getUser(data) {
|
||||
return client.select().from(users).where(eq(users.id, data)).get() ?? null
|
||||
},
|
||||
getUserByEmail(data) {
|
||||
getUserByTokenId(data) {
|
||||
return (
|
||||
client.select().from(users).where(eq(users.email, data)).get() ?? null
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-dynamodb": "^3.36.1",
|
||||
"@aws-sdk/lib-dynamodb": "^3.36.1",
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@shelf/jest-dynamodb": "^2.1.0",
|
||||
"jest": "^27.4.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/core": "workspace:*"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ export function DynamoDBAdapter(
|
||||
})
|
||||
return format.from<AdapterUser>(data.Item)
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const data = await client.query({
|
||||
TableName,
|
||||
IndexName,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DynamoDB } from "@aws-sdk/client-dynamodb"
|
||||
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"
|
||||
import { DynamoDBAdapter } from "../src"
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { format } from "../src/"
|
||||
const config = {
|
||||
endpoint: "http://127.0.0.1:8000",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -51,12 +51,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fauna-labs/fauna-schema-migrate": "^2.1.3",
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"faunadb": "^4.3.0",
|
||||
"jest": "^27.4.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ export function FaunaAdapter(f: FaunaClient): Adapter {
|
||||
return {
|
||||
createUser: async (data) => (await q(Create(Users, { data: to(data) })))!,
|
||||
getUser: async (id) => await q(Get(Ref(Users, id))),
|
||||
getUserByEmail: async (email) => await q(Get(Match(UserByEmail, email))),
|
||||
getUserByTokenId: async (email) => await q(Get(Match(UserByEmail, email))),
|
||||
async getUserByAccount({ provider, providerAccountId }) {
|
||||
const key = [provider, providerAccountId]
|
||||
const ref = Match(AccountByProviderAndProviderAccountId, key)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { collections, FaunaAdapter, format, indexes, query } from "../src"
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { Client as FaunaClient, Get, Match, Ref } from "faunadb"
|
||||
|
||||
const client = new FaunaClient({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -48,10 +48,10 @@
|
||||
"firebase-admin": "^11.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"firebase-admin": "^11.4.1",
|
||||
"firebase-tools": "^11.16.1",
|
||||
"jest": "^29.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ export function FirestoreAdapter(
|
||||
return await getDoc(C.users.doc(id))
|
||||
},
|
||||
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
return await getOneDoc(C.users.where("email", "==", email))
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
|
||||
import { FirestoreAdapter, type FirebaseAdapterConfig } from "../src"
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import config from "@auth/adapter-test/jest/jest-preset.js"
|
||||
import config from "@next-auth/adapter-test/jest/jest-preset.js"
|
||||
|
||||
//TODO: update rest of the packages to Jest 29+
|
||||
const {testURL, ...rest} = config
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
"kysely": "^0.26.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/better-sqlite3": "^7.6.3",
|
||||
"@types/pg": "^8.6.5",
|
||||
"better-sqlite3": "^8.2.0",
|
||||
@@ -51,6 +51,6 @@
|
||||
"pg": "^8.10.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,7 +307,7 @@ export function KyselyAdapter(db: Kysely<Database>): Adapter {
|
||||
if (!result) return null
|
||||
return to(result, "emailVerified")
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const result =
|
||||
(await db
|
||||
.selectFrom("User")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { Pool } from "pg"
|
||||
import {
|
||||
Kysely,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -46,14 +46,14 @@
|
||||
"devDependencies": {
|
||||
"@mikro-orm/core": "^5",
|
||||
"@mikro-orm/sqlite": "^5",
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"jest": "^29"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ export function MikroOrmAdapter<
|
||||
|
||||
return wrap(user).toObject()
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const em = await getEM()
|
||||
const user = await em.findOne(UserModel, { email })
|
||||
if (!user) return null
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
Options,
|
||||
types,
|
||||
} from "@mikro-orm/core"
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
|
||||
globalThis.crypto ??= require("node:crypto").webcrypto
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@auth/mongodb-adapter",
|
||||
"version": "2.0.0",
|
||||
"version": "1.0.0",
|
||||
"description": "MongoDB adapter for Auth.js",
|
||||
"homepage": "https://authjs.dev",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -42,15 +42,15 @@
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mongodb": "^6"
|
||||
"mongodb": "^5 || ^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"jest": "^27.4.3",
|
||||
"mongodb": "^6.0.0"
|
||||
"mongodb": "^5.1.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
@@ -172,7 +172,7 @@ export function MongoDBAdapter(
|
||||
if (!user) return null
|
||||
return from<AdapterUser>(user)
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const user = await (await db).U.findOne({ email })
|
||||
if (!user) return null
|
||||
return from<AdapterUser>(user)
|
||||
@@ -193,7 +193,7 @@ export function MongoDBAdapter(
|
||||
await db
|
||||
).U.findOneAndUpdate({ _id }, { $set: user }, { returnDocument: "after" })
|
||||
|
||||
return from<AdapterUser>(result!)
|
||||
return from<AdapterUser>(result.value!)
|
||||
},
|
||||
async deleteUser(id) {
|
||||
const userId = _id(id)
|
||||
@@ -210,7 +210,7 @@ export function MongoDBAdapter(
|
||||
return account
|
||||
},
|
||||
async unlinkAccount(provider_providerAccountId) {
|
||||
const account = await (
|
||||
const { value: account } = await (
|
||||
await db
|
||||
).A.findOneAndDelete(provider_providerAccountId)
|
||||
return from<AdapterAccount>(account!)
|
||||
@@ -235,17 +235,17 @@ export function MongoDBAdapter(
|
||||
async updateSession(data) {
|
||||
const { _id, ...session } = to<AdapterSession>(data)
|
||||
|
||||
const updatedSession = await (
|
||||
const result = await (
|
||||
await db
|
||||
).S.findOneAndUpdate(
|
||||
{ sessionToken: session.sessionToken },
|
||||
{ $set: session },
|
||||
{ returnDocument: "after" }
|
||||
)
|
||||
return from<AdapterSession>(updatedSession!)
|
||||
return from<AdapterSession>(result.value!)
|
||||
},
|
||||
async deleteSession(sessionToken) {
|
||||
const session = await (
|
||||
const { value: session } = await (
|
||||
await db
|
||||
).S.findOneAndDelete({
|
||||
sessionToken,
|
||||
@@ -257,13 +257,14 @@ export function MongoDBAdapter(
|
||||
return data
|
||||
},
|
||||
async useVerificationToken(identifier_token) {
|
||||
const verificationToken = await (
|
||||
const { value: verificationToken } = await (
|
||||
await db
|
||||
).V.findOneAndDelete(identifier_token)
|
||||
|
||||
if (!verificationToken) return null
|
||||
const { _id, ...rest } = verificationToken;
|
||||
return rest;
|
||||
// @ts-expect-error
|
||||
delete verificationToken._id
|
||||
return verificationToken
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
|
||||
import { MongoClient } from "mongodb"
|
||||
const name = "custom-test"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
|
||||
import { MongoClient } from "mongodb"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
"neo4j-driver": "^4.0.0 || ^5.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"jest": "^27.4.3",
|
||||
"neo4j-driver": "^5.7.0"
|
||||
@@ -54,6 +54,6 @@
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ export function Neo4jAdapter(session: Session): Adapter {
|
||||
})
|
||||
},
|
||||
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
return await read(`MATCH (u:User { email: $email }) RETURN u{.*}`, {
|
||||
email,
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as neo4j from "neo4j-driver"
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import statements from "./resources/statements"
|
||||
|
||||
import { Neo4jAdapter, format } from "../src"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/pouchdb": "^6.4.0",
|
||||
"jest": "^27.4.3",
|
||||
"pouchdb": "^8.0.1",
|
||||
@@ -54,6 +54,6 @@
|
||||
"pouchdb-find": "^8.0.1"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ export function PouchDBAdapter(options: PouchDBAdapterOptions): Adapter {
|
||||
}
|
||||
},
|
||||
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const res = await (
|
||||
pouchdb as unknown as PouchDB.Database<AdapterUser>
|
||||
).find({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import {
|
||||
createIndexes,
|
||||
PouchDBAdapter,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@auth/prisma-adapter",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.1",
|
||||
"description": "Prisma adapter for Auth.js",
|
||||
"homepage": "https://authjs.dev/reference/adapter/prisma",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -51,17 +51,17 @@
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@prisma/client": ">=2.26.0 || >=3 || >=4 || >=5"
|
||||
"@prisma/client": ">=2.26.0 || >=3 || >=4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@prisma/client": "^5.2.0",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@prisma/client": "^4.15.0",
|
||||
"jest": "^27.4.3",
|
||||
"mongodb": "^4.17.0",
|
||||
"prisma": "^5.2.0"
|
||||
"mongodb": "^4.4.0",
|
||||
"prisma": "^4.15.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,7 @@ export function PrismaAdapter(p: PrismaClient): Adapter {
|
||||
return {
|
||||
createUser: (data) => p.user.create({ data }),
|
||||
getUser: (id) => p.user.findUnique({ where: { id } }),
|
||||
getUserByEmail: (email) => p.user.findUnique({ where: { email } }),
|
||||
getUserByTokenId: (email) => p.user.findUnique({ where: { email } }),
|
||||
async getUserByAccount(provider_providerAccountId) {
|
||||
const account = await p.account.findUnique({
|
||||
where: { provider_providerAccountId },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { randomUUID, runBasicTests } from "@auth/adapter-test"
|
||||
import { randomUUID, runBasicTests } from "@next-auth/adapter-test"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
import { PrismaAdapter } from "../src"
|
||||
import { ObjectId } from "mongodb"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@auth/sequelize-adapter",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.1",
|
||||
"description": "Sequelize adapter for Auth.js",
|
||||
"homepage": "https://authjs.dev",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -43,12 +43,12 @@
|
||||
"sequelize": "^6.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"jest": "^27.4.3",
|
||||
"sequelize": "^6.6.5"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ export default function SequelizeAdapter(
|
||||
|
||||
return userInstance?.get({ plain: true }) ?? null
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
await sync()
|
||||
|
||||
const userInstance = await User.findOne({
|
||||
@@ -301,9 +301,7 @@ export default function SequelizeAdapter(
|
||||
async deleteSession(sessionToken) {
|
||||
await sync()
|
||||
|
||||
const session = await Session.findOne({ where: { sessionToken } })
|
||||
await Session.destroy({ where: { sessionToken } })
|
||||
return session?.get({ plain: true })
|
||||
},
|
||||
async createVerificationToken(token) {
|
||||
await sync()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Sequelize, DataTypes } from "sequelize"
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import SequelizeAdapter, { models } from "../src"
|
||||
|
||||
const sequelize = new Sequelize({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -42,12 +42,12 @@
|
||||
"@supabase/supabase-js": "^2.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:^0.0.0",
|
||||
"@auth/tsconfig": "workspace:^0.0.0",
|
||||
"@next-auth/adapter-test": "workspace:^0.0.0",
|
||||
"@next-auth/tsconfig": "workspace:^0.0.0",
|
||||
"@supabase/supabase-js": "^2.0.5",
|
||||
"jest": "^27.4.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,7 +378,7 @@ export function SupabaseAdapter(options: SupabaseAdapterOptions): Adapter {
|
||||
|
||||
return format<AdapterUser>(data)
|
||||
},
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const { data, error } = await supabase
|
||||
.from("users")
|
||||
.select()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { runBasicTests } from "@auth/adapter-test"
|
||||
import { runBasicTests } from "@next-auth/adapter-test"
|
||||
import { format, SupabaseAdapter } from "../src"
|
||||
import { createClient } from "@supabase/supabase-js"
|
||||
import type {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# install Supabase CLI when run on CI
|
||||
if [ "$CI" = true ]; then
|
||||
wget -q -O supabase.deb https://github.com/supabase/cli/releases/download/v1.91.1/supabase_1.91.1_linux_amd64.deb
|
||||
wget -q -O supabase.deb https://github.com/supabase/cli/releases/download/v0.29.0/supabase_0.29.0_linux_amd64.deb
|
||||
sudo dpkg -i supabase.deb
|
||||
fi
|
||||
|
||||
@@ -17,4 +17,3 @@ if npx jest; then
|
||||
else
|
||||
supabase stop && exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createHash, randomUUID } from "crypto"
|
||||
const requiredMethods = [
|
||||
"createUser",
|
||||
"getUser",
|
||||
"getUserByEmail",
|
||||
"getUserByTokenId",
|
||||
"getUserByAccount",
|
||||
"updateUser",
|
||||
"linkAccount",
|
||||
@@ -21,7 +21,7 @@ export interface TestOptions {
|
||||
account?: any
|
||||
sessionUpdateExpires?: Date
|
||||
verificationTokenExpires?: Date
|
||||
},
|
||||
}
|
||||
db: {
|
||||
/** Generates UUID v4 by default. Use it to override how the test suite should generate IDs, like user id. */
|
||||
id?: () => string
|
||||
@@ -78,7 +78,7 @@ export async function runBasicTests(options: TestOptions) {
|
||||
email: "fill@murray.com",
|
||||
image: "https://www.fillmurray.com/460/300",
|
||||
name: "Fill Murray",
|
||||
emailVerified: new Date()
|
||||
emailVerified: new Date(),
|
||||
}
|
||||
|
||||
if (process.env.CUSTOM_MODEL === "1") {
|
||||
@@ -110,7 +110,7 @@ export async function runBasicTests(options: TestOptions) {
|
||||
const requiredMethods = [
|
||||
"createUser",
|
||||
"getUser",
|
||||
"getUserByEmail",
|
||||
"getUserByTokenId",
|
||||
"getUserByAccount",
|
||||
"updateUser",
|
||||
"linkAccount",
|
||||
@@ -138,9 +138,9 @@ export async function runBasicTests(options: TestOptions) {
|
||||
expect(await adapter.getUser(user.id)).toEqual(user)
|
||||
})
|
||||
|
||||
test("getUserByEmail", async () => {
|
||||
expect(await adapter.getUserByEmail("non-existent-email")).toBeNull()
|
||||
expect(await adapter.getUserByEmail(user.email)).toEqual(user)
|
||||
test("getUserByTokenId", async () => {
|
||||
expect(await adapter.getUserByTokenId("non-existent-email")).toBeNull()
|
||||
expect(await adapter.getUserByTokenId(user.email)).toEqual(user)
|
||||
})
|
||||
|
||||
test("createSession", async () => {
|
||||
@@ -241,7 +241,8 @@ export async function runBasicTests(options: TestOptions) {
|
||||
const verificationToken = {
|
||||
token: hashedToken,
|
||||
identifier,
|
||||
expires: options.fixtures?.verificationTokenExpires ?? FIFTEEN_MINUTES_FROM_NOW,
|
||||
expires:
|
||||
options.fixtures?.verificationTokenExpires ?? FIFTEEN_MINUTES_FROM_NOW,
|
||||
}
|
||||
await adapter.createVerificationToken?.(verificationToken)
|
||||
|
||||
@@ -260,7 +261,8 @@ export async function runBasicTests(options: TestOptions) {
|
||||
const verificationToken = {
|
||||
token: hashedToken,
|
||||
identifier,
|
||||
expires: options.fixtures?.verificationTokenExpires ?? FIFTEEN_MINUTES_FROM_NOW,
|
||||
expires:
|
||||
options.fixtures?.verificationTokenExpires ?? FIFTEEN_MINUTES_FROM_NOW,
|
||||
}
|
||||
await adapter.createVerificationToken?.(verificationToken)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@auth/adapter-test",
|
||||
"name": "@next-auth/adapter-test",
|
||||
"version": "0.0.0",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
"contributors": [
|
||||
@@ -21,6 +21,6 @@
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"jest": "^29.5.0",
|
||||
"ts-jest": "^27.0.3",
|
||||
"typescript": "5.2.2"
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
"@auth/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@auth/adapter-test": "workspace:*",
|
||||
"@auth/tsconfig": "workspace:*",
|
||||
"@next-auth/adapter-test": "workspace:*",
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"jest": "^27.4.3",
|
||||
"mssql": "^7.2.1",
|
||||
"mysql": "^2.18.1",
|
||||
@@ -59,7 +59,7 @@
|
||||
"sqlite3": "^5.0.8",
|
||||
"typeorm": "0.3.15",
|
||||
"typeorm-naming-strategies": "^4.1.0",
|
||||
"typescript": "5.2.2"
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mssql": "^6.2.1 || 7",
|
||||
@@ -83,6 +83,6 @@
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@auth/adapter-test/jest"
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,7 +320,7 @@ export function TypeORMAdapter(
|
||||
return { ...user }
|
||||
},
|
||||
// @ts-expect-error
|
||||
async getUserByEmail(email) {
|
||||
async getUserByTokenId(email) {
|
||||
const m = await getManager(c)
|
||||
const user = await m.findOne("UserEntity", { where: { email } })
|
||||
if (!user) return null
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DataSource } from "typeorm"
|
||||
import type { DataSourceOptions } from "typeorm"
|
||||
import type { TestOptions } from "@auth/adapter-test"
|
||||
import type { TestOptions } from "@next-auth/adapter-test"
|
||||
import * as defaultEntities from "../src/entities"
|
||||
import { parseDataSourceConfig } from "../src/utils"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"extends": "@auth/tsconfig/tsconfig.base.json",
|
||||
"extends": "@next-auth/tsconfig/tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user