From 726a8ed3d9e399ea1b4d01425c6a2ae65d7d159a Mon Sep 17 00:00:00 2001
From: guabu <135956181+guabu@users.noreply.github.com>
Date: Tue, 3 Dec 2024 08:25:56 +0100
Subject: [PATCH] 4.0.0-beta.9 (#1827)
---
README.md | 32 ++++++++++++++++++++++++-
package.json | 2 +-
src/client/hooks/use-user.ts | 9 +++++++
src/client/index.ts | 1 +
src/client/providers/auth0-provider.tsx | 26 ++++++++++++++++++++
src/server/auth-client.test.ts | 5 ++++
src/server/auth-client.ts | 5 +++-
src/server/client.ts | 8 +++----
8 files changed, 81 insertions(+), 7 deletions(-)
create mode 100644 src/client/providers/auth0-provider.tsx
diff --git a/README.md b/README.md
index 493a1f82..5fcca121 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
### 1. Install the SDK
```shell
-npm i @auth0/nextjs-auth0@4.0.0-beta.8
+npm i @auth0/nextjs-auth0@4.0.0-beta.9
```
### 2. Add the environment variables
@@ -322,6 +322,36 @@ export default async function handler(
}
```
+## ``
+
+### Passing an initial user from the server
+
+You can wrap your components in an `` and pass an initial user object to make it available to your components using the `useUser()` hook. For example:
+
+```tsx
+import { Auth0Provider } from "@auth0/nextjs-auth0"
+
+import { auth0 } from "@/lib/auth0"
+
+export default async function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode
+}>) {
+ const session = await auth0.getSession()
+
+ return (
+
+
+ {children}
+
+
+ )
+}
+```
+
+The loaded user will then be used as a fallback in `useUser()` hook.
+
## Hooks
The SDK exposes hooks to enable you to provide custom logic that would be run at certain lifecycle events.
diff --git a/package.json b/package.json
index 6c810444..cccf2eb3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@auth0/nextjs-auth0",
- "version": "4.0.0-beta.8",
+ "version": "4.0.0-beta.9",
"description": "Auth0 Next.js SDK",
"main": "dist/index.js",
"scripts": {
diff --git a/src/client/hooks/use-user.ts b/src/client/hooks/use-user.ts
index d9ed8a9b..681c4461 100644
--- a/src/client/hooks/use-user.ts
+++ b/src/client/hooks/use-user.ts
@@ -17,6 +17,15 @@ export function useUser() {
})
)
+ // if we have the user loaded via the provider, return it
+ if (data) {
+ return {
+ user: data,
+ isLoading: false,
+ error: null,
+ }
+ }
+
if (error) {
return {
user: null,
diff --git a/src/client/index.ts b/src/client/index.ts
index f6baabcc..1804b203 100644
--- a/src/client/index.ts
+++ b/src/client/index.ts
@@ -1,2 +1,3 @@
export { useUser } from "./hooks/use-user"
export { getAccessToken } from "./helpers/get-access-token"
+export { Auth0Provider } from "./providers/auth0-provider"
diff --git a/src/client/providers/auth0-provider.tsx b/src/client/providers/auth0-provider.tsx
new file mode 100644
index 00000000..8195cb0c
--- /dev/null
+++ b/src/client/providers/auth0-provider.tsx
@@ -0,0 +1,26 @@
+"use client"
+
+import React from "react"
+import { SWRConfig } from "swr"
+
+import { User } from "../../types"
+
+export function Auth0Provider({
+ user,
+ children,
+}: {
+ user?: User
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/src/server/auth-client.test.ts b/src/server/auth-client.test.ts
index 256674fa..614a4d9b 100644
--- a/src/server/auth-client.test.ts
+++ b/src/server/auth-client.test.ts
@@ -1337,6 +1337,11 @@ describe("Authentication Client", async () => {
// query parameters
expect(logoutUrl.searchParams.get("client_id")).toEqual(DEFAULT.clientId)
expect(logoutUrl.searchParams.get("returnTo")).toEqual(DEFAULT.appBaseUrl)
+
+ // session cookie is cleared
+ const cookie = response.cookies.get("__session")
+ expect(cookie?.value).toEqual("")
+ expect(cookie?.expires).toEqual(new Date("1970-01-01T00:00:00.000Z"))
})
it("should return an error if the discovery endpoint could not be fetched", async () => {
diff --git a/src/server/auth-client.ts b/src/server/auth-client.ts
index d8414665..f298e8c8 100644
--- a/src/server/auth-client.ts
+++ b/src/server/auth-client.ts
@@ -287,7 +287,10 @@ export class AuthClient {
const url = new URL("/v2/logout", this.issuer)
url.searchParams.set("returnTo", returnTo)
url.searchParams.set("client_id", this.clientMetadata.client_id)
- return NextResponse.redirect(url)
+
+ const res = NextResponse.redirect(url)
+ await this.sessionStore.delete(req.cookies, res.cookies)
+ return res
}
const url = new URL(authorizationServerMetadata.end_session_endpoint)
diff --git a/src/server/client.ts b/src/server/client.ts
index 3617ed0b..e5b9c529 100644
--- a/src/server/client.ts
+++ b/src/server/client.ts
@@ -180,7 +180,7 @@ export class Auth0Client {
*
* This method can be used in Server Components, Server Actions, Route Handlers, and middleware in the **App Router**.
*/
- async getAccessToken(): Promise<{ token: string; expiresAt: number } | null>
+ async getAccessToken(): Promise<{ token: string; expiresAt: number }>
/**
* getAccessToken returns the access token.
@@ -189,14 +189,14 @@ export class Auth0Client {
*/
async getAccessToken(
req: PagesRouterRequest
- ): Promise<{ token: string; expiresAt: number } | null>
+ ): Promise<{ token: string; expiresAt: number }>
/**
* getAccessToken returns the access token.
*/
async getAccessToken(
req?: PagesRouterRequest
- ): Promise<{ token: string; expiresAt: number } | null> {
+ ): Promise<{ token: string; expiresAt: number }> {
let session: SessionData | null = null
if (req) {
@@ -212,7 +212,7 @@ export class Auth0Client {
)
}
- // if access token has expired, return null
+ // if access token has expired, throw an error
if (session.tokenSet.expiresAt <= Date.now() / 1000) {
if (!session.tokenSet.refreshToken) {
throw new AccessTokenError(