-
Notifications
You must be signed in to change notification settings - Fork 161
Migration of sample app to Nexjs SDK v4 #180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
eb7332c
7c9b31e
cdac62a
8e266d7
e8ff516
a6e6654
6db82c2
9ade2bb
8790154
ab85e21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
{ | ||
"presets": ["next/babel"] | ||
} | ||
"presets": [ | ||
"@babel/preset-env", | ||
["@babel/preset-react", { "runtime": "automatic" }], | ||
"@babel/preset-typescript" | ||
], | ||
"plugins": [] | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
AUTH0_SECRET=replace-with-your-own-secret-generated-with-openssl | ||
AUTH0_BASE_URL=http://localhost:3000 | ||
AUTH0_ISSUER_BASE_URL='https://{DOMAIN}' | ||
AUTH0_CLIENT_ID='{CLIENT_ID}' | ||
AUTH0_CLIENT_SECRET='{CLIENT_SECRET}' | ||
AUTH0_AUDIENCE= | ||
AUTH0_SCOPE='openid profile' | ||
APP_BASE_URL=http://localhost:3000 | ||
AUTH0_DOMAIN={DOMAIN} | ||
AUTH0_CLIENT_ID={CLIENT_ID} | ||
AUTH0_CLIENT_SECRET={CLIENT_SECRET} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,14 @@ | ||
# Auth0 Next.js SDK Sample Application | ||
|
||
This sample demonstrates the integration of [Auth0 Next.js SDK](https://github.com/auth0/nextjs-auth0) into a Next.js application created using [create-next-app](https://nextjs.org/docs/api-reference/create-next-app). The sample is a companion to the [Auth0 Next.js SDK Quickstart](https://auth0.com/docs/quickstart/webapp/nextjs). | ||
This sample demonstrates the integration of [Auth0 Next.js SDK v4](https://github.com/auth0/nextjs-auth0) into a Next.js application created using [create-next-app](https://nextjs.org/docs/api-reference/create-next-app). The sample is a companion to the [Auth0 Next.js SDK Quickstart](https://auth0.com/docs/quickstart/webapp/nextjs). | ||
|
||
This sample demonstrates the following use cases: | ||
|
||
- [Login](https://github.com/auth0-samples/auth0-nextjs-samples/blob/main/Sample-01/components/NavBar.jsx#L61-L67) | ||
- [Logout](https://github.com/auth0-samples/auth0-nextjs-samples/blob/main/Sample-01/components/NavBar.jsx#L93-L95) | ||
- [Showing the user profile](https://github.com/auth0-samples/auth0-nextjs-samples/blob/main/Sample-01/pages/profile.jsx) | ||
- [Protecting client-side rendered pages](https://github.com/auth0-samples/auth0-nextjs-samples/blob/main/Sample-01/pages/profile.jsx#L43-L46) | ||
- [Calling APIs](https://github.com/auth0-samples/auth0-nextjs-samples/blob/main/Sample-01/pages/external.jsx) | ||
- Login | ||
- Logout | ||
- Showing the user profile | ||
- Protecting routes using middleware | ||
- Calling APIs with access tokens | ||
tusharpandey13 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Project setup | ||
|
||
|
@@ -22,37 +22,329 @@ npm install | |
|
||
### Create an API | ||
|
||
For the **External API** page to work, you will need to [create an API](https://auth0.com/docs/authorization/apis) using the [management dashboard](https://manage.auth0.com/#/apis). This will give you an API Identifier that you can use in the `AUTH0_AUDIENCE` environment variable below. Then you will need to [add a permission](https://auth0.com/docs/get-started/dashboard/add-api-permissions) named `read:shows` to your API. To get your app to ask for that permission, include it in the value of the `AUTH0_SCOPE` environment variable. | ||
For the **External API** page to work, you will need to [create an API](https://auth0.com/docs/authorization/apis) using the [management dashboard](https://manage.auth0.com/#/apis). This will give you an API Identifier that you can use in the `AUTH0_AUDIENCE` environment variable below. Then you will need to [add a permission](https://auth0.com/docs/get-started/dashboard/add-api-permissions) named `read:shows` to your API. | ||
tusharpandey13 marked this conversation as resolved.
Show resolved
Hide resolved
tusharpandey13 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
If you do not wish to use an API or observe the API call working, you should not specify the `AUTH0_AUDIENCE` and `AUTH0_SCOPE` values in the next steps. | ||
If you do not wish to use an API or observe the API call working, you should not specify the `AUTH0_AUDIENCE` value in the next steps. | ||
tusharpandey13 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AUTH0_AUDIENCE? |
||
|
||
### Configure credentials | ||
|
||
The project needs to be configured with your Auth0 Domain, Client ID and Client Secret for the authentication flow to work. | ||
|
||
To do this, first copy `.env.local.example` into a new file in the same folder called `.env.local`, and replace the values with your own Auth0 application credentials (see more info about [loading environmental variables in Next.js](https://nextjs.org/docs/basic-features/environment-variables)): | ||
To do this, first copy `.env.local.example` into a new file in the same folder called `.env.local`, and replace the values with your own Auth0 application credentials: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this link (https://nextjs.org/docs/basic-features/environment-variables) no longer relevant? |
||
|
||
```sh | ||
# A long secret value used to encrypt the session cookie | ||
AUTH0_SECRET='LONG_RANDOM_VALUE' | ||
# The base url of your application | ||
AUTH0_BASE_URL='http://localhost:3000' | ||
# The url of your Auth0 tenant domain | ||
AUTH0_ISSUER_BASE_URL='https://YOUR_AUTH0_DOMAIN.auth0.com' | ||
# Your Auth0 application's Client ID | ||
AUTH0_CLIENT_ID='YOUR_AUTH0_CLIENT_ID' | ||
# Your Auth0 application's Client Secret | ||
AUTH0_CLIENT_SECRET='YOUR_AUTH0_CLIENT_SECRET' | ||
# Your Auth0 API's Identifier | ||
# OMIT if you do not want to use the API part of the sample | ||
AUTH0_AUDIENCE='YOUR_AUTH0_API_IDENTIFIER' | ||
# The permissions your app is asking for | ||
# OMIT if you do not want to use the API part of the sample | ||
AUTH0_SCOPE='openid profile email read:shows' | ||
# Your Auth0 tenant domain | ||
AUTH0_DOMAIN='YOUR_AUTH0_DOMAIN.auth0.com' | ||
# The base url of your application | ||
APP_BASE_URL='http://localhost:3000' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we keep the order, so we simplify the diff? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Order isnt maintained |
||
``` | ||
|
||
**Note**: Make sure you replace `AUTH0_SECRET` with your own secret (you can generate a suitable string using `openssl rand -hex 32` on the command line). | ||
|
||
## Step-by-Step Implementation Guide | ||
|
||
This guide will walk you through integrating Auth0 with Next.js using the Auth0 Next.js SDK v4. | ||
|
||
### Step 1: Create a Next.js App | ||
|
||
If you don't have an existing Next.js application, create one using: | ||
|
||
```bash | ||
npx create-next-app@latest my-auth0-app | ||
cd my-auth0-app | ||
``` | ||
|
||
### Step 2: Install the Auth0 SDK | ||
|
||
Install the Auth0 Next.js SDK v4: | ||
|
||
```bash | ||
npm install @auth0/nextjs-auth0@4.2.0 | ||
``` | ||
|
||
### Step 3: Set Up Auth0 Configuration | ||
|
||
1. **Set up your Auth0 account**: | ||
- Sign up for an Auth0 account at [https://auth0.com](https://auth0.com) if you don't have one | ||
- Create a new application in the Auth0 Dashboard | ||
- Choose "Regular Web Application" as the application type | ||
|
||
2. **Configure Auth0 application settings**: | ||
- Set the "Allowed Callback URLs" to `http://localhost:3000/auth/callback` | ||
- Set the "Allowed Logout URLs" to `http://localhost:3000` | ||
- Set the "Allowed Web Origins" to `http://localhost:3000` | ||
|
||
3. **Create the environment variables file**: | ||
- Create a `.env.local` file in your project root with the following variables: | ||
|
||
|
||
```sh | ||
# A long secret value used to encrypt the session cookie | ||
AUTH0_SECRET='LONG_RANDOM_VALUE' | ||
# The base url of your application | ||
APP_BASE_URL='http://localhost:3000' | ||
# Your Auth0 application's Client ID | ||
AUTH0_CLIENT_ID='YOUR_AUTH0_CLIENT_ID' | ||
# Your Auth0 application's Client Secret | ||
AUTH0_CLIENT_SECRET='YOUR_AUTH0_CLIENT_SECRET' | ||
``` | ||
|
||
### Step 4: Initialize the Auth0 Client | ||
|
||
Create a file at `lib/auth0.ts` with the following content: | ||
|
||
```typescript | ||
import { Auth0Client } from "@auth0/nextjs-auth0/server"; | ||
|
||
export const auth0 = new Auth0Client({ | ||
// Options are loaded from environment variables by default | ||
authorizationParameters: { | ||
scope: "openid profile email", | ||
} | ||
}); | ||
``` | ||
|
||
If you need to call an API, adjust the scope to include the required permissions: | ||
|
||
```typescript | ||
authorizationParameters: { | ||
scope: "openid profile email read:shows", | ||
} | ||
``` | ||
|
||
### Step 5: Set Up Middleware for Route Protection | ||
|
||
Create a file named `middleware.ts` in your project root: | ||
|
||
```typescript | ||
import type { NextRequest } from "next/server"; | ||
import { auth0 } from "./lib/auth0"; | ||
|
||
export async function middleware(request: NextRequest) { | ||
return await auth0.middleware(request); | ||
} | ||
|
||
export const config = { | ||
matcher: [ | ||
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", | ||
], | ||
}; | ||
``` | ||
|
||
This middleware will handle authentication for all routes except static assets. | ||
|
||
### Step 6: Create a Profile Page | ||
|
||
Create a profile page to display user information at `app/profile/page.tsx`: | ||
|
||
```typescript | ||
import { auth0 } from "../../lib/auth0"; | ||
import { redirect } from "next/navigation"; | ||
|
||
export default async function ProfilePage() { | ||
const session = await auth0.getSession(); | ||
|
||
// Redirect to login if not authenticated | ||
if (!session?.user) { | ||
return redirect("/auth/login"); | ||
} | ||
|
||
return ( | ||
<div> | ||
<h1>Profile</h1> | ||
<h2>{session.user.name}</h2> | ||
<p>{session.user.email}</p> | ||
<img src={session.user.picture} alt="Profile" width="100" /> | ||
|
||
<pre>{JSON.stringify(session.user, null, 2)}</pre> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
### Step 7: Create Navigation Component | ||
|
||
Create a navigation component with login/logout buttons at `components/NavBar.tsx`: | ||
|
||
```typescript | ||
import Link from "next/link"; | ||
import { auth0 } from "../lib/auth0"; | ||
|
||
export default async function NavBar() { | ||
const session = await auth0.getSession(); | ||
const isAuthenticated = !!session?.user; | ||
|
||
return ( | ||
<nav> | ||
<ul style={{ display: "flex", gap: "1rem", listStyle: "none" }}> | ||
<li> | ||
<Link href="/">Home</Link> | ||
</li> | ||
{isAuthenticated && ( | ||
<li> | ||
<Link href="/profile">Profile</Link> | ||
</li> | ||
)} | ||
<li> | ||
{isAuthenticated ? ( | ||
<a href="/auth/logout">Logout</a> | ||
) : ( | ||
<a href="/auth/login">Login</a> | ||
)} | ||
</li> | ||
</ul> | ||
</nav> | ||
); | ||
} | ||
``` | ||
|
||
### Step 8: Integrate API Access (Optional) | ||
|
||
If you want to access an external API with the user's access token, create an API route: | ||
|
||
```typescript | ||
// app/api/shows/route.js | ||
import { auth0 } from '../../../lib/auth0'; | ||
import { NextResponse } from 'next/server'; | ||
|
||
export async function GET(req) { | ||
// Check if user is authenticated | ||
const session = await auth0.getSession(); | ||
if (!session) { | ||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); | ||
} | ||
|
||
try { | ||
// Get access token | ||
const { accessToken } = await auth0.getAccessToken(); | ||
|
||
const apiPort = process.env.API_PORT || 3001; | ||
const response = await fetch(`http://localhost:${apiPort}/api/shows`, { | ||
headers: { | ||
Authorization: `Bearer ${accessToken}` | ||
} | ||
}); | ||
const shows = await response.json(); | ||
|
||
return NextResponse.json(shows); | ||
} catch (error) { | ||
console.error('Auth0 or API error:', error); | ||
return NextResponse.json({ error: error.message }, { status: error.status || 500 }); | ||
} | ||
} | ||
``` | ||
|
||
### Step 9: Update Root Layout | ||
|
||
Add the NavBar to your root layout at `app/layout.tsx`: | ||
|
||
```typescript | ||
import { Inter } from 'next/font/google'; | ||
import NavBar from '../components/NavBar'; | ||
|
||
const inter = Inter({ subsets: ['latin'] }); | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<html lang="en"> | ||
<body className={inter.className}> | ||
<NavBar /> | ||
<main>{children}</main> | ||
</body> | ||
</html> | ||
); | ||
} | ||
``` | ||
|
||
### Step 11: Start your Application | ||
|
||
Start your Next.js application: | ||
|
||
```bash | ||
npm run dev | ||
``` | ||
|
||
Visit http://localhost:3000 and test the authentication flow. | ||
|
||
## Key Changes in v4 | ||
|
||
This sample has been updated to use Auth0 NextJS SDK v4, which includes several important changes: | ||
|
||
1. **New Auth0Client Class**: We now use the `Auth0Client` from `@auth0/nextjs-auth0/server` which provides a simpler API. | ||
|
||
2. **Middleware-based Protection**: Route protection now uses Next.js middleware instead of higher-order components or hooks for server-side protection. | ||
|
||
3. **App Router Support**: The sample now works with Next.js App Router, with API routes implemented as route handlers. | ||
|
||
5. **Environment Variables**: The configuration has been simplified with the required environment variables loaded automatically. | ||
|
||
## Implementation Details | ||
|
||
### Auth0 Client Initialization | ||
|
||
```typescript | ||
// lib/auth0.ts | ||
import { Auth0Client } from "@auth0/nextjs-auth0/server"; | ||
|
||
export const auth0 = new Auth0Client({ | ||
// Options are loaded from environment variables by default | ||
authorizationParameters: { | ||
scope: "openid profile email offline_access read:shows", | ||
} | ||
}); | ||
``` | ||
|
||
### Middleware for Route Protection | ||
|
||
```typescript | ||
// middleware.ts | ||
import type { NextRequest } from "next/server" | ||
import { auth0 } from "./lib/auth0" | ||
|
||
export async function middleware(request: NextRequest) { | ||
return await auth0.middleware(request) | ||
} | ||
|
||
export const config = { | ||
matcher: [ | ||
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", | ||
], | ||
} | ||
``` | ||
|
||
### API Route Implementation | ||
|
||
```javascript | ||
// app/api/shows/route.js | ||
import { auth0 } from '../../../lib/auth0'; | ||
import { NextResponse } from 'next/server'; | ||
|
||
export async function GET(req) { | ||
const session = await auth0.getSession(); | ||
if (!session) { | ||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); | ||
} | ||
|
||
try { | ||
const { accessToken } = await auth0.getAccessToken(); | ||
// Use the access token to call your API | ||
// ... | ||
} catch (error) { | ||
// Error handling | ||
} | ||
} | ||
``` | ||
|
||
## Run the sample | ||
|
||
### Compile and hot-reload for development | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this neccessary to update the SDK?