-
Notifications
You must be signed in to change notification settings - Fork 396
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
565 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ | |
### 1. Install the SDK | ||
|
||
```shell | ||
npm i @auth0/[email protected].10 | ||
npm i @auth0/[email protected].11 | ||
``` | ||
|
||
### 2. Add the environment variables | ||
|
@@ -109,21 +109,24 @@ export default async function Home() { | |
|
||
You can customize the client by using the options below: | ||
|
||
| Option | Type | Description | | ||
| --------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| domain | `string` | The Auth0 domain for the tenant (e.g.: `example.us.auth0.com`). If it's not specified, it will be loaded from the `AUTH0_DOMAIN` environment variable. | | ||
| clientId | `string` | The Auth0 client ID. If it's not specified, it will be loaded from the `AUTH0_CLIENT_ID` environment variable. | | ||
| clientSecret | `string` | The Auth0 client secret. If it's not specified, it will be loaded from the `AUTH0_CLIENT_SECRET` environment variable. | | ||
| authorizationParameters | `AuthorizationParameters` | The authorization parameters to pass to the `/authorize` endpoint. See [Passing authorization parameters](#passing-authorization-parameters) for more details. | | ||
| appBaseUrl | `string` | The URL of your application (e.g.: `http://localhost:3000`). If it's not specified, it will be loaded from the `APP_BASE_URL` environment variable. | | ||
| secret | `string` | A 32-byte, hex-encoded secret used for encrypting cookies. If it's not specified, it will be loaded from the `AUTH0_SECRET` environment variable. | | ||
| signInReturnToPath | `string` | The path to redirect the user to after successfully authenticating. Defaults to `/`. | | ||
| session | `SessionConfiguration` | Configure the session timeouts and whether to use rolling sessions or not. See [Session configuration](#session-configuration) for additional details. | | ||
| beforeSessionSaved | `BeforeSessionSavedHook` | A method to manipulate the session before persisting it. See [beforeSessionSaved](#beforesessionsaved) for additional details. | | ||
| onCallback | `OnCallbackHook` | A method to handle errors or manage redirects after attempting to authenticate. See [onCallback](#oncallback) for additional details. | | ||
| sessionStore | `SessionStore` | A custom session store implementation used to persist sessions to a data store. See [Database sessions](#database-sessions) for additional details. | | ||
| pushedAuthorizationRequests | `boolean` | Configure the SDK to use the Pushed Authorization Requests (PAR) protocol when communicating with the authorization server. | | ||
| routes | `Routes` | Configure the paths for the authentication routes. See [Custom routes](#custom-routes) for additional details. | | ||
| Option | Type | Description | | ||
| --------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| domain | `string` | The Auth0 domain for the tenant (e.g.: `example.us.auth0.com` or `https://example.us.auth0.com`). If it's not specified, it will be loaded from the `AUTH0_DOMAIN` environment variable. | | ||
| clientId | `string` | The Auth0 client ID. If it's not specified, it will be loaded from the `AUTH0_CLIENT_ID` environment variable. | | ||
| clientSecret | `string` | The Auth0 client secret. If it's not specified, it will be loaded from the `AUTH0_CLIENT_SECRET` environment variable. | | ||
| authorizationParameters | `AuthorizationParameters` | The authorization parameters to pass to the `/authorize` endpoint. See [Passing authorization parameters](#passing-authorization-parameters) for more details. | | ||
| clientAssertionSigningKey | `string` or `CryptoKey` | Private key for use with `private_key_jwt` clients. | | ||
| clientAssertionSigningAlg | `string` | The algorithm used to sign the client assertion JWT. | | ||
| appBaseUrl | `string` | The URL of your application (e.g.: `http://localhost:3000`). If it's not specified, it will be loaded from the `APP_BASE_URL` environment variable. | | ||
| secret | `string` | A 32-byte, hex-encoded secret used for encrypting cookies. If it's not specified, it will be loaded from the `AUTH0_SECRET` environment variable. | | ||
| signInReturnToPath | `string` | The path to redirect the user to after successfully authenticating. Defaults to `/`. | | ||
| session | `SessionConfiguration` | Configure the session timeouts and whether to use rolling sessions or not. See [Session configuration](#session-configuration) for additional details. | | ||
| beforeSessionSaved | `BeforeSessionSavedHook` | A method to manipulate the session before persisting it. See [beforeSessionSaved](#beforesessionsaved) for additional details. | | ||
| onCallback | `OnCallbackHook` | A method to handle errors or manage redirects after attempting to authenticate. See [onCallback](#oncallback) for additional details. | | ||
| sessionStore | `SessionStore` | A custom session store implementation used to persist sessions to a data store. See [Database sessions](#database-sessions) for additional details. | | ||
| pushedAuthorizationRequests | `boolean` | Configure the SDK to use the Pushed Authorization Requests (PAR) protocol when communicating with the authorization server. | | ||
| routes | `Routes` | Configure the paths for the authentication routes. See [Custom routes](#custom-routes) for additional details. | | ||
| allowInsecureRequests | `boolean` | Allow insecure requests to be made to the authorization server. This can be useful when testing with a mock OIDC provider that does not support TLS, locally. This option can only be used when `NODE_ENV` is not set to `production`. | | ||
|
||
## Passing authorization parameters | ||
|
||
|
@@ -246,6 +249,75 @@ export default function Page({ | |
} | ||
``` | ||
|
||
## Updating the session | ||
|
||
The `updateSession` method could be used to update the session of the currently authenticated user in both the App Router and Pages Router. If the user does not have a session, an error will be thrown. | ||
|
||
> [!NOTE] | ||
> Any updates to the session will be overwritten when the user re-authenticates and obtains a new session. | ||
### On the server (App Router) | ||
|
||
On the server, the `updateSession()` helper can be used in Server Routes, Server Actions, and middleware to update the session of the currently authenticated user, like so: | ||
|
||
```tsx | ||
import { NextResponse } from "next/server" | ||
|
||
import { auth0 } from "@/lib/auth0" | ||
|
||
export async function GET() { | ||
const session = await auth0.getSession() | ||
|
||
if (!session) { | ||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) | ||
} | ||
|
||
await auth0.updateSession({ | ||
...session, | ||
updatedAt: Date.now(), | ||
}) | ||
|
||
return NextResponse.json(null, { status: 200 }) | ||
} | ||
``` | ||
|
||
> [!NOTE] | ||
> The `updateSession()` method is not usable in Server Components as it is not possible to write cookies. | ||
### On the server (Pages Router) | ||
|
||
On the server, the `updateSession(req, res, session)` helper can be used in `getServerSideProps`, API routes, and middleware to update the session of the currently authenticated user, like so: | ||
|
||
```tsx | ||
import type { NextApiRequest, NextApiResponse } from "next" | ||
|
||
import { auth0 } from "@/lib/auth0" | ||
|
||
type ResponseData = | ||
| {} | ||
| { | ||
error: string | ||
} | ||
|
||
export default async function handler( | ||
req: NextApiRequest, | ||
res: NextApiResponse<ResponseData> | ||
) { | ||
const session = await auth0.getSession(req) | ||
|
||
if (!session) { | ||
return res.status(401).json({ error: "Unauthorized" }) | ||
} | ||
|
||
await auth0.updateSession(req, res, { | ||
...session, | ||
updatedAt: Date.now(), | ||
}) | ||
|
||
res.status(200).json({}) | ||
} | ||
``` | ||
|
||
## Getting an access token | ||
|
||
The `getAccessToken()` helper can be used both in the browser and on the server to obtain the access token to call external APIs. If the access token has expired and a refresh token is available, it will automatically be refreshed and persisted. | ||
|
@@ -262,7 +334,7 @@ import { getAccessToken } from "@auth0/nextjs-auth0" | |
export default function Component() { | ||
async function fetchData() { | ||
try { | ||
const token = await auth0.getAccessToken() | ||
const token = await getAccessToken() | ||
// call external API with token... | ||
} catch (err) { | ||
// err will be an instance of AccessTokenError if an access token could not be obtained | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,7 +65,7 @@ test("getAccessToken()", async ({ page }) => { | |
expect(tokenRequest).toHaveProperty("expires_at") | ||
}) | ||
|
||
test("protected server route", async ({ page, request, context }) => { | ||
test("protected server route", async ({ page, context }) => { | ||
// before establishing a session, we should receive a 401 | ||
const unauthedRes = await context.request.fetch("/app-router/api/test") | ||
expect(unauthedRes.status()).toBe(401) | ||
|
@@ -101,3 +101,33 @@ test("protected server action", async ({ page }) => { | |
await page.getByText("Call server action").click() | ||
await expect(page.locator("#status")).toHaveValue("authenticated") | ||
}) | ||
|
||
test("updateSession()", async ({ page, context }) => { | ||
const now = Date.now() | ||
|
||
await page.goto("/auth/login?returnTo=/app-router/server") | ||
|
||
// fill out Auth0 form | ||
await page.fill('input[id="username"]', "[email protected]") | ||
await page.fill('input[id="password"]', process.env.TEST_USER_PASSWORD!) | ||
await page.getByText("Continue", { exact: true }).click() | ||
|
||
// check that the page says "Welcome, [email protected]!" | ||
expect(await page.getByRole("heading", { level: 1 }).textContent()).toBe( | ||
"Welcome, [email protected]!" | ||
) | ||
|
||
// the session should not have an `updatedAt` field initially | ||
let getSessionRes = await context.request.fetch("/app-router/api/get-session") | ||
let getSessionJson = await getSessionRes.json() | ||
expect(getSessionJson.updatedAt).toBeUndefined() | ||
|
||
// now update the session and check that the `updatedAt` field is updated | ||
const updateSessionRes = await context.request.fetch( | ||
"/app-router/api/update-session" | ||
) | ||
expect(updateSessionRes.status()).toBe(200) | ||
getSessionRes = await context.request.fetch("/app-router/api/get-session") | ||
getSessionJson = await getSessionRes.json() | ||
expect(getSessionJson.updatedAt).toBeGreaterThan(now) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,3 +82,35 @@ test("protected API route", async ({ page, request, context }) => { | |
expect(authedRes.status()).toBe(200) | ||
expect(await authedRes.json()).toEqual({ email: "[email protected]" }) | ||
}) | ||
|
||
test("updateSession()", async ({ page, context }) => { | ||
const now = Date.now() | ||
|
||
await page.goto("/auth/login?returnTo=/pages-router/server") | ||
|
||
// fill out Auth0 form | ||
await page.fill('input[id="username"]', "[email protected]") | ||
await page.fill('input[id="password"]', process.env.TEST_USER_PASSWORD!) | ||
await page.getByText("Continue", { exact: true }).click() | ||
|
||
// check that the page says "Welcome, [email protected]!" | ||
expect(await page.getByRole("heading", { level: 1 }).textContent()).toBe( | ||
"Welcome, [email protected]!" | ||
) | ||
|
||
// the session should not have an `updatedAt` field initially | ||
let getSessionRes = await context.request.fetch( | ||
"/api/pages-router/get-session" | ||
) | ||
let getSessionJson = await getSessionRes.json() | ||
expect(getSessionJson.updatedAt).toBeUndefined() | ||
|
||
// now update the session and check that the `updatedAt` field is updated | ||
const updateSessionRes = await context.request.fetch( | ||
"/api/pages-router/update-session" | ||
) | ||
expect(updateSessionRes.status()).toBe(200) | ||
getSessionRes = await context.request.fetch("/api/pages-router/get-session") | ||
getSessionJson = await getSessionRes.json() | ||
expect(getSessionJson.updatedAt).toBeGreaterThan(now) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { NextResponse } from "next/server" | ||
|
||
import { auth0 } from "@/lib/auth0" | ||
|
||
export async function GET() { | ||
const session = await auth0.getSession() | ||
|
||
if (!session) { | ||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) | ||
} | ||
|
||
return NextResponse.json(session, { status: 200 }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { NextResponse } from "next/server" | ||
|
||
import { auth0 } from "@/lib/auth0" | ||
|
||
export async function GET() { | ||
const session = await auth0.getSession() | ||
|
||
if (!session) { | ||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 }) | ||
} | ||
|
||
await auth0.updateSession({ | ||
...session, | ||
updatedAt: Date.now(), | ||
}) | ||
|
||
return NextResponse.json(null, { status: 200 }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next" | ||
import { SessionData } from "@auth0/nextjs-auth0/types" | ||
|
||
import { auth0 } from "@/lib/auth0" | ||
|
||
type ResponseData = SessionData | { error: string } | ||
|
||
export default async function handler( | ||
req: NextApiRequest, | ||
res: NextApiResponse<ResponseData> | ||
) { | ||
const session = await auth0.getSession(req) | ||
|
||
if (!session) { | ||
return res.status(401).json({ error: "Unauthorized" }) | ||
} | ||
|
||
res.status(200).json(session) | ||
} |
27 changes: 27 additions & 0 deletions
27
e2e/test-app/pages/api/pages-router/update-session/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next" | ||
|
||
import { auth0 } from "@/lib/auth0" | ||
|
||
type ResponseData = | ||
| {} | ||
| { | ||
error: string | ||
} | ||
|
||
export default async function handler( | ||
req: NextApiRequest, | ||
res: NextApiResponse<ResponseData> | ||
) { | ||
const session = await auth0.getSession(req) | ||
|
||
if (!session) { | ||
return res.status(401).json({ error: "Unauthorized" }) | ||
} | ||
|
||
await auth0.updateSession(req, res, { | ||
...session, | ||
updatedAt: Date.now(), | ||
}) | ||
|
||
res.status(200).json({}) | ||
} |
Oops, something went wrong.