-
Notifications
You must be signed in to change notification settings - Fork 27k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate auth0 example into Next.js repo (#8802)
* Add auth0 example * Apply suggestions from code review Co-Authored-By: Joe Haddad <joe.haddad@zeit.co> * Remove LICENSE * Add create next-app section * Update to latest @auth0/nextjs-auth0 * Update user handling * Update profile link to use <Link> * Update .env template to reflect guides * Simplify example * Update example to prefer API call (temporary hardcoded url) * Simplify state and ensure rerenders don’t race * Clear up import being commented * Make code style consistent * Update pages to reflect required auth on the client-side * Memoize the user on window * Update now.json instruction * Remove meta fields * Update docs with explanation * Update UI for auth0 example
- Loading branch information
1 parent
1ff5005
commit a73fb5d
Showing
18 changed files
with
547 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,6 @@ | ||
AUTH0_CLIENT_ID= | ||
AUTH0_DOMAIN= | ||
AUTH0_CLIENT_SECRET= | ||
REDIRECT_URI= | ||
POST_LOGOUT_REDIRECT_URI= | ||
SESSION_COOKIE_SECRET= |
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,3 @@ | ||
node_modules | ||
.env | ||
.next |
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,98 @@ | ||
# Next.js and Auth0 Example | ||
|
||
This example shows how you can use `@auth0/nextjs-auth` to easily add authentication support to your Next.js application. | ||
|
||
### Using `create-next-app` | ||
|
||
Execute [`create-next-app`](https://www.npmjs.com/package/create-next-app) with [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) or [npx](https://github.com/zkat/npx#readme) to bootstrap the example: | ||
|
||
```bash | ||
npx create-next-app --example auth0 auth0 | ||
# or | ||
yarn create next-app --example auth0 auth0 | ||
``` | ||
|
||
## Configuring Auth0 | ||
|
||
1. Go to the [Auth0 dashboard](https://manage.auth0.com/) and create a new application of type _Regular Web Applications_ and make sure to configure the following | ||
2. Go to the settings page of the application | ||
3. Configure the following settings: | ||
|
||
- _Allowed Callback URLs_: Should be set to `http://localhost:3000/api/callback` when testing locally or typically to `https://myapp.com/api/callback` when deploying your application. | ||
- _Allowed Logout URLs_: Should be set to `http://localhost:3000/` when testing locally or typically to `https://myapp.com/` when deploying your application. | ||
|
||
4. Save the settings | ||
|
||
### Configuring Next.js | ||
|
||
In the Next.js configuration file (`next.config.js`) you'll see that different environment variables are being assigned. | ||
|
||
### Local Development | ||
|
||
For local development you'll want to create a `.env` file with the necessary settings. | ||
|
||
The required settings can be found on the Auth0 application's settings page: | ||
|
||
``` | ||
AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN | ||
AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID | ||
AUTH0_CLIENT_SECRET=YOUR_AUTH0_CLIENT_SECRET | ||
SESSION_COOKIE_SECRET=viloxyf_z2GW6K4CT-KQD_MoLEA2wqv5jWuq4Jd0P7ymgG5GJGMpvMneXZzhK3sL (at least 32 characters, used to encrypt the cookie) | ||
REDIRECT_URI=http://localhost:3000/api/callback | ||
POST_LOGOUT_REDIRECT_URI=http://localhost:3000/ | ||
``` | ||
|
||
### Hosting on ZEIT Now | ||
|
||
When deploying this example to ZEIT Now you'll want to update the `now.json` configuration file. | ||
|
||
```json | ||
{ | ||
"build": { | ||
"env": { | ||
"AUTH0_DOMAIN": "YOUR_AUTH0_DOMAIN", | ||
"AUTH0_CLIENT_ID": "YOUR_AUTH0_CLIENT_ID", | ||
"AUTH0_CLIENT_SECRET": "@auth0_client_secret", | ||
"REDIRECT_URI": "https://my-website.now.sh/api/callback", | ||
"POST_LOGOUT_REDIRECT_URI": "https://my-website.now.sh/", | ||
"SESSION_COOKIE_SECRET": "@session_cookie_secret", | ||
"SESSION_COOKIE_LIFETIME": 7200 | ||
} | ||
} | ||
} | ||
``` | ||
|
||
- `AUTH0_DOMAIN` - Can be found in the Auth0 dashboard under `settings`. | ||
- `AUTH0_CLIENT_ID` - Can be found in the Auth0 dashboard under `settings`. | ||
- `AUTH0_CLIENT_SECRET` - Can be found in the Auth0 dashboard under `settings`. | ||
- `REDIRECT_URI` - The url where Auth0 redirects back to, make sure a consistent url is used here. | ||
- `POST_LOGOUT_REDIRECT_URI` - Where to redirect after logging out | ||
- `SESSION_COOKIE_SECRET` - A unique secret used to encrypt the cookies, has to be at least 32 characters. You can use [this generator](https://generate-secret.now.sh/32) to generate a value. | ||
- `SESSION_COOKIE_LIFETIME` - How long a session lasts in seconds. The default is 2 hours. | ||
|
||
The `@auth0_client_secret` and `@session_cookie_secret` are [ZEIT Now environment secrets](https://zeit.co/docs/v2/environment-variables-and-secrets/) | ||
|
||
You can create the `@auth0_client_secret` by running: | ||
|
||
``` | ||
now secrets add auth0_client_secret PLACE_YOUR_AUTH0_CLIENT_SECRET | ||
``` | ||
|
||
And create the `session_cookie_secret` by generating a value [here](https://generate-secret.now.sh/32) and running: | ||
|
||
``` | ||
now secrets add session_cookie_secret PLACE_YOUR_SESSION_COOKIE_SECRET | ||
``` | ||
|
||
## About this sample | ||
|
||
This sample tries to cover a few topics: | ||
|
||
- Signing in | ||
- Signing out | ||
- Loading the user on the server side and adding it as part of SSR (`/pages/advanced/srr-profile.js`) | ||
- Loading the user on the client side and using fast/cached SSR pages (`/pages/index.js`) | ||
- API Routes which can load the current user (`/pages/api/me.js`) | ||
- Using hooks to make the user available throughout the application (`/lib/user.js`) |
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,81 @@ | ||
import Link from 'next/link' | ||
|
||
function Header ({ user, loading }) { | ||
return ( | ||
<header> | ||
<nav> | ||
<ul> | ||
<li> | ||
<Link href='/'> | ||
<a>Home</a> | ||
</Link> | ||
</li> | ||
<li> | ||
<Link href='/about'> | ||
<a>About</a> | ||
</Link> | ||
</li> | ||
{!loading && | ||
(user ? ( | ||
<> | ||
<li> | ||
<Link href='/profile'> | ||
<a>Client-rendered profile</a> | ||
</Link> | ||
</li> | ||
<li> | ||
<Link href='/advanced/ssr-profile'> | ||
<a>Server rendered profile (advanced)</a> | ||
</Link> | ||
</li> | ||
<li> | ||
<a href='/api/logout'>Logout</a> | ||
</li> | ||
</> | ||
) : ( | ||
<li> | ||
<a href='/api/login'>Login</a> | ||
</li> | ||
))} | ||
</ul> | ||
</nav> | ||
|
||
<style jsx>{` | ||
header { | ||
padding: 0.2rem; | ||
color: #fff; | ||
background-color: #333; | ||
} | ||
nav { | ||
max-width: 42rem; | ||
margin: 1.5rem auto; | ||
} | ||
ul { | ||
display: flex; | ||
list-style: none; | ||
margin-left: 0; | ||
padding-left: 0; | ||
} | ||
li { | ||
margin-right: 1rem; | ||
} | ||
li:nth-child(2) { | ||
margin-right: auto; | ||
} | ||
a { | ||
color: #fff; | ||
text-decoration: none; | ||
} | ||
button { | ||
font-size: 1rem; | ||
color: #fff; | ||
cursor: pointer; | ||
border: none; | ||
background: none; | ||
} | ||
`}</style> | ||
</header> | ||
) | ||
} | ||
|
||
export default Header |
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,35 @@ | ||
import Head from 'next/head' | ||
import Header from './header' | ||
|
||
function Layout ({ user, loading = false, children }) { | ||
return ( | ||
<> | ||
<Head> | ||
<title>Next.js with Auth0</title> | ||
</Head> | ||
|
||
<Header user={user} loading={loading} /> | ||
|
||
<main> | ||
<div className='container'>{children}</div> | ||
</main> | ||
|
||
<style jsx>{` | ||
.container { | ||
max-width: 42rem; | ||
margin: 1.5rem auto; | ||
} | ||
`}</style> | ||
<style jsx global>{` | ||
body { | ||
margin: 0; | ||
color: #333; | ||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, | ||
Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; | ||
} | ||
`}</style> | ||
</> | ||
) | ||
} | ||
|
||
export default Layout |
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,14 @@ | ||
import { useAuth0 } from '@auth0/nextjs-auth0' | ||
|
||
export default useAuth0({ | ||
clientId: process.env.AUTH0_CLIENT_ID, | ||
clientSecret: process.env.AUTH0_CLIENT_SECRET, | ||
scope: process.env.AUTH0_SCOPE, | ||
domain: process.env.AUTH0_DOMAIN, | ||
redirectUri: process.env.REDIRECT_URI, | ||
postLogoutRedirectUri: process.env.POST_LOGOUT_REDIRECT_URI, | ||
session: { | ||
cookieSecret: process.env.SESSION_COOKIE_SECRET, | ||
cookieLifetime: process.env.SESSION_COOKIE_LIFETIME | ||
} | ||
}) |
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,70 @@ | ||
import { useState, useEffect } from 'react' | ||
import fetch from 'isomorphic-unfetch' | ||
|
||
export async function fetchUser (cookie = '') { | ||
if (typeof window !== 'undefined' && window.__user) { | ||
return window.__user | ||
} | ||
|
||
const res = await fetch( | ||
'/api/me', | ||
cookie | ||
? { | ||
headers: { | ||
cookie | ||
} | ||
} | ||
: {} | ||
) | ||
|
||
if (!res.ok) { | ||
delete window.__user | ||
return null | ||
} | ||
|
||
const json = await res.json() | ||
if (typeof window !== 'undefined') { | ||
window.__user = json | ||
} | ||
return json | ||
} | ||
|
||
export function useFetchUser ({ required } = {}) { | ||
const [loading, setLoading] = useState( | ||
() => !(typeof window !== 'undefined' && window.__user) | ||
) | ||
const [user, setUser] = useState(() => { | ||
if (typeof window === 'undefined') { | ||
return null | ||
} | ||
|
||
return window.__user || null | ||
}) | ||
|
||
useEffect(() => { | ||
if (!loading && user) { | ||
return | ||
} | ||
setLoading(true) | ||
let isMounted = true | ||
|
||
fetchUser().then(user => { | ||
// Only set the user if the component is still mounted | ||
if (isMounted) { | ||
// When the user is not logged in but login is required | ||
if (required && !user) { | ||
window.location.href = '/api/login' | ||
return | ||
} | ||
setUser(user) | ||
setLoading(false) | ||
} | ||
}) | ||
|
||
return () => { | ||
isMounted = false | ||
} | ||
}, []) | ||
|
||
return { user, loading } | ||
} |
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,17 @@ | ||
const dotenv = require('dotenv') | ||
dotenv.config() | ||
|
||
module.exports = { | ||
env: { | ||
AUTH0_DOMAIN: process.env.AUTH0_DOMAIN, | ||
AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID, | ||
AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET, | ||
AUTH0_SCOPE: 'openid profile', | ||
REDIRECT_URI: | ||
process.env.REDIRECT_URI || 'http://localhost:3000/api/callback', | ||
POST_LOGOUT_REDIRECT_URI: | ||
process.env.POST_LOGOUT_REDIRECT_URI || 'http://localhost:3000/', | ||
SESSION_COOKIE_SECRET: process.env.SESSION_COOKIE_SECRET, | ||
SESSION_COOKIE_LIFETIME: 7200 // 2 hours | ||
} | ||
} |
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,12 @@ | ||
{ | ||
"build": { | ||
"env": { | ||
"AUTH0_DOMAIN": "YOUR_AUTH0_DOMAIN", | ||
"AUTH0_CLIENT_ID": "YOUR_AUTH0_CLIENT_ID", | ||
"AUTH0_CLIENT_SECRET": "@auth0_client_secret", | ||
"REDIRECT_URI": "https://my-website.now.sh/api/callback", | ||
"POST_LOGOUT_REDIRECT_URI": "https://my-website.now.sh/", | ||
"SESSION_COOKIE_SECRET": "@session_cookie_secret" | ||
} | ||
} | ||
} |
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 @@ | ||
{ | ||
"name": "nextjs-auth0-example", | ||
"scripts": { | ||
"dev": "next", | ||
"build": "next build", | ||
"start": "next start" | ||
}, | ||
"author": "", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@auth0/nextjs-auth0": "0.2.0", | ||
"dotenv": "^8.1.0", | ||
"isomorphic-unfetch": "^3.0.0", | ||
"next": "latest", | ||
"react": "^16.9.0", | ||
"react-dom": "^16.9.0" | ||
} | ||
} |
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,21 @@ | ||
import React from 'react' | ||
|
||
import Layout from '../components/layout' | ||
import { useFetchUser } from '../lib/user' | ||
|
||
function About () { | ||
const { user, loading } = useFetchUser() | ||
|
||
return ( | ||
<Layout user={user} loading={loading}> | ||
<h1>About</h1> | ||
<p> | ||
This is the about page, navigating between this page and <i>Home</i> is | ||
always pretty fast. However, when you navigate to the <i>Profile</i>{' '} | ||
page it takes more time because it uses SSR to fetch the user first; | ||
</p> | ||
</Layout> | ||
) | ||
} | ||
|
||
export default About |
Oops, something went wrong.