Skip to content

Commit

Permalink
[SDK-4499] Update Next.js QS for app dir (#10293)
Browse files Browse the repository at this point in the history
Co-authored-by: Frederik Prijck <[email protected]>
  • Loading branch information
adamjmcgrath and frederikprijck authored Aug 29, 2023
1 parent b2f0e66 commit accdf14
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 76 deletions.
64 changes: 44 additions & 20 deletions articles/quickstart/webapp/nextjs/01-login.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Run the following command within your project directory to install the Auth0 Nex
npm install @auth0/nextjs-auth0
```

The SDK exposes methods and variables that help you integrate Auth0 with your Next.js application using [API Routes](https://nextjs.org/docs/api-routes/introduction) on the backend and [React Context](https://reactjs.org/docs/context.html) with [React Hooks](https://reactjs.org/docs/hooks-overview.html) on the frontend.
The SDK exposes methods and variables that help you integrate Auth0 with your Next.js application using [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) on the backend and [React Context](https://reactjs.org/docs/context.html) with [React Hooks](https://reactjs.org/docs/hooks-overview.html) on the frontend.

### Configure the SDK

Expand All @@ -48,17 +48,17 @@ AUTH0_CLIENT_SECRET='${account.clientSecret}'

The SDK will read these values from the Node.js process environment and automatically configure itself.

### Add the dynamic API route
### Add the dynamic API route handler

Create an `auth` directory under the `pages/api` directory. Under this newly created `auth` directory, create a `[auth0].js` file. The path to your [dynamic API route](https://nextjs.org/docs/api-routes/dynamic-api-routes) file should then be `pages/api/auth/[auth0].js`.
Create a file at `app/api/auth/[auth0]/route.js`. This is your Route Handler file with a [Dynamic Route Segment](https://nextjs.org/docs/app/building-your-application/routing/route-handlers#dynamic-route-segments).

Then, import in that file the `handleAuth` method from the SDK, and export the result of calling it.
Then, import the `handleAuth` method from the SDK, and export the result of calling it from the `GET` export.

```javascript
// pages/api/auth/[auth0].js
// app/api/auth/[auth0]/route.js
import { handleAuth } from '@auth0/nextjs-auth0';

export default handleAuth();
export const GET = handleAuth();
```

This creates the following routes:
Expand All @@ -70,29 +70,26 @@ This creates the following routes:

### Add the `UserProvider` component

On the frontend side, the SDK uses React Context to manage the authentication state of your users. To make that state available to all your pages, you need to override the [App component](https://nextjs.org/docs/advanced-features/custom-app) and wrap its inner component with a `UserProvider`.
On the frontend side, the SDK uses React Context to manage the authentication state of your users. To make that state available to all your pages, you need to override the [Root Layout component](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required) and wrap the `<body>` tag with a `UserProvider` in the file `app/layout.jsx`.

:::note
Support for the new `app` directory is coming. Check out the [beta release](https://github.com/auth0/nextjs-auth0/issues/1235).
:::

Create the file `pages/_app.js` as follows:
Create the file `app/layout.jsx` as follows:

```jsx
// pages/_app.js
import React from 'react';
// app/layout.jsx
import { UserProvider } from '@auth0/nextjs-auth0/client';

export default function App({ Component, pageProps }) {
export default function RootLayout({ children }) {
return (
<html lang="en">
<UserProvider>
<Component {...pageProps} />
<body>{children}</body>
</UserProvider>
</html>
);
}
```

The authentication state exposed by `UserProvider` can be accessed in any component using the `useUser()` hook.
The authentication state exposed by `UserProvider` can be accessed in any Client Component using the `useUser()` hook.

:::panel Checkpoint
Now that you have added the dynamic route and `UserProvider`, run your application to verify that your application is not throwing any errors related to Auth0.
Expand Down Expand Up @@ -134,13 +131,18 @@ Add the logout link to your application. When you click it, verify that your Nex

## Show User Profile Information

The Auth0 Next.js SDK helps you retrieve the [profile information](https://auth0.com/docs/users/user-profiles) associated with the logged-in user, such as their name or profile picture, to personalize the user interface. The profile information is available through the `user` property exposed by the `useUser()` hook. Take this `Profile` component as an example of how to use it:
The Auth0 Next.js SDK helps you retrieve the [profile information](https://auth0.com/docs/users/user-profiles) associated with the logged-in user, such as their name or profile picture, to personalize the user interface.

### From a Client Component

The profile information is available through the `user` property exposed by the `useUser()` hook. Take this [Client Component](https://nextjs.org/docs/getting-started/react-essentials#client-components) as an example of how to use it:

```jsx
import React from 'react';
'use client';

import { useUser } from '@auth0/nextjs-auth0/client';

export default function Profile() {
export default function ProfileClient() {
const { user, error, isLoading } = useUser();

if (isLoading) return <div>Loading...</div>;
Expand All @@ -164,6 +166,28 @@ The `user` property contains sensitive information and artifacts related to the
- Ensure that the SDK has loaded successfully by checking that no `error` was produced.
- Check the `user` property to ensure that Auth0 has authenticated the user before React renders any component that consumes it.

### From a Server Component

The profile information is available through the `user` property exposed by the `getSession` function. Take this [Server Component](https://nextjs.org/docs/getting-started/react-essentials#server-components) as an example of how to use it:

```jsx
import { getSession } from '@auth0/nextjs-auth0';

export default async function ProfileServer() {
const { user } = await getSession();

return (
user && (
<div>
<img src={user.picture} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
)
);
}
```

:::panel Checkpoint
Verify that you can display the `user.name` or [any other](https://auth0.com/docs/users/user-profile-structure#user-profile-attributes) `user` property within a component correctly after you have logged in.
:::
Expand Down
19 changes: 0 additions & 19 deletions articles/quickstart/webapp/nextjs/files/app.md

This file was deleted.

4 changes: 2 additions & 2 deletions articles/quickstart/webapp/nextjs/files/auth.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: "[...auth0].js"
name: "app/api/[auth0]/route.js"
language: javascript
---

Expand All @@ -8,5 +8,5 @@ language: javascript
```javascript
import { handleAuth } from '@auth0/nextjs-auth0';

export default handleAuth();
export const GET = handleAuth();
```
20 changes: 20 additions & 0 deletions articles/quickstart/webapp/nextjs/files/layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: "app/layout.jsx"
language: jsx
---

<!-- markdownlint-disable MD041 -->

```jsx
import { UserProvider } from '@auth0/nextjs-auth0/client';

export default function RootLayout({ children }) {
return (
<html lang="en">
<UserProvider>
<body>{children}</body>
</UserProvider>
</html>
);
}
```
2 changes: 1 addition & 1 deletion articles/quickstart/webapp/nextjs/files/login.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: login.jsx
name: "app/login.jsx"
language: jsx
---

Expand Down
2 changes: 1 addition & 1 deletion articles/quickstart/webapp/nextjs/files/logout.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: logout.jsx
name: "app/logout.jsx"
language: jsx
---

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
---
name: profile.jsx
name: "app/profile-client/page.jsx"
language: jsx
---

<!-- markdownlint-disable MD041 -->

```jsx
import React from 'react';
'use client';

import { useUser } from '@auth0/nextjs-auth0/client';

export default function Profile() {
export default function ProfileClient() {
const { user, error, isLoading } = useUser();

if (isLoading) return <div>Loading...</div>;
Expand Down
24 changes: 24 additions & 0 deletions articles/quickstart/webapp/nextjs/files/profile-server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
name: "app/profile-server/page.jsx"
language: jsx
---

<!-- markdownlint-disable MD041 -->

```jsx
import { getSession } from '@auth0/nextjs-auth0';

export default async function ProfileServer() {
const { user } = await getSession();

return (
user && (
<div>
<img src={user.picture} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
)
);
}
```
2 changes: 1 addition & 1 deletion articles/quickstart/webapp/nextjs/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ seo_alias: nextjs
show_releases: true
show_steps: true
requirements:
- Next.js 10+
- Next.js 13.4+
default_article: 01-login
articles:
- 01-login
Expand Down
69 changes: 40 additions & 29 deletions articles/quickstart/webapp/nextjs/interactive.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ contentType: tutorial
useCase: quickstart
interactive: true
files:
- files/env
- files/auth
- files/app
- files/login
- files/logout
- files/profile
- files/auth
- files/env
- files/layout
- files/login
- files/logout
- files/profile-client
- files/profile-server
---

<!-- markdownlint-disable MD025 MD034 -->
Expand All @@ -39,7 +40,7 @@ Run the following command within your project directory to install the Auth0 Nex
npm install @auth0/nextjs-auth0
```

The SDK exposes methods and variables that help you integrate Auth0 with your Next.js application using [API Routes](https://nextjs.org/docs/api-routes/introduction) on the backend and [React Context](https://reactjs.org/docs/context.html) with [React Hooks](https://reactjs.org/docs/hooks-overview.html) on the frontend.
The SDK exposes methods and variables that help you integrate Auth0 with your Next.js application using [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) on the backend and [React Context](https://reactjs.org/docs/context.html) with [React Hooks](https://reactjs.org/docs/hooks-overview.html) on the frontend.

## Configure the SDK {{{ data-action=code data-code=".env.local" }}}

Expand All @@ -53,44 +54,40 @@ In the root directory of your project, add the file `.env.local` with the follow

The SDK will read these values from the Node.js process environment and automatically configure itself.

## Add the dynamic API route {{{ data-action=code data-code="[...auth0].js" }}}
## Add the dynamic Route Handler {{{ data-action=code data-code="app/api/[auth0]/route.js" }}}

Create an `auth` directory under the `pages/api` directory. Under this newly created `auth` directory, create a `[...auth0].js` file. The path to your [dynamic API route](https://nextjs.org/docs/api-routes/dynamic-api-routes) file should then be `pages/api/auth/[...auth0].js`.
Create a file at `app/api/auth/[auth0]/route.js`. This is your Route Handler file with a [Dynamic Route Segment](https://nextjs.org/docs/app/building-your-application/routing/route-handlers#dynamic-route-segments).

Then, import in that file the `handleAuth` method from the SDK, and export the result of calling it. This creates the following routes:
Then, import in that file the `handleAuth` method from the SDK, and export the result of calling it from the `GET` export. This creates the following routes:

- `/api/auth/login`: The route used to perform login with Auth0.
- `/api/auth/logout`: The route used to log the user out.
- `/api/auth/callback`: The route Auth0 will redirect the user to after a successful login.
- `/api/auth/me`: The route to fetch the user profile from.

## Add the `UserProvider` component {{{ data-action=code data-code="_app.jsx" }}}
## Add the `UserProvider` component {{{ data-action=code data-code="app/layout.jsx" }}}

On the frontend side, the SDK uses React Context to manage the authentication state of your users. To make that state available to all your pages, you need to override the [App component](https://nextjs.org/docs/advanced-features/custom-app) and wrap its inner component with a `UserProvider` in the file `pages/_app.jsx`.
On the frontend side, the SDK uses React Context to manage the authentication state of your users. To make that state available to all your pages, you need to override the [Root Layout component](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required) and wrap the `<body>` tag with a `UserProvider` in the file `app/layout.jsx`.

:::note
Support for the new `app` directory is coming. Check out the [beta release](https://github.com/auth0/nextjs-auth0/issues/1235).
:::

The authentication state exposed by `UserProvider` can be accessed in any component using the `useUser()` hook.
The authentication state exposed by `UserProvider` can be accessed in any Client Component using the `useUser()` hook.

::::checkpoint
:::checkpoint-default
Now that you have added the dynamic route and `UserProvider`, run your application to verify that your application is not throwing any errors related to Auth0.
Now that you have added the route handler and `UserProvider`, run your application to verify that your application is not throwing any errors related to Auth0.
:::
:::checkpoint-failure
Sorry about that. Here's a couple of things to double check:
* Are your environment variables populated correctly?
* did you put the `[...auth0].js` and `_app.jsx` files in the correct folder?
* did you put the `app/api/auth/[auth0]/route.js` and `app/layout.jsx` files in the correct folder?
* make sure the domain and client ID are configured correctly

Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help.
:::
::::

## Add Login to Your Application {{{ data-action=code data-code="login.jsx" }}}
## Add Login to Your Application {{{ data-action=code data-code="app/login.jsx" }}}

Users can now log in to your application by visiting the `/api/auth/login` route provided by the SDK. Add a link that points to the login route using an **anchor tag**. Clicking it redirects your users to the Auth0 Universal Login Page, where Auth0 can authenticate them. Upon successful authentication, Auth0 will redirect your users back to your application.
Users can now log in to your application by visiting the `/api/auth/login` route handler provided by the SDK. Add a link that points to the login route using an **anchor tag**. Clicking it redirects your users to the Auth0 Universal Login Page, where Auth0 can authenticate them. Upon successful authentication, Auth0 will redirect your users back to your application.

:::note
Next linting rules might suggest using the `Link` component instead of an anchor tag. The `Link` component is meant to perform [client-side transitions between pages](https://nextjs.org/docs/api-reference/next/link). As the link points to an API route and not to a page, you should keep it as an anchor tag.
Expand All @@ -115,7 +112,7 @@ Still having issues? Check out our [documentation](https://auth0.com/docs) or vi

<%= include('../_includes/_auth_note_dev_keys') %>

## Add Logout to Your Application {{{ data-action=code data-code="logout.jsx" }}}
## Add Logout to Your Application {{{ data-action=code data-code="app/logout.jsx" }}}

Now that you can log in to your Next.js application, you need [a way to log out](https://auth0.com/docs/logout/log-users-out-of-auth0). Add a link that points to the `/api/auth/logout` API route. Clicking it redirects your users to your [Auth0 logout endpoint](https://auth0.com/docs/api/authentication?javascript#logout) (`https://YOUR_DOMAIN/v2/logout`) and then immediately redirects them back to your application.

Expand All @@ -132,15 +129,11 @@ Still having issues? Check out our [documentation](https://auth0.com/docs) or vi
:::
::::

## Show User Profile Information {{{ data-action=code data-code="profile.jsx" }}}
## Show User Profile Information from a Client Component{{{ data-action=code data-code="app/profile-client/page.jsx" }}}

The Auth0 Next.js SDK helps you retrieve the [profile information](https://auth0.com/docs/users/user-profiles) associated with the logged-in user, such as their name or profile picture, to personalize the user interface. The profile information is available through the `user` property exposed by the `useUser()` hook. Take this `Profile` page component as an example of how to use it.
The Auth0 Next.js SDK helps you retrieve the [profile information](https://auth0.com/docs/users/user-profiles) associated with the logged-in user, such as their name or profile picture, to personalize the user interface.

The `user` property contains sensitive information and artifacts related to the user's identity. As such, its availability depends on the user's authentication status. To prevent any render errors:

- Ensure that the SDK has completed loading before accessing the `user` property by checking that `isLoading` is `false`.
- Ensure that the SDK has loaded successfully by checking that no `error` was produced.
- Check the `user` property to ensure that Auth0 has authenticated the user before React renders any component that consumes it.
The profile information is available through the `user` property exposed by the `useUser()` hook. Take this [Client Component](https://nextjs.org/docs/getting-started/react-essentials#client-components) `ProfileClient` as an example of how to use it.

::::checkpoint
:::checkpoint-default
Expand All @@ -155,3 +148,21 @@ Sorry about that. Here's a couple of things to double check:
Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help.
:::
::::

## Show User Profile Information from a Server Component{{{ data-action=code data-code="app/profile-server/page.jsx" }}}

The profile information is available through the `user` property exposed by the `getSession` function. Take this [Server Component](https://nextjs.org/docs/getting-started/react-essentials#server-components) `ProfileServer` as an example of how to use it.

::::checkpoint
:::checkpoint-default
Verify that you can display the `user.name` or [any other](https://auth0.com/docs/users/user-profile-structure#user-profile-attributes) `user` property within a component correctly after you have logged in.
:::
:::checkpoint-failure
Sorry about that. Here's a couple of things to double check:
* are your environment variables populated correctly?
* make sure you have successfully logged in through the `/api/auth/login` handler.
* make sure there are no errors in the console

Still having issues? Check out our [documentation](https://auth0.com/docs) or visit our [community page](https://community.auth0.com) to get more help.
:::
::::

0 comments on commit accdf14

Please sign in to comment.