Open Source. Full Stack. Own Your Data.
@@ -32,7 +32,7 @@ NextAuth.js is a complete open-source authentication solution. -This is an example application that shows how `@auth/nextjs` is applied to a basic Next.js app. +This is an example application that shows how `next-auth` is applied to a basic Next.js app. The deployed version can be found at [`next-auth-example.vercel.app`](https://next-auth-example.vercel.app) diff --git a/apps/examples/nextjs/auth.ts b/apps/examples/nextjs/auth.ts index 06f3b80e..cf7a8ccf 100644 --- a/apps/examples/nextjs/auth.ts +++ b/apps/examples/nextjs/auth.ts @@ -1,4 +1,4 @@ -import { NextAuth } from "@auth/nextjs" +import NextAuth from "next-auth" import GitHub from "@auth/core/providers/github" export const { handlers, auth } = NextAuth({ diff --git a/apps/examples/nextjs/components/access-denied.tsx b/apps/examples/nextjs/components/access-denied.tsx index 6224511e..4c9c0d79 100644 --- a/apps/examples/nextjs/components/access-denied.tsx +++ b/apps/examples/nextjs/components/access-denied.tsx @@ -1,4 +1,4 @@ -import { signIn } from "@auth/nextjs/client" +import { signIn } from "next-auth/react" export default function AccessDenied() { return ( diff --git a/apps/examples/nextjs/components/footer.tsx b/apps/examples/nextjs/components/footer.tsx index c9e3f1d4..1303c60e 100644 --- a/apps/examples/nextjs/components/footer.tsx +++ b/apps/examples/nextjs/components/footer.tsx @@ -1,6 +1,6 @@ import Link from "next/link" import styles from "./footer.module.css" -import packageJSON from "@auth/nextjs/package.json" +import packageJSON from "next-auth/package.json" export default function Footer() { return ( diff --git a/apps/examples/nextjs/package.json b/apps/examples/nextjs/package.json index bbb063aa..400d00e1 100644 --- a/apps/examples/nextjs/package.json +++ b/apps/examples/nextjs/package.json @@ -20,15 +20,14 @@ ], "dependencies": { "@auth/core": "workspace:*", - "@auth/nextjs": "workspace:*", "next": "latest", - "nodemailer": "^6", - "react": "^18", - "react-dom": "^18" + "next-auth": "workspace:*", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "devDependencies": { - "@types/node": "^17", - "@types/react": "^18.0.37", - "typescript": "^4" + "@types/node": "^18.16.2", + "@types/react": "^18.2.0", + "typescript": "^5.0.4" } } diff --git a/docs/docs/concepts/faq.md b/docs/docs/concepts/faq.md index 4279eb7e..3c86a4c4 100644 --- a/docs/docs/concepts/faq.md +++ b/docs/docs/concepts/faq.md @@ -269,7 +269,7 @@ Ultimately if your request is not accepted or is not actively in development, yo-Auth.js by default uses JSON Web Tokens for saving the user's session. However, if you use a [database adapter](/guides/adapters/using-a-database-adapter), the database will be used to persist the user's session. You can force the usage of JWT when using a database [through the configuration options](/reference/configuration/auth-config#session). Since v4 all our JWT tokens are now encrypted by default with A256GCM. +Auth.js by default uses JSON Web Tokens for saving the user's session. However, if you use a [database adapter](/guides/adapters/using-a-database-adapter), the database will be used to persist the user's session. You can force the usage of JWT when using a database [through the configuration options](/reference/configuration/auth-config#session). Since v4 all our JWTs are now encrypted by default with A256GCM.
diff --git a/docs/docs/getting-started/oauth-tutorial.mdx b/docs/docs/getting-started/oauth-tutorial.mdx index 0bbb3251..ddafeafd 100644 --- a/docs/docs/getting-started/oauth-tutorial.mdx +++ b/docs/docs/getting-started/oauth-tutorial.mdx @@ -36,10 +36,6 @@ This tutorial assumes you have a Next.js application set up. If you don't, you c npm install next-auth ``` -:::info -We are working on a new `@auth/nextjs` package that will make it easier to set up Auth.js with Next.js. Stay tuned! For now, you can use the `next-auth` package. -::: - ### Creating the server config Create the following [API route](https://nextjs.org/docs/api-routes/dynamic-api-routes#catch-all-api-routes) file. This route contains the necessary configuration for NextAuth.js, as well as the dynamic route handler: @@ -270,7 +266,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 diff --git a/docs/docs/guides/adapters/creating-a-database-adapter.md b/docs/docs/guides/adapters/creating-a-database-adapter.md index e8620008..b31ca33f 100644 --- a/docs/docs/guides/adapters/creating-a-database-adapter.md +++ b/docs/docs/guides/adapters/creating-a-database-adapter.md @@ -6,7 +6,7 @@ Using a custom adapter you can connect to any database back-end or even several ## How to create an adapter -For more information about the data these methods need to manage see [models](/reference/adapters/models). +For more information about the data these methods need to manage see [models](/reference/adapters#models). _See the code below for practical example._ diff --git a/docs/docs/guides/basics/events.md b/docs/docs/guides/basics/events.md index 33305562..2d699eac 100644 --- a/docs/docs/guides/basics/events.md +++ b/docs/docs/guides/basics/events.md @@ -29,7 +29,7 @@ Sent when the user signs out. The message object will contain one of these depending on if you use JWT or database persisted sessions: -- `token`: The JWT token for this session. +- `token`: The JWT for this session. - `session`: The session object from your adapter that is being ended ### createUser @@ -60,5 +60,5 @@ Sent at the end of a request for the current session. The message object will contain one of these depending on if you use JWT or database persisted sessions: -- `token`: The JWT token for this session. +- `token`: The JWT for this session. - `session`: The session object from your adapter. diff --git a/docs/docs/reference/adapters/index.md b/docs/docs/reference/adapters/index.md index 1ad11728..17662141 100644 --- a/docs/docs/reference/adapters/index.md +++ b/docs/docs/reference/adapters/index.md @@ -2,7 +2,7 @@ title: Overview --- -Using a Auth.js / NextAuth.js adapter you can connect to any database service or even several different services at the same time. The following listed official adapters are created and maintained by the community: +Using an Auth.js / NextAuth.js adapter you can connect to any database service or even several different services at the same time. The following listed official adapters are created and maintained by the community: {
conform?: (response: Response) => Awaitable
*
*
*
*
*
*
|
-
- - Vercel - 🥉 Bronze Financial Sponsor ☁️ Infrastructure Support - |
-
-
- - Prisma - 🥉 Bronze Financial Sponsor - |
-
-
- - Clerk - 🥉 Bronze Financial Sponsor - |
-
-
- - Lowdefy - 🥉 Bronze Financial Sponsor - |
-
-
- - WorkOS - 🥉 Bronze Financial Sponsor - |
-
-
- - Checkly - ☁️ Infrastructure Support - |
-
-
-
- - superblog - ☁️ Infrastructure Support - |
-
- {response === null ? "null-response" : response || "no response"} -
-- {response === null - ? "null-response" - : JSON.stringify(response) || "no response"} -
-{JSON.stringify(session, null, 2)}
-
- return No session
-} diff --git a/packages/next-auth/src/client/__tests__/sign-in.test.js b/packages/next-auth/src/client/__tests__/sign-in.test.js deleted file mode 100644 index 0422fe90..00000000 --- a/packages/next-auth/src/client/__tests__/sign-in.test.js +++ /dev/null @@ -1,290 +0,0 @@ -import { useState } from "react" -import userEvent from "@testing-library/user-event" -import { render, screen, waitFor } from "@testing-library/react" -import logger from "../../utils/logger" -import { - server, - mockCredentialsResponse, - mockEmailResponse, - mockGithubResponse, -} from "./helpers/mocks" -import { signIn } from "../../react" -import { rest } from "msw" - -const { location } = window - -jest.mock("../../utils/logger", () => ({ - __esModule: true, - default: { - warn: jest.fn(), - debug: jest.fn(), - error: jest.fn(), - }, - proxyLogger(logger) { - return logger - }, -})) - -beforeAll(() => { - server.listen() - - let _href = window.location.href - // Allows to mutate `window.location`... - delete window.location - - window.location = { - reload: jest.fn(), - } - Object.defineProperty(window.location, "href", { - get: () => _href, - // whatwg-fetch or whatwg-url does not seem to work with relative URLs - set: (href) => { - _href = href.startsWith("/") ? `http://localhost${href}` : href - return _href - }, - }) -}) - -beforeEach(() => { - jest.clearAllMocks() - server.resetHandlers() -}) - -afterAll(() => { - window.location = location - server.close() -}) - -const callbackUrl = "https://redirects/to" - -test.each` - provider | type - ${""} | ${"no"} - ${"foo"} | ${"unknown"} -`( - "if $type provider, it redirects to the default sign-in page", - async ({ provider }) => { - render(- {response ? JSON.stringify(response) : "no response"} -
-- {response ? JSON.stringify(response) : "no response"} -
-- - {url?.host} - -
- ), - }, - configuration: { - status: 500, - heading: "Server error", - message: ( -There is a problem with the server configuration.
-Check the server logs for more information.
-You do not have permission to sign in.
-- - Sign in - -
-The sign in link is no longer valid.
-It may have been used already or it may have expired.
-- - Sign in - -
- ), - }, - } - - const { status, heading, message, signin } = - errors[error.toLowerCase()] ?? errors.default - - return { - status, - html: ( -{error}
-Are you sure you want to sign out?
- -A sign in link has been sent to your email address.
-- - {url.host} - -
- {
- /**
- * Use this callback to control if a user is allowed to sign in.
- * Returning true will continue the sign-in flow.
- * Throwing an error or returning a string will stop the flow, and redirect the user.
- *
- * [Documentation](https://next-auth.js.org/configuration/callbacks#sign-in-callback)
- */
- signIn: (params: {
- user: User | AdapterUser
- account: A | null
- /**
- * If OAuth provider is used, it contains the full
- * OAuth profile returned by your provider.
- */
- profile?: P
- /**
- * If Email provider is used, on the first call, it contains a
- * `verificationRequest: true` property to indicate it is being triggered in the verification request flow.
- * When the callback is invoked after a user has clicked on a sign in link,
- * this property will not be present. You can check for the `verificationRequest` property
- * to avoid sending emails to addresses or domains on a blocklist or to only explicitly generate them
- * for email address in an allow list.
- */
- email?: {
- verificationRequest?: boolean
- }
- /** If Credentials provider is used, it contains the user credentials */
- credentials?: Record
- extends Omit (
- options: OAuthUserConfig
-): OAuthConfig {
- return {
- id: "42-school",
- name: "42 School",
- type: "oauth",
- authorization: {
- url: "https://api.intra.42.fr/oauth/authorize",
- params: { scope: "public" },
- },
- token: "https://api.intra.42.fr/oauth/token",
- userinfo: "https://api.intra.42.fr/v2/me",
- profile(profile) {
- return {
- id: profile.id.toString(),
- name: profile.usual_full_name,
- email: profile.email,
- image: profile.image_url,
- }
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/apple.ts b/packages/next-auth/src/providers/apple.ts
deleted file mode 100644
index 5ab16885..00000000
--- a/packages/next-auth/src/providers/apple.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-import { OAuthConfig, OAuthUserConfig } from "."
-
-/**
- * See more at:
- * [Retrieve the User's Information from Apple ID Servers
-](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773)
- */
-export interface AppleProfile extends Record (
- options: Omit {
- return {
- id: "apple",
- name: "Apple",
- type: "oauth",
- wellKnown: "https://appleid.apple.com/.well-known/openid-configuration",
- authorization: {
- params: { scope: "name email", response_mode: "form_post" },
- },
- idToken: true,
- profile(profile) {
- return {
- id: profile.sub,
- name: profile.name,
- email: profile.email,
- image: null,
- }
- },
- checks: ["pkce"],
- style: {
- logo: "/apple.svg",
- logoDark: "/apple-dark.svg",
- bg: "#fff",
- text: "#000",
- bgDark: "#000",
- textDark: "#fff",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/atlassian.ts b/packages/next-auth/src/providers/atlassian.ts
deleted file mode 100644
index 1b18036f..00000000
--- a/packages/next-auth/src/providers/atlassian.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-interface AtlassianProfile extends Record (
- options: OAuthUserConfig
-): OAuthConfig {
- return {
- id: "atlassian",
- name: "Atlassian",
- type: "oauth",
- authorization: {
- url: "https://auth.atlassian.com/authorize",
- params: {
- audience: "api.atlassian.com",
- prompt: "consent",
- },
- },
- token: "https://auth.atlassian.com/oauth/token",
- userinfo: "https://api.atlassian.com/me",
- profile(profile) {
- return {
- id: profile.account_id,
- name: profile.name,
- email: profile.email,
- image: profile.picture,
- }
- },
- style: {
- logo: "/atlassian.svg",
- logoDark: "/atlassian-dark.svg",
- bg: "#0052cc",
- text: "#fff",
- bgDark: "#fff",
- textDark: "#0052cc",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/auth0.ts b/packages/next-auth/src/providers/auth0.ts
deleted file mode 100644
index 8ad5ead0..00000000
--- a/packages/next-auth/src/providers/auth0.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface Auth0Profile extends Record (
- options: OAuthUserConfig
-): OAuthConfig {
- return {
- id: "auth0",
- name: "Auth0",
- wellKnown: `${options.issuer}/.well-known/openid-configuration`,
- type: "oauth",
- authorization: { params: { scope: "openid email profile" } },
- checks: ["pkce", "state"],
- idToken: true,
- profile(profile) {
- return {
- id: profile.sub,
- name: profile.nickname,
- email: profile.email,
- image: profile.picture,
- }
- },
- style: {
- logo: "/auth0.svg",
- logoDark: "/auth0-dark.svg",
- bg: "#fff",
- text: "#EB5424",
- bgDark: "#EB5424",
- textDark: "#fff",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/authentik.ts b/packages/next-auth/src/providers/authentik.ts
deleted file mode 100644
index cacab1bb..00000000
--- a/packages/next-auth/src/providers/authentik.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface AuthentikProfile extends Record (
- options: OAuthUserConfig
-): OAuthConfig {
- return {
- id: "authentik",
- name: "Authentik",
- wellKnown: `${options.issuer}/.well-known/openid-configuration`,
- type: "oauth",
- authorization: { params: { scope: "openid email profile" } },
- checks: ["pkce", "state"],
- profile(profile) {
- return {
- id: profile.sub,
- name: profile.name ?? profile.preferred_username,
- email: profile.email,
- image: profile.picture,
- }
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/azure-ad-b2c.ts b/packages/next-auth/src/providers/azure-ad-b2c.ts
deleted file mode 100644
index fd32be87..00000000
--- a/packages/next-auth/src/providers/azure-ad-b2c.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface AzureB2CProfile extends Record (
- options: OAuthUserConfig & {
- primaryUserFlow?: string
- tenantId?: string
- }
-): OAuthConfig {
- const { tenantId, primaryUserFlow } = options
- const issuer =
- options.issuer ??
- `https://${tenantId}.b2clogin.com/${tenantId}.onmicrosoft.com/${primaryUserFlow}/v2.0`
- return {
- id: "azure-ad-b2c",
- name: "Azure Active Directory B2C",
- type: "oauth",
- wellKnown: `${issuer}/.well-known/openid-configuration`,
- idToken: true,
- profile(profile) {
- return {
- id: profile.sub,
- name: profile.name,
- email: profile.emails[0],
- // TODO: Find out how to retrieve the profile picture
- image: null,
- }
- },
- style: {
- logo: "/azure.svg",
- logoDark: "/azure-dark.svg",
- bg: "#fff",
- text: "#0072c6",
- bgDark: "#0072c6",
- textDark: "#fff",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/azure-ad.ts b/packages/next-auth/src/providers/azure-ad.ts
deleted file mode 100644
index f12b07c9..00000000
--- a/packages/next-auth/src/providers/azure-ad.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface AzureADProfile extends Record (
- options: OAuthUserConfig & {
- /**
- * https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
- * @default 48
- */
- profilePhotoSize?: 48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648
- /** @default "common" */
- tenantId?: string
- }
-): OAuthConfig {
- const tenant = options.tenantId ?? "common"
- const profilePhotoSize = options.profilePhotoSize ?? 48
-
- return {
- id: "azure-ad",
- name: "Azure Active Directory",
- type: "oauth",
- wellKnown: `https://login.microsoftonline.com/${tenant}/v2.0/.well-known/openid-configuration?appid=${options.clientId}`,
- authorization: {
- params: {
- scope: "openid profile email",
- },
- },
- async profile(profile, tokens) {
- // https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
- const response = await fetch(
- `https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
- { headers: { Authorization: `Bearer ${tokens.access_token}` } }
- )
-
- // Confirm that profile photo was returned
- let image
- // TODO: Do this without Buffer
- if (response.ok && typeof Buffer !== "undefined") {
- try {
- const pictureBuffer = await response.arrayBuffer()
- const pictureBase64 = Buffer.from(pictureBuffer).toString("base64")
- image = `data:image/jpeg;base64, ${pictureBase64}`
- } catch {}
- }
-
- return {
- id: profile.sub,
- name: profile.name,
- email: profile.email,
- image: image ?? null,
- }
- },
- style: {
- logo: "/azure.svg",
- logoDark: "/azure-dark.svg",
- bg: "#fff",
- text: "#0072c6",
- bgDark: "#0072c6",
- textDark: "#fff",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/battlenet.ts b/packages/next-auth/src/providers/battlenet.ts
deleted file mode 100644
index c921d5df..00000000
--- a/packages/next-auth/src/providers/battlenet.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface BattleNetProfile extends Record (
- options: OAuthUserConfig & { issuer: BattleNetIssuer }
-): OAuthConfig {
- return {
- id: "battlenet",
- name: "Battle.net",
- type: "oauth",
- wellKnown: `${options.issuer}/.well-known/openid-configuration`,
- profile(profile) {
- return {
- id: profile.sub,
- name: profile.battle_tag,
- email: null,
- image: null,
- }
- },
- style: {
- logo: "/battlenet.svg",
- logoDark: "/battlenet-dark.svg",
- bg: "#fff",
- text: "#148eff",
- bgDark: "#148eff",
- textDark: "#fff",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/box.js b/packages/next-auth/src/providers/box.js
deleted file mode 100644
index 7d7e8546..00000000
--- a/packages/next-auth/src/providers/box.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/** @type {import(".").OAuthProvider} */
-export default function Box(options) {
- return {
- id: "box",
- name: "Box",
- type: "oauth",
- authorization: "https://account.box.com/api/oauth2/authorize",
- token: "https://api.box.com/oauth2/token",
- userinfo: "https://api.box.com/2.0/users/me",
- profile(profile) {
- return {
- id: profile.id,
- name: profile.name,
- email: profile.login,
- image: profile.avatar_url,
- }
- },
- style: {
- logo: "/box.svg",
- logoDark: "/box-dark.svg",
- bg: "#fff",
- text: "#0075C9",
- bgDark: "#0075C9",
- textDark: "#fff",
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/boxyhq-saml.ts b/packages/next-auth/src/providers/boxyhq-saml.ts
deleted file mode 100644
index a00e15d5..00000000
--- a/packages/next-auth/src/providers/boxyhq-saml.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface BoxyHQSAMLProfile extends Record (
- options: OAuthUserConfig
-): OAuthConfig {
- return {
- id: "boxyhq-saml",
- name: "BoxyHQ SAML",
- type: "oauth",
- version: "2.0",
- checks: ["pkce", "state"],
- authorization: {
- url: `${options.issuer}/api/oauth/authorize`,
- params: {
- provider: "saml",
- },
- },
- token: `${options.issuer}/api/oauth/token`,
- userinfo: `${options.issuer}/api/oauth/userinfo`,
- profile(profile) {
- return {
- id: profile.id,
- email: profile.email,
- name: [profile.firstName, profile.lastName].filter(Boolean).join(" "),
- image: null,
- }
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/bungie.js b/packages/next-auth/src/providers/bungie.js
deleted file mode 100644
index dc6c998f..00000000
--- a/packages/next-auth/src/providers/bungie.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/** @type {import(".").OAuthProvider} */
-export default function Bungie(options) {
- return {
- id: "bungie",
- name: "Bungie",
- type: "oauth",
- authorization: "https://www.bungie.net/en/OAuth/Authorize?reauth=true",
- token: "https://www.bungie.net/platform/app/oauth/token/",
- userinfo:
- "https://www.bungie.net/platform/User/GetBungieAccount/{membershipId}/254/",
- profile(profile) {
- const { bungieNetUser: user } = profile.Response
-
- return {
- id: user.membershipId,
- name: user.displayName,
- email: null,
- image: `https://www.bungie.net${
- user.profilePicturePath.startsWith("/") ? "" : "/"
- }${user.profilePicturePath}`,
- }
- },
- options,
- }
-}
diff --git a/packages/next-auth/src/providers/cognito.ts b/packages/next-auth/src/providers/cognito.ts
deleted file mode 100644
index 26b92231..00000000
--- a/packages/next-auth/src/providers/cognito.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import type { OAuthConfig, OAuthUserConfig } from "."
-
-export interface CognitoProfile extends Record{JSON.stringify(session, null, 2)}
+ *