Compare commits

..

20 Commits

Author SHA1 Message Date
Balázs Orbán
4e94d89554 chore(release): bump version 2023-02-02 02:16:28 +01:00
Balázs Orbán
43d66fcb23 fix(ts): stop using typeof + generic together (#6595) 2023-02-02 02:15:43 +01:00
Thang Vu
bfcf1a3604 chore(release): bump version [skip ci] 2023-01-31 19:25:50 +07:00
Thang Vu
5b1555ed97 feat: redesign all default pages
sync from core via #5825

Co-Authored-By: Rein Undheim <46612252+Gawdfrey@users.noreply.github.com>
2023-01-31 17:40:46 +07:00
Vu Van Dung
0ed07b31b6 fix(ts): correctly type unstable_getServerSession (#6560)
* fix: type of unstable_getServerSession

Signed-off-by: Vu Van Dung <me@joulev.dev>

* Apply suggestions from code review

---------

Signed-off-by: Vu Van Dung <me@joulev.dev>
Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-01-30 12:10:26 +00:00
OrJDev
2311be7589 docs: Remove the unstable note. (#6537) 2023-01-28 15:15:09 +01:00
Balázs Orbán
e847b3466f chore(release): bump version [skip ci] 2023-01-28 13:24:50 +01:00
Balázs Orbán
8df6d5b469 feat: make generateSessionToken awaitable (#6536)
Co-authored-by: @HommeSauvage
2023-01-28 12:19:32 +00:00
Balázs Orbán
0bcaeca369 feat: remove unstable_ prefix getServerSession (#6535)
* feat: remove `unstable_` prefix from `getServerSession`

* fix test

* fix lint
2023-01-28 12:12:00 +00:00
Balázs Orbán
4f5ddbcb76 fix(oauth1): pass oauth_token_secret (#6534)
* Pass oauth_token_secret in OAuth 1.0 calls

* simplify

* simplify

---------

Co-authored-by: dawidos234 <dawidos234@gmail.com>
2023-01-28 09:44:23 +00:00
Balázs Orbán
0cbeb4055e chore(release): bump version 2023-01-24 14:03:59 +01:00
Balázs Orbán
5a128db369 fix(providers): add slash to default logo urls
fixes #6495
2023-01-24 14:03:40 +01:00
Balázs Orbán
c385cf8c7c chore(release): bump version [skip ci] 2023-01-24 02:47:03 +01:00
Balázs Orbán
53fa46744c chore: match core 2023-01-24 02:40:29 +01:00
StachowiakDawid
451eaaabd2 fix: Allow adding own logo to provider (#6465) 2023-01-24 02:35:30 +01:00
Balázs Orbán
f54424c216 fix(next-auth): remove engines 2023-01-24 02:24:45 +01:00
Balázs Orbán
09bcc1d504 fix(providers): default image to null for Azure AD
Fixes #6482
2023-01-24 02:24:35 +01:00
Chiemerie Arum
6ecf9cb93d docs(client): Improve grammar (#6444)
Improve grammar
2023-01-20 11:14:40 +00:00
Judicael
ba2711d279 docs: Remove Demo Identity server 4 (#6354)
Since the demo is not working anymore (removed), we should remove the demo identity server from the docs
2023-01-10 12:05:59 +00:00
Balázs Orbán
03881bf98f chore: fix sync GH Action pat 2023-01-07 08:29:07 +01:00
64 changed files with 282 additions and 297 deletions

View File

@@ -14,5 +14,5 @@ jobs:
# Can update to v1 when https://github.com/BetaHuhn/repo-file-sync-action/issues/168 is resolved
uses: BetaHuhn/repo-file-sync-action@v1.16.5
with:
GH_PAT: ${{ secrets.SYNC_EXAMPLE_PAT }}
GH_PAT: ${{ secrets.GH_PAT_CLASSIC }}
SKIP_PR: true

View File

@@ -1,6 +1,6 @@
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
export default async function Page() {
const session = await unstable_getServerSession()
const session = await getServerSession()
return <pre>{JSON.stringify(session, null, 2)}</pre>
}

View File

@@ -1,9 +1,9 @@
// This is an example of to protect an API route
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "../auth/[...nextauth]"
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
const session = await getServerSession(req, res, authOptions)
if (session) {
res.send({

View File

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

View File

@@ -1,11 +1,11 @@
// This is an example of how to query data from Supabase with RLS.
// Learn more about Row Levele Security (RLS): https://supabase.com/docs/guides/auth/row-level-security
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "../auth/[...nextauth]"
import { createClient } from "@supabase/supabase-js"
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
const session = await getServerSession(req, res, authOptions)
if (!session)
return res.send(JSON.stringify({ error: "No session!" }, null, 2))

View File

@@ -1,5 +1,5 @@
// This is an example of how to protect content using server rendering
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout"
import AccessDenied from "../components/access-denied"
@@ -26,11 +26,7 @@ export default function Page({ content, session }) {
}
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(
context.req,
context.res,
authOptions
)
const session = await getServerSession(context.req, context.res, authOptions)
let content = null
if (session) {

View File

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

View File

@@ -1,6 +1,6 @@
// This is an example of how to protect content using server rendering
// and fetching data from Supabase with RLS enabled.
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import { createClient } from "@supabase/supabase-js"
import Layout from "../components/layout"
@@ -27,11 +27,7 @@ export default function Page({ data, session }) {
}
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(
context.req,
context.res,
authOptions
)
const session = await getServerSession(context.req, context.res, authOptions)
if (!session)
return {

View File

@@ -1,5 +1,5 @@
// This is an example of to protect an API route
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "../auth/[...nextauth]"
import type { NextApiRequest, NextApiResponse } from "next"
@@ -8,7 +8,7 @@ export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await unstable_getServerSession(req, res, authOptions)
const session = await getServerSession(req, res, authOptions)
if (session) {
return res.send({

View File

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

View File

@@ -1,4 +1,4 @@
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout"
@@ -12,11 +12,11 @@ export default function ServerSidePage({ session }: { session: Session }) {
<Layout>
<h1>Server Side Rendering</h1>
<p>
This page uses the <strong>unstable_getServerSession()</strong> method
in <strong>getServerSideProps()</strong>.
This page uses the <strong>getServerSession()</strong> method in{" "}
<strong>getServerSideProps()</strong>.
</p>
<p>
Using <strong>unstable_getServerSession()</strong> in{" "}
Using <strong>getServerSession()</strong> in{" "}
<strong>getServerSideProps()</strong> is the recommended approach if you
need to support Server Side Rendering with authentication.
</p>
@@ -37,11 +37,7 @@ export default function ServerSidePage({ session }: { session: Session }) {
export async function getServerSideProps(context: GetServerSidePropsContext) {
return {
props: {
session: await unstable_getServerSession(
context.req,
context.res,
authOptions
),
session: await getServerSession(context.req, context.res, authOptions),
},
}
}

View File

@@ -254,7 +254,7 @@ The `supabaseAccessToken` is now available on the `session` object and can be pa
```js
// ...
// Use `useSession()` or `unstable_getServerSession()` to get the NextAuth session.
// Use `useSession()` or `getServerSession()` to get the NextAuth session.
const { supabaseAccessToken } = session

View File

@@ -107,7 +107,7 @@ The redirect callback may be invoked more than once in the same flow.
This callback is called whenever a JSON Web Token is created (i.e. at sign
in) or updated (i.e whenever a session is accessed in the client). The returned value will be [encrypted](/configuration/options#jwt), and it is stored in a cookie.
Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`, `unstable_getServerSession()`, `useSession()` will invoke this function, but only if you are using a [JWT session](/configuration/options#session). This method is not invoked when you persist sessions in a database.
Requests to `/api/auth/signin`, `/api/auth/session` and calls to `getSession()`, `getServerSession()`, `useSession()` will invoke this function, but only if you are using a [JWT session](/configuration/options#session). This method is not invoked when you persist sessions in a database.
- As with database persisted session expiry times, token expiry time is extended whenever a session is active.
- The arguments _user_, _account_, _profile_ and _isNewUser_ are only passed the first time this callback is called on a new session, after the user signs in. In subsequent calls, only `token` will be available.

View File

@@ -2,15 +2,15 @@
## `unstable_getServerSession`
:::warning
This feature is experimental and may be removed or changed in the future.
:::
This method was renamed to `getServerSession`. See the documentation below.
When calling from server-side i.e. in API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `unstable_getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
## `getServerSession`
When calling from server-side i.e. in API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
Otherwise, if you only want to get the session token, see [`getToken`](/tutorials/securing-pages-and-api-routes#using-gettoken).
`unstable_getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way:
`getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way:
In `[...nextauth].ts`:
```ts
@@ -27,10 +27,10 @@ export default NextAuth(authOptions);
### In `getServerSideProps`:
```js
import { authOptions } from 'pages/api/auth/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(context.req, context.res, authOptions)
const session = await getServerSession(context.req, context.res, authOptions)
if (!session) {
return {
@@ -52,11 +52,11 @@ export async function getServerSideProps(context) {
### In API Routes:
```js
import { authOptions } from 'pages/api/auth/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
export async function handler(req, res) {
const session = await unstable_getServerSession(req, res, authOptions)
const session = await getServerSession(req, res, authOptions)
if (!session) {
res.status(401).json({ message: "You must be logged in." });
@@ -71,14 +71,14 @@ export async function handler(req, res) {
### In `app/` directory:
You can also use `unstable_getServerSession` in Next.js' server components:
You can also use `getServerSession` in Next.js' server components:
```tsx
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "pages/api/auth/[...nextauth]"
export default async function Page() {
const session = await unstable_getServerSession(authOptions)
const session = await getServerSession(authOptions)
return <pre>{JSON.stringify(session, null, 2)}</pre>
}
```

View File

@@ -65,7 +65,7 @@ export default function Component() {
### Require session
Due to the way how Next.js handles `getServerSideProps` and `getInitialProps`, every protected page load has to make a server-side request to check if the session is valid and then generate the requested page (SSR). This increases server load, and if you are good with making the requests from the client, there is an alternative. You can use `useSession` in a way that makes sure you always have a valid session. If after the initial loading state there was no session found, you can define the appropriate action to respond.
Due to the way Next.js handles `getServerSideProps` and `getInitialProps`, every protected page load has to make a server-side request to check if the session is valid and then generate the requested page (SSR). This increases server load, and if you are good with making the requests from the client, there is an alternative. You can use `useSession` in a way that makes sure you always have a valid session. If after the initial loading state there was no session found, you can define the appropriate action to respond.
The default behavior is to redirect the user to the sign-in page, from where - after a successful login - they will be sent back to the page they started on. You can also define an `onUnauthenticated()` callback, if you would like to do something else:
@@ -157,15 +157,11 @@ You can create your own session management solution using data fetching librarie
## getSession()
- Client Side: **Yes**
- Server Side: **No** (See: [`unstable_getServerSession()`](/configuration/nextjs#unstable_getserversession)
- Server Side: **No** (See: [`getServerSession()`](/configuration/nextjs#unstable_getserversession)
NextAuth.js provides a `getSession()` helper which should be called **client side only** to return the current active session.
On the server side, **this is still available to use**, however, we recommend using `unstable_getServerSession` going forward. The idea behind this is to avoid an additional unnecessary `fetch` call on the server side. For more information, please check out [this issue](https://github.com/nextauthjs/next-auth/issues/1535).
:::note
The `unstable_getServerSession` only has the prefix `unstable_` at the moment, because the API may change in the future. There are no known bugs at the moment and it is safe to use. If you discover any issues, please do report them as a [GitHub Issue](https://github.com/nextauthjs/next-auth/issues) and we will patch them as soon as possible.
:::
On the server side, **this is still available to use**, however, we recommend using `getServerSession` going forward. The idea behind this is to avoid an additional unnecessary `fetch` call on the server side. For more information, please check out [this issue](https://github.com/nextauthjs/next-auth/issues/1535).
This helper is helpful in case you want to read the session outside of the context of React.
@@ -178,7 +174,7 @@ async function myFunction() {
}
```
Read the tutorial [securing pages and API routes](/tutorials/securing-pages-and-api-routes) to know how to fetch the session in server side calls using `unstable_getServerSession()`.
Read the tutorial [securing pages and API routes](/tutorials/securing-pages-and-api-routes) to know how to fetch the session in server side calls using `getServerSession()`.
---
@@ -422,7 +418,7 @@ If you pass the `session` page prop to the `<SessionProvider>` as in the exa
This only works on pages where you provide the correct `pageProps`, however. This is normally done in `getInitialProps` or `getServerSideProps` on an individual page basis like so:
```js title="pages/index.js"
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from './api/auth/[...nextauth]'
...
@@ -430,7 +426,7 @@ import { authOptions } from './api/auth/[...nextauth]'
export async function getServerSideProps({ req, res }) {
return {
props: {
session: await unstable_getServerSession(req, res, authOptions)
session: await getServerSession(req, res, authOptions)
}
}
}

View File

@@ -106,14 +106,14 @@ You can use the `useSession` hook from anywhere in your application (e.g. in a h
### Backend - API Route
To protect an API Route, you can use the [`unstable_getServerSession()`](/configuration/nextjs#unstable_getserversession) method.
To protect an API Route, you can use the [`getServerSession()`](/configuration/nextjs#unstable_getserversession) method.
```javascript title="pages/api/restricted.js" showLineNumbers
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./auth/[...nextauth]"
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
const session = await getServerSession(req, res, authOptions)
if (session) {
res.send({

View File

@@ -35,27 +35,3 @@ providers: [
]
...
```
## Demo IdentityServer
The configuration below is for the demo server at https://demo.identityserver.io/
If you want to try it out, you can copy and paste the configuration below.
You can sign in to the demo service with either <b>bob/bob</b> or <b>alice/alice</b>.
```js
import IdentityServer4Provider from `next-auth/providers/identity-server4`
...
providers: [
IdentityServer4Provider({
id: "demo-identity-server",
name: "Demo IdentityServer4",
authorization: { params: { scope: "openid profile email api offline_access" } },
issuer: "https://demo.identityserver.io/",
clientId: "interactive.confidential",
clientSecret: "secret",
})
}
...
```

View File

@@ -68,12 +68,12 @@ For other patterns check out the [Next.js Middleware documentation](https://next
### Server Side
You can protect server side rendered pages using the `unstable_getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly.
You can protect server side rendered pages using the `getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly.
You need to add this to every server rendered page you want to protect. Be aware, `unstable_getServerSession` takes slightly different arguments than the method it is replacing, `getSession`.
You need to add this to every server rendered page you want to protect. Be aware, `getServerSession` takes slightly different arguments than the method it is replacing, `getSession`.
```js title="pages/server-side-example.js"
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import { useSession } from "next-auth/react"
@@ -96,7 +96,7 @@ export default function Page() {
export async function getServerSideProps(context) {
return {
props: {
session: await unstable_getServerSession(
session: await getServerSession(
context.req,
context.res,
authOptions
@@ -128,16 +128,16 @@ export default function App({
## Securing API Routes
### Using unstable_getServerSession()
### Using getServerSession()
You can protect API routes using the `unstable_getServerSession()` method.
You can protect API routes using the `getServerSession()` method.
```js title="pages/api/get-session-example.js"
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./auth/[...nextauth]"
export default async (req, res) => {
const session = await unstable_getServerSession(req, res, authOptions)
const session = await getServerSession(req, res, authOptions)
if (session) {
// Signed in
console.log("Session", JSON.stringify(session, null, 2))

View File

@@ -1,6 +1,6 @@
{
"name": "next-auth",
"version": "4.18.8",
"version": "4.19.2",
"description": "Authentication for Next.js",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth.git",
@@ -127,8 +127,5 @@
"react": "^18",
"react-dom": "^18",
"whatwg-fetch": "^3.6.2"
},
"engines": {
"node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0"
}
}

View File

@@ -61,7 +61,7 @@ export function assertConfig(params: {
return new MissingSecret("Please define a `secret` in production.")
}
// req.query isn't defined when asserting `unstable_getServerSession` for example
// req.query isn't defined when asserting `getServerSession` for example
if (!req.query?.nextauth && !req.action) {
return new MissingAPIRoute(
"Cannot find [...nextauth].{js,ts} in `/pages/api/auth`. Make sure the filename is written correctly."

View File

@@ -113,7 +113,7 @@ export default async function callbackHandler(params: {
session = useJwtSession
? {}
: await createSession({
sessionToken: generateSessionToken(),
sessionToken: await generateSessionToken(),
userId: user.id,
expires: fromDate(options.session.maxAge),
})
@@ -143,7 +143,7 @@ export default async function callbackHandler(params: {
session = useJwtSession
? {}
: await createSession({
sessionToken: generateSessionToken(),
sessionToken: await generateSessionToken(),
userId: userByAccount.id,
expires: fromDate(options.session.maxAge),
})
@@ -181,11 +181,11 @@ export default async function callbackHandler(params: {
? await getUserByEmail(profile.email)
: null
if (userByEmail) {
const provider = options.provider as OAuthConfig<any>;
const provider = options.provider as OAuthConfig<any>
if (provider?.allowDangerousEmailAccountLinking) {
// If you trust the oauth provider to correctly verify email addresses, you can opt-in to
// If you trust the oauth provider to correctly verify email addresses, you can opt-in to
// account linking even when the user is not signed-in.
user = userByEmail;
user = userByEmail
} else {
// We end up here when we don't have an account with the same [provider].id *BUT*
// we do already have an account with the same email address as the one in the
@@ -216,7 +216,7 @@ export default async function callbackHandler(params: {
session = useJwtSession
? {}
: await createSession({
sessionToken: generateSessionToken(),
sessionToken: await generateSessionToken(),
userId: user.id,
expires: fromDate(options.session.maxAge),
})

View File

@@ -1,5 +1,5 @@
import { openidClient } from "./client"
import { oAuth1Client } from "./client-legacy"
import { oAuth1Client, oAuth1TokenStore } from "./client-legacy"
import { createState } from "./state-handler"
import { createNonce } from "./nonce-handler"
import { createPKCE } from "./pkce-handler"
@@ -44,7 +44,7 @@ export default async function getAuthorizationUrl({
oauth_token_secret: tokens.oauth_token_secret,
...tokens.params,
})}`
oAuth1TokenStore.set(tokens.oauth_token, tokens.oauth_token_secret)
logger.debug("GET_AUTHORIZATION_URL", { url, provider })
return { redirect: url }
}

View File

@@ -1,6 +1,6 @@
import { TokenSet } from "openid-client"
import { openidClient } from "./client"
import { oAuth1Client } from "./client-legacy"
import { oAuth1Client, oAuth1TokenStore } from "./client-legacy"
import { useState } from "./state-handler"
import { usePKCECodeVerifier } from "./pkce-handler"
import { useNonce } from "./nonce-handler"
@@ -42,7 +42,7 @@ export default async function oAuthCallback(params: {
const { oauth_token, oauth_verifier } = query ?? {}
const tokens = (await (client as any).getOAuthAccessToken(
oauth_token,
null,
oAuth1TokenStore.get(oauth_token),
oauth_verifier
)) as TokenSet
let profile: Profile = await (client as any).get(
@@ -63,6 +63,8 @@ export default async function oAuthCallback(params: {
}
}
if (query?.oauth_token) oAuth1TokenStore.delete(query.oauth_token)
try {
const client = await openidClient(options)

View File

@@ -69,3 +69,5 @@ export function oAuth1Client(options: InternalOptions<"oauth">) {
}
return oauth1Client
}
export const oAuth1TokenStore = new Map()

View File

@@ -102,8 +102,8 @@ export default function ErrorPage(props: ErrorProps) {
}}
/>
)}
{theme?.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<div className="card">
{theme?.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<h1>{heading}</h1>
<div className="message">{message}</div>
{signin}

View File

@@ -49,6 +49,13 @@ export default function SigninPage(props: SignInServerPageParams) {
return false
})
if (typeof document !== "undefined" && theme.buttonText) {
document.documentElement.style.setProperty(
"--button-text-color",
theme.buttonText
)
}
if (typeof document !== "undefined" && theme.brandColor) {
document.documentElement.style.setProperty(
"--brand-color",
@@ -74,6 +81,7 @@ export default function SigninPage(props: SignInServerPageParams) {
const error = errorType && (errors[errorType] ?? errors.default)
const logos = "https://authjs.dev/img/providers"
return (
<div className="signin">
{theme.brandColor && (
@@ -87,7 +95,17 @@ export default function SigninPage(props: SignInServerPageParams) {
}}
/>
)}
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
{theme.buttonText && (
<style
dangerouslySetInnerHTML={{
__html: `
:root {
--button-text-color: ${theme.buttonText}
}
`,
}}
/>
)}
<div className="card">
{error && (
<div className="error">
@@ -117,14 +135,24 @@ export default function SigninPage(props: SignInServerPageParams) {
>
{provider.style?.logo && (
<img
loading="lazy"
height={24}
width={24}
id="provider-logo"
src={`https://authjs.dev/img/providers/${provider.style.logo}`}
src={`${
provider.style.logo.startsWith("/") ? logos : ""
}${provider.style.logo}`}
/>
)}
{provider.style?.logoDark && (
<img
loading="lazy"
height={24}
width={24}
id="provider-logo-dark"
src={`https://authjs.dev/img/providers/${provider.style.logoDark}`}
src={`${
provider.style.logo.startsWith("/") ? logos : ""
}${provider.style.logoDark}`}
/>
)}
<span>Sign in with {provider.name}</span>
@@ -153,7 +181,7 @@ export default function SigninPage(props: SignInServerPageParams) {
placeholder="email@example.com"
required
/>
<button type="submit">Sign in with {provider.name}</button>
<button id="submitButton" type="submit">Sign in with {provider.name}</button>
</form>
)}
{provider.type === "credentials" && (

View File

@@ -23,13 +23,24 @@ export default function SignoutPage(props: SignoutProps) {
}}
/>
)}
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
{theme.buttonText && (
<style
dangerouslySetInnerHTML={{
__html: `
:root {
--button-text-color: ${theme.buttonText}
}
`,
}}
/>
)}
<div className="card">
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<h1>Signout</h1>
<p>Are you sure you want to sign out?</p>
<form action={`${url}/signout`} method="POST">
<input type="hidden" name="csrfToken" value={csrfToken} />
<button type="submit">Sign out</button>
<button id="submitButton" type="submit">Sign out</button>
</form>
</div>
</div>

View File

@@ -22,8 +22,8 @@ export default function VerifyRequestPage(props: VerifyRequestPageProps) {
}}
/>
)}
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<div className="card">
{theme.logo && <img src={theme.logo} alt="Logo" className="logo" />}
<h1>Check your email</h1>
<p>A sign in link has been sent to your email address.</p>
<p>

View File

@@ -465,7 +465,7 @@ export interface SessionOptions {
* However, you can specify your own custom string (such as CUID) to be used.
* @default `randomUUID` or `randomBytes.toHex` depending on the Node.js version
*/
generateSessionToken: () => string
generateSessionToken: () => Awaitable<string>
}
export interface DefaultUser {

View File

@@ -8,7 +8,8 @@
.__next-auth-theme-auto,
.__next-auth-theme-light {
--color-background: #fff;
--color-background: #ececec;
--color-background-card: #fff;
--color-text: #000;
--color-primary: #444;
--color-control-border: #bbb;
@@ -18,7 +19,8 @@
}
.__next-auth-theme-dark {
--color-background: #000;
--color-background: #161b22;
--color-background-card: #0d1117;
--color-text: #fff;
--color-primary: #ccc;
--color-control-border: #555;
@@ -29,7 +31,8 @@
@media (prefers-color-scheme: dark) {
.__next-auth-theme-auto {
--color-background: #000;
--color-background: #161b22;
--color-background-card: #0d1117;
--color-text: #fff;
--color-primary: #ccc;
--color-control-border: #555;
@@ -78,10 +81,9 @@ input[type] {
width: 100%;
padding: 0.5rem 1rem;
border: var(--border-width) solid var(--color-control-border);
background: var(--color-background);
background: var(--color-background-card);
font-size: 1rem;
border-radius: var(--border-radius);
box-shadow: inset 0 0.1rem 0.2rem rgba(0, 0, 0, 0.2);
color: var(--color-text);
&:focus {
@@ -107,41 +109,39 @@ a.button {
}
}
button span {
flex-grow: 1;
}
button,
a.button {
margin: 0 0 0.75rem 0;
padding: 0.75rem 1rem;
color: var(--provider-color, var(--color-primary));
background-color: var(--provider-bg, var(--color-background));
background-color: var(--provider-bg, var(--color-background-card));
font-size: 1.1rem;
min-height: 62px;
border-color: rgba(0, 0, 0, 0.1);
border-radius: var(--border-radius);
transition: all 0.1s ease-in-out;
box-shadow: #000 0px 0px 0px 0px, #000 0px 0px 0px 0px,
rgba(0, 0, 0, 0.2) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -4px;
font-weight: 500;
position: relative;
display: flex;
align-items: center;
justify-content: center;
&:has(img) {
justify-content: unset;
span {
flex-grow: 1;
}
@media (max-width: 450px) {
font-size: 0.9rem;
}
&:hover {
cursor: pointer;
}
&:active {
box-shadow: 0 0.15rem 0.3rem rgba(0, 0, 0, 0.15),
inset 0 0.1rem 0.2rem var(--color-background),
inset 0 -0.1rem 0.1rem rgba(0, 0, 0, 0.1);
cursor: pointer;
}
#provider-logo {
width: 25px;
display: block;
}
#provider-logo-dark {
@@ -149,20 +149,23 @@ a.button {
}
}
#submitButton {
color: var(--button-text-color, var(--color-info-text));
background-color: var(--brand-color, var(--color-info));
width: 100%;
}
@media (prefers-color-scheme: dark) {
button,
a.button {
color: var(--provider-dark-color, var(--color-primary));
background-color: var(--provider-dark-bg, var(--color-background));
border: 1px solid #0d0d0d;
box-shadow: #000 0px 0px 0px 0px, #ccc 0px 0px 0px 0px,
rgba(255, 255, 255, 0.01) 0px 5px 5px -3px,
rgba(255, 255, 255, 0.05) 0px 4px 6px -4px;
}
#provider-logo {
display: none !important;
}
#provider-logo-dark {
width: 25px;
display: block !important;
}
}
@@ -189,7 +192,6 @@ a.site {
> div {
text-align: center;
padding: 0.5rem;
}
}
@@ -217,16 +219,16 @@ a.site {
display: block;
border: 0;
border-top: 1px solid var(--color-seperator);
margin: 1.5em auto 0 auto;
margin: 2rem auto 1rem auto;
overflow: visible;
&::before {
content: "or";
background: var(--color-background);
background: var(--color-background-card);
color: #888;
padding: 0 0.4rem;
position: relative;
top: -0.6rem;
top: -0.7rem;
}
}
@@ -234,7 +236,7 @@ a.site {
background: #f5f5f5;
font-weight: 500;
border-radius: 0.3rem;
background: var(--color-info);
background: var(--color-error);
p {
text-align: left;
@@ -260,25 +262,26 @@ a.site {
max-width: 300px;
}
}
.signout {
.message {
margin-bottom: 1.5rem;
}
}
.logo {
display: inline-block;
margin-top: 100px;
max-width: 300px;
max-height: 150px;
max-width: 150px;
margin-top: 20px;
margin-bottom: 25px;
max-height: 70px;
}
.card {
max-width: max-content;
border: 1px solid var(--color-control-border);
border-radius: 5px;
@media screen and (min-width: 450px) {
width: 350px;
}
@media screen and (max-width: 450px) {
width: 200px;
}
margin: 20px 0 20px 0;
background-color: var(--color-background-card);
border-radius: 30px;
padding: 20px 50px;
margin: 50px auto;
.header {
color: var(--color-primary);
@@ -286,5 +289,5 @@ a.site {
}
.section-header {
color: var(--brand-color, var(--color-text));
color: var(--color-text);
}

View File

@@ -82,7 +82,6 @@ function NextAuth(
export default NextAuth
let experimentalWarningShown = false
let experimentalRSCWarningShown = false
type GetServerSessionOptions = Partial<Omit<AuthOptions, "callbacks">> & {
@@ -91,28 +90,18 @@ type GetServerSessionOptions = Partial<Omit<AuthOptions, "callbacks">> & {
}
}
export async function unstable_getServerSession<
type GetServerSessionParams<O extends GetServerSessionOptions> =
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"], O]
| [NextApiRequest, NextApiResponse, O]
| [O]
| []
export async function getServerSession<
O extends GetServerSessionOptions,
R = O["callbacks"] extends { session: (...args: any[]) => infer U }
? U
: Session
>(
...args:
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"], O]
| [NextApiRequest, NextApiResponse, O]
| [O]
| []
): Promise<R | null> {
if (!experimentalWarningShown && process.env.NODE_ENV !== "production") {
console.warn(
"[next-auth][warn][EXPERIMENTAL_API]",
"\n`unstable_getServerSession` is experimental and may be removed or changed in the future, as the name suggested.",
`\nhttps://next-auth.js.org/configuration/nextjs#unstable_getServerSession}`,
`\nhttps://next-auth.js.org/warnings#EXPERIMENTAL_API`
)
experimentalWarningShown = true
}
>(...args: GetServerSessionParams<O>): Promise<R | null> {
const isRSC = args.length === 0 || args.length === 1
if (
!experimentalRSCWarningShown &&
@@ -121,8 +110,8 @@ export async function unstable_getServerSession<
) {
console.warn(
"[next-auth][warn][EXPERIMENTAL_API]",
"\n`unstable_getServerSession` is used in a React Server Component.",
`\nhttps://next-auth.js.org/configuration/nextjs#unstable_getServerSession}`,
"\n`getServerSession` is used in a React Server Component.",
`\nhttps://next-auth.js.org/configuration/nextjs#getServerSession}`,
`\nhttps://next-auth.js.org/warnings#EXPERIMENTAL_API`
)
experimentalRSCWarningShown = true
@@ -178,6 +167,25 @@ export async function unstable_getServerSession<
return null
}
let deprecatedWarningShown = false
/** @deprecated renamed to `getServerSession` */
export async function unstable_getServerSession<
O extends GetServerSessionOptions,
R = O["callbacks"] extends { session: (...args: any[]) => infer U }
? U
: Session
>(...args: GetServerSessionParams<O>): Promise<R | null> {
if (!deprecatedWarningShown && process.env.NODE_ENV !== "production") {
console.warn(
"`unstable_getServerSession` has been renamed to `getServerSession`."
)
deprecatedWarningShown = true
}
return await getServerSession(...args)
}
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace NodeJS {

View File

@@ -118,8 +118,8 @@ export default function Apple<P extends AppleProfile>(
},
checks: ["pkce"],
style: {
logo: "apple.svg",
logoDark: "apple-dark.svg",
logo: "/apple.svg",
logoDark: "/apple-dark.svg",
bg: "#fff",
text: "#000",
bgDark: "#000",

View File

@@ -32,8 +32,8 @@ export default function Atlassian<P extends AtlassianProfile>(
}
},
style: {
logo: "atlassian.svg",
logoDark: "atlassian-dark.svg",
logo: "/atlassian.svg",
logoDark: "/atlassian-dark.svg",
bg: "#0052cc",
text: "#fff",
bgDark: "#fff",

View File

@@ -27,8 +27,8 @@ export default function Auth0<P extends Auth0Profile>(
}
},
style: {
logo: "auth0.svg",
logoDark: "auth0-dark.svg",
logo: "/auth0.svg",
logoDark: "/auth0-dark.svg",
bg: "#fff",
text: "#EB5424",
bgDark: "#EB5424",

View File

@@ -43,8 +43,8 @@ export default function AzureADB2C<P extends AzureB2CProfile>(
}
},
style: {
logo: "azure.svg",
logoDark: "azure-dark.svg",
logo: "/azure.svg",
logoDark: "/azure-dark.svg",
bg: "#fff",
text: "#0072c6",
bgDark: "#0072c6",

View File

@@ -33,36 +33,32 @@ export default function AzureAD<P extends AzureADProfile>(
},
async profile(profile, tokens) {
// https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
const profilePicture = await fetch(
const response = await fetch(
`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
{
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
}
{ headers: { Authorization: `Bearer ${tokens.access_token}` } }
)
// Confirm that profile photo was returned
if (profilePicture.ok) {
const pictureBuffer = await profilePicture.arrayBuffer()
const pictureBase64 = Buffer.from(pictureBuffer).toString("base64")
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: `data:image/jpeg;base64, ${pictureBase64}`,
}
} else {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
}
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",
logo: "/azure.svg",
logoDark: "/azure-dark.svg",
bg: "#fff",
text: "#0072c6",
bgDark: "#0072c6",

View File

@@ -27,8 +27,8 @@ export default function BattleNet<P extends BattleNetProfile>(
}
},
style: {
logo: "battlenet.svg",
logoDark: "battlenet-dark.svg",
logo: "/battlenet.svg",
logoDark: "/battlenet-dark.svg",
bg: "#fff",
text: "#148eff",
bgDark: "#148eff",

View File

@@ -16,8 +16,8 @@ export default function Box(options) {
}
},
style: {
logo: "box.svg",
logoDark: "box-dark.svg",
logo: "/box.svg",
logoDark: "/box-dark.svg",
bg: "#fff",
text: "#0075C9",
bgDark: "#0075C9",

View File

@@ -25,8 +25,8 @@ export default function Cognito<P extends CognitoProfile>(
}
},
style: {
logo: "cognito.svg",
logoDark: "cognito.svg",
logo: "/cognito.svg",
logoDark: "/cognito.svg",
bg: "#fff",
text: "#C17B9E",
bgDark: "#fff",

View File

@@ -45,8 +45,8 @@ export default function Discord<P extends DiscordProfile>(
}
},
style: {
logo: "discord.svg",
logoDark: "discord-dark.svg",
logo: "/discord.svg",
logoDark: "/discord-dark.svg",
bg: "#fff",
text: "#7289DA",
bgDark: "#7289DA",

View File

@@ -42,8 +42,8 @@ export default function Facebook<P extends FacebookProfile>(
}
},
style: {
logo: "facebook.svg",
logoDark: "facebook-dark.svg",
logo: "/facebook.svg",
logoDark: "/facebook-dark.svg",
bg: "#fff",
text: "#006aff",
bgDark: "#006aff",

View File

@@ -51,8 +51,8 @@ export default function Foursquare(options) {
}
},
style: {
logo: "foursquare.svg",
logoDark: "foursquare-dark.svg",
logo: "/foursquare.svg",
logoDark: "/foursquare-dark.svg",
bg: "#fff",
text: "#000",
bgDark: "#000",

View File

@@ -18,8 +18,8 @@ export default function Freshbooks(options) {
}
},
style: {
logo: "freshbooks.svg",
logoDark: "freshbooks-dark.svg",
logo: "/freshbooks.svg",
logoDark: "/freshbooks-dark.svg",
bg: "#fff",
text: "#0075dd",
bgDark: "#0075dd",

View File

@@ -99,8 +99,8 @@ export default function Github<P extends GithubProfile>(
}
},
style: {
logo: "github.svg",
logoDark: "github-dark.svg",
logo: "/github.svg",
logoDark: "/github-dark.svg",
bg: "#fff",
bgDark: "#000",
text: "#000",

View File

@@ -68,8 +68,8 @@ export default function GitLab<P extends GitLabProfile>(
}
},
style: {
logo: "gitlab.svg",
logoDark: "gitlab-dark.svg",
logo: "/gitlab.svg",
logoDark: "/gitlab-dark.svg",
bg: "#fff",
text: "#FC6D26",
bgDark: "#FC6D26",

View File

@@ -38,8 +38,8 @@ export default function Google<P extends GoogleProfile>(
}
},
style: {
logo: "google.svg",
logoDark: "google.svg",
logo: "/google.svg",
logoDark: "/google.svg",
bgDark: "#fff",
bg: "#fff",
text: "#000",

View File

@@ -65,8 +65,8 @@ export default function HubSpot<P extends HubSpotProfile>(
}
},
style: {
logo: "hubspot.svg",
logoDark: "hubspot-dark.svg",
logo: "/hubspot.svg",
logoDark: "/hubspot-dark.svg",
bg: "#fff",
text: "#ff7a59",
bgDark: "#ff7a59",

View File

@@ -47,8 +47,8 @@ export default function Instagram(options) {
}
},
style: {
logo: "instagram.svg",
logoDark: "instagram.svg",
logo: "/instagram.svg",
logoDark: "/instagram.svg",
bg: "#fff",
text: "#000",
bgDark: "#fff",

View File

@@ -44,8 +44,8 @@ export default function Keycloak<P extends KeycloakProfile>(
}
},
style: {
logo: "keycloak.svg",
logoDark: "keycloak.svg",
logo: "/keycloak.svg",
logoDark: "/keycloak.svg",
bg: "#fff",
text: "#000",
bgDark: "#fff",

View File

@@ -34,8 +34,8 @@ export default function LINE<P extends LineProfile>(
id_token_signed_response_alg: "HS256",
},
style: {
logo: "line.svg",
logoDark: "line.svg",
logo: "/line.svg",
logoDark: "/line.svg",
bg: "#fff",
text: "#00C300",
bgDark: "#00C300",

View File

@@ -56,8 +56,8 @@ export default function LinkedIn<P extends LinkedInProfile>(
}
},
style: {
logo: "linkedin.svg",
logoDark: "linkedin-dark.svg",
logo: "/linkedin.svg",
logoDark: "/linkedin-dark.svg",
bg: "#fff",
text: "#069",
bgDark: "#069",

View File

@@ -16,8 +16,8 @@ export default function Mailchimp(options) {
}
},
style: {
logo: "mailchimp.svg",
logoDark: "mailchimp-dark.svg",
logo: "/mailchimp.svg",
logoDark: "/mailchimp-dark.svg",
bg: "#fff",
text: "#000",
bgDark: "#000",

View File

@@ -53,8 +53,8 @@ export default function Okta<P extends OktaProfile>(
}
},
style: {
logo: "okta.svg",
logoDark: "okta-dark.svg",
logo: "/okta.svg",
logoDark: "/okta-dark.svg",
bg: "#fff",
text: "#000",
bgDark: "#000",

View File

@@ -30,8 +30,8 @@ export default function Patreon<P extends PatreonProfile>(
}
},
style: {
logo: "patreon.svg",
logoDark: "patreon.svg",
logo: "/patreon.svg",
logoDark: "/patreon.svg",
bg: "#fff",
text: "#e85b46",
bgDark: "#000",

View File

@@ -50,8 +50,8 @@ export default function Slack<P extends SlackProfile>(
}
},
style: {
logo: "slack.svg",
logoDark: "slack.svg",
logo: "/slack.svg",
logoDark: "/slack.svg",
bg: "#fff",
text: "#000",
bgDark: "#000",

View File

@@ -30,8 +30,8 @@ export default function Spotify<P extends SpotifyProfile>(
}
},
style: {
logo: "spotify.svg",
logoDark: "spotify.svg",
logo: "/spotify.svg",
logoDark: "/spotify.svg",
bg: "#fff",
text: "#2ebd59",
bgDark: "#fff",

View File

@@ -54,8 +54,8 @@ export default function TodoistProvider<P extends TodoistProfile>(
}
},
style: {
logo: "todoist.svg",
logoDark: "todoist.svg",
logo: "/todoist.svg",
logoDark: "/todoist.svg",
bg: "#fff",
text: "#E44332",
bgDark: "#000",

View File

@@ -52,8 +52,8 @@ export default function Trakt<P extends TraktUser>(
}
},
style: {
logo: "trakt.svg",
logoDark: "trakt-dark.svg",
logo: "/trakt.svg",
logoDark: "/trakt-dark.svg",
bg: "#fff",
text: "#ED2224",
bgDark: "#ED2224",

View File

@@ -37,8 +37,8 @@ export default function Twitch<P extends TwitchProfile>(
}
},
style: {
logo: "twitch.svg",
logoDark: "twitch-dark.svg",
logo: "/twitch.svg",
logoDark: "/twitch-dark.svg",
bg: "#fff",
text: "#65459B",
bgDark: "#65459B",

View File

@@ -120,8 +120,8 @@ export function TwitterLegacy<
}
},
style: {
logo: "twitter.svg",
logoDark: "twitter-dark.svg",
logo: "/twitter.svg",
logoDark: "/twitter-dark.svg",
bg: "#fff",
text: "#1da1f2",
bgDark: "#1da1f2",
@@ -215,8 +215,8 @@ export default function Twitter<
},
checks: ["pkce", "state"],
style: {
logo: "twitter.svg",
logoDark: "twitter-dark.svg",
logo: "/twitter.svg",
logoDark: "/twitter-dark.svg",
bg: "#fff",
text: "#1da1f2",
bgDark: "#1da1f2",

View File

@@ -306,8 +306,8 @@ export default function VK<P extends Record<string, any> = VkProfile>(
}
},
style: {
logo: "vk.svg",
logoDark: "vk-dark.svg",
logo: "/vk.svg",
logoDark: "/vk-dark.svg",
bg: "#fff",
text: "#07F",
bgDark: "#07F",

View File

@@ -181,8 +181,8 @@ export default function Wikimedia<P extends WikimediaProfile>(
}
},
style: {
logo: "wikimedia.svg",
logoDark: "wikimedia-dark.svg",
logo: "/wikimedia.svg",
logoDark: "/wikimedia-dark.svg",
bg: "#fff",
text: "#000",
bgDark: "#000",

View File

@@ -45,8 +45,8 @@ export default function WorkOS<P extends WorkOSProfile>(
}
},
style: {
logo: "workos.svg",
logoDark: "workos-dark.svg",
logo: "/workos.svg",
logoDark: "/workos-dark.svg",
bg: "#fff",
text: "#6363f1",
bgDark: "#6363f1",

View File

@@ -1,6 +1,6 @@
import * as core from "../src/core"
import { MissingSecret } from "../src/core/errors"
import { unstable_getServerSession } from "../src/next"
import { getServerSession } from "../src/next"
import { mockLogger } from "./lib"
const originalWarn = console.warn
@@ -27,7 +27,7 @@ afterEach(() => {
describe("Treat secret correctly", () => {
it("Read from NEXTAUTH_SECRET", async () => {
process.env.NEXTAUTH_SECRET = "secret"
await unstable_getServerSession(req, res, { providers: [], logger })
await getServerSession(req, res, { providers: [], logger })
expect(logger.error).toBeCalledTimes(0)
expect(logger.error).not.toBeCalledWith("NO_SECRET")
@@ -36,7 +36,7 @@ describe("Treat secret correctly", () => {
})
it("Read from options.secret", async () => {
await unstable_getServerSession(req, res, {
await getServerSession(req, res, {
providers: [],
logger,
secret: "secret",
@@ -51,30 +51,12 @@ describe("Treat secret correctly", () => {
"There is a problem with the server configuration. Check the server logs for more information."
)
await expect(
unstable_getServerSession(req, res, { providers: [], logger })
getServerSession(req, res, { providers: [], logger })
).rejects.toThrowError(configError)
expect(logger.error).toBeCalledTimes(1)
expect(logger.error).toBeCalledWith("NO_SECRET", expect.any(MissingSecret))
})
it("Only logs warning once and in development", async () => {
process.env.NEXTAUTH_SECRET = "secret"
// Expect console.warn to NOT be called due to NODE_ENV=production
await unstable_getServerSession(req, res, { providers: [], logger })
expect(console.warn).toBeCalledTimes(0)
// Expect console.warn to be called ONCE due to NODE_ENV=development
// @ts-expect-error
process.env.NODE_ENV = "development"
await unstable_getServerSession(req, res, { providers: [], logger })
expect(console.warn).toBeCalledTimes(1)
// Expect console.warn to be still only be called ONCE
await unstable_getServerSession(req, res, { providers: [], logger })
expect(console.warn).toBeCalledTimes(1)
delete process.env.NEXTAUTH_SECRET
})
})
describe("Return correct data", () => {
@@ -87,7 +69,7 @@ describe("Return correct data", () => {
// @ts-expect-error
spy.mockReturnValue({ body: {} })
const session = await unstable_getServerSession(req, res, {
const session = await getServerSession(req, res, {
providers: [],
logger,
secret: "secret",
@@ -113,7 +95,7 @@ describe("Return correct data", () => {
// @ts-expect-error
spy.mockReturnValue(mockedResponse)
const session = await unstable_getServerSession(req, res, {
const session = await getServerSession(req, res, {
providers: [],
logger,
secret: "secret",