Skip to content

Commit 55560e0

Browse files
Convert auth0 example to TypeScript (vercel#38087)
Converted auth0 example over to TypeScript to match the Contribution guidelines, and got rid of the `tslib` dependency. Note: You must copy `.env.local.example` to `.env.local`, or you will encounter "TypeError: "secret" is required" at build time. ## Documentation / Examples - [X] Make sure the linting passes by running `pnpm lint` - [X] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples) Co-authored-by: Balázs Orbán <[email protected]>
1 parent bbffaea commit 55560e0

24 files changed

+161
-67
lines changed

Diff for: examples/auth0/.env.local.example

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Public Environment variables that can be used in the browser.
2-
NEXT_PUBLIC_AUTH0_CLIENT_ID=
2+
NEXT_PUBLIC_AUTH0_CLIENT_ID=TEST
33
NEXT_PUBLIC_AUTH0_SCOPE="openid profile"
4-
NEXT_PUBLIC_AUTH0_DOMAIN=
4+
NEXT_PUBLIC_AUTH0_DOMAIN="http://example.com"
55
NEXT_PUBLIC_BASE_URL="http://localhost:3000"
66
NEXT_PUBLIC_REDIRECT_URI="/api/callback"
77
NEXT_PUBLIC_POST_LOGOUT_REDIRECT_URI="/"

Diff for: examples/auth0/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,6 @@ yarn-error.log*
3232

3333
# vercel
3434
.vercel
35+
36+
# typescript
37+
*.tsbuildinfo

Diff for: examples/auth0/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ This example shows how you can use `@auth0/nextjs-auth` to easily add authentica
44

55
- Signing in
66
- Signing out
7-
- Loading the user on the server side and adding it as part of SSR ([`pages/advanced/ssr-profile.js`](pages/advanced/ssr-profile.js))
8-
- Loading the user on the client side and using fast/cached SSR pages ([`pages/index.js`](pages/index.js))
9-
- API Routes which can load the current user ([`pages/api/me.js`](pages/api/me.js))
10-
- Using hooks to make the user available throughout the application ([`lib/user.js`](lib/user.js))
7+
- Loading the user on the server side and adding it as part of SSR ([`pages/advanced/ssr-profile.ts`](pages/advanced/ssr-profile.ts))
8+
- Loading the user on the client side and using fast/cached SSR pages ([`pages/index.ts`](pages/index.ts))
9+
- API Routes which can load the current user ([`pages/api/me.ts`](pages/api/me.ts))
10+
- Using hooks to make the user available throughout the application ([`lib/user.ts`](lib/user.ts))
1111

1212
Read more: [https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/](https://auth0.com/blog/ultimate-guide-nextjs-authentication-auth0/)
1313

Diff for: examples/auth0/additional.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export {}
2+
3+
declare global {
4+
interface Window {
5+
__user: any
6+
}
7+
}

Diff for: examples/auth0/components/header.js renamed to examples/auth0/components/header.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import Link from 'next/link'
22

3-
function Header({ user, loading }) {
3+
type HeaderProps = {
4+
user?: any
5+
loading: boolean
6+
}
7+
8+
const Header = ({ user, loading }: HeaderProps) => {
49
return (
510
<header>
611
<nav>

Diff for: examples/auth0/components/layout.js renamed to examples/auth0/components/layout.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import Head from 'next/head'
22
import Header from './header'
33

4-
function Layout({ user, loading = false, children }) {
4+
type LayoutProps = {
5+
user?: any
6+
loading?: boolean
7+
children: React.ReactNode
8+
}
9+
10+
const Layout = ({ user, loading = false, children }: LayoutProps) => {
511
return (
612
<>
713
<Head>

Diff for: examples/auth0/interfaces/index.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export type User = {
2+
email: string
3+
email_verified: boolean
4+
name: string
5+
nickname: string
6+
picture: string
7+
sub: string
8+
updated_at: string
9+
}

Diff for: examples/auth0/lib/auth0.js renamed to examples/auth0/lib/auth0.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { initAuth0 } from '@auth0/nextjs-auth0'
2+
import { SignInWithAuth0 } from '@auth0/nextjs-auth0/dist/instance'
23

3-
export default initAuth0({
4+
const auth0: SignInWithAuth0 = initAuth0({
45
secret: process.env.SESSION_COOKIE_SECRET,
56
issuerBaseURL: process.env.NEXT_PUBLIC_AUTH0_DOMAIN,
67
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
@@ -19,6 +20,8 @@ export default initAuth0({
1920
scope: process.env.NEXT_PUBLIC_AUTH0_SCOPE,
2021
},
2122
session: {
22-
absoluteDuration: process.env.SESSION_COOKIE_LIFETIME,
23+
absoluteDuration: Number(process.env.SESSION_COOKIE_LIFETIME),
2324
},
2425
})
26+
27+
export default auth0

Diff for: examples/auth0/lib/user.js renamed to examples/auth0/lib/user.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { UserProfile } from '@auth0/nextjs-auth0'
12
import { useState, useEffect } from 'react'
23

34
export async function fetchUser(cookie = '') {
@@ -21,14 +22,16 @@ export async function fetchUser(cookie = '') {
2122
return null
2223
}
2324

24-
const json = await res.json()
25+
const json: UserProfile = await res.json()
2526
if (typeof window !== 'undefined') {
2627
window.__user = json
2728
}
2829
return json
2930
}
3031

31-
export function useFetchUser({ required } = {}) {
32+
export function useFetchUser(
33+
{ required }: { required: boolean } = { required: false }
34+
) {
3235
const [loading, setLoading] = useState(
3336
() => !(typeof window !== 'undefined' && window.__user)
3437
)

Diff for: examples/auth0/next-env.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.

Diff for: examples/auth0/package.json

+9-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66
"start": "next start"
77
},
88
"dependencies": {
9-
"@auth0/nextjs-auth0": "^1.4.2",
9+
"@auth0/nextjs-auth0": "^1.9.1",
1010
"next": "latest",
11-
"react": "^17.0.2",
12-
"react-dom": "^17.0.2",
13-
"tslib": "^2.2.0"
11+
"react": "^18.2.0",
12+
"react-dom": "^18.2.0"
13+
},
14+
"devDependencies": {
15+
"@types/node": "^18.0.0",
16+
"@types/react": "^18.0.14",
17+
"@types/react-dom": "^18.0.5",
18+
"typescript": "^4.7.4"
1419
}
1520
}

Diff for: examples/auth0/pages/about.js renamed to examples/auth0/pages/about.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Layout from '../components/layout'
22
import { useFetchUser } from '../lib/user'
33

4-
function About() {
4+
const About = () => {
55
const { user, loading } = useFetchUser()
66

77
return (

Diff for: examples/auth0/pages/advanced/ssr-profile.js renamed to examples/auth0/pages/advanced/ssr-profile.tsx

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
import { GetServerSideProps } from 'next'
2+
13
// This import is only included in the server build, because it's only used by getServerSideProps
24
import auth0 from '../../lib/auth0'
35
import Layout from '../../components/layout'
6+
import { User } from '../../interfaces'
7+
8+
type ProfileProps = {
9+
user: User
10+
}
411

5-
function Profile({ user }) {
12+
const Profile = ({ user }: ProfileProps) => {
613
return (
714
<Layout user={user}>
815
<h1>Profile</h1>
@@ -17,18 +24,14 @@ function Profile({ user }) {
1724
)
1825
}
1926

20-
export async function getServerSideProps({ req, res }) {
27+
export const getServerSideProps: GetServerSideProps = async ({ req, res }) => {
2128
// Here you can check authentication status directly before rendering the page,
2229
// however the page would be a serverless function, which is more expensive and
2330
// slower than a static page with client side authentication
2431
const session = await auth0.getSession(req, res)
2532

2633
if (!session || !session.user) {
27-
res.writeHead(302, {
28-
Location: '/api/login',
29-
})
30-
res.end()
31-
return
34+
return { redirect: { destination: '/api/login', permanent: false } }
3235
}
3336

3437
return { props: { user: session.user } }

Diff for: examples/auth0/pages/api/callback.js

-10
This file was deleted.

Diff for: examples/auth0/pages/api/callback.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next'
2+
import auth0 from '../../lib/auth0'
3+
4+
const callback = async (req: NextApiRequest, res: NextApiResponse) => {
5+
try {
6+
await auth0.handleCallback(req, res)
7+
} catch (error) {
8+
console.error(error)
9+
const errorMessage =
10+
error instanceof Error ? error.message : 'Internal server error'
11+
res.status(500).end(errorMessage)
12+
}
13+
}
14+
15+
export default callback

Diff for: examples/auth0/pages/api/login.js

-10
This file was deleted.

Diff for: examples/auth0/pages/api/login.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next'
2+
import auth0 from '../../lib/auth0'
3+
4+
const login = async (req: NextApiRequest, res: NextApiResponse) => {
5+
try {
6+
await auth0.handleLogin(req, res)
7+
} catch (error) {
8+
console.error(error)
9+
const errorMessage =
10+
error instanceof Error ? error.message : 'Internal server error'
11+
res.status(500).end(errorMessage)
12+
}
13+
}
14+
15+
export default login

Diff for: examples/auth0/pages/api/logout.js

-10
This file was deleted.

Diff for: examples/auth0/pages/api/logout.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next'
2+
import auth0 from '../../lib/auth0'
3+
4+
const logout = async (req: NextApiRequest, res: NextApiResponse) => {
5+
try {
6+
await auth0.handleLogout(req, res)
7+
} catch (error) {
8+
console.error(error)
9+
const errorMessage =
10+
error instanceof Error ? error.message : 'Internal server error'
11+
res.status(500).end(errorMessage)
12+
}
13+
}
14+
15+
export default logout

Diff for: examples/auth0/pages/api/me.js

-10
This file was deleted.

Diff for: examples/auth0/pages/api/me.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next'
2+
import auth0 from '../../lib/auth0'
3+
4+
const me = async (req: NextApiRequest, res: NextApiResponse) => {
5+
try {
6+
await auth0.handleProfile(req, res)
7+
} catch (error) {
8+
console.error(error)
9+
const errorMessage =
10+
error instanceof Error ? error.message : 'Internal server error'
11+
res.status(500).end(errorMessage)
12+
}
13+
}
14+
15+
export default me

Diff for: examples/auth0/pages/index.js renamed to examples/auth0/pages/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Layout from '../components/layout'
22
import { useFetchUser } from '../lib/user'
33

4-
function Home() {
4+
const Home = () => {
55
const { user, loading } = useFetchUser()
66

77
return (

Diff for: examples/auth0/pages/profile.js renamed to examples/auth0/pages/profile.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
// import auth0 from '../lib/auth0'
33
import { useFetchUser } from '../lib/user'
44
import Layout from '../components/layout'
5+
import { User } from '../interfaces'
56

6-
function ProfileCard({ user }) {
7+
type ProfileCardProps = {
8+
user: User
9+
}
10+
11+
const ProfileCard = ({ user }: ProfileCardProps) => {
712
return (
813
<>
914
<h1>Profile</h1>
@@ -18,7 +23,7 @@ function ProfileCard({ user }) {
1823
)
1924
}
2025

21-
function Profile() {
26+
const Profile = () => {
2227
const { user, loading } = useFetchUser({ required: true })
2328

2429
return (

Diff for: examples/auth0/tsconfig.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"lib": ["dom", "dom.iterable", "esnext"],
5+
"allowJs": true,
6+
"skipLibCheck": true,
7+
"strict": false,
8+
"forceConsistentCasingInFileNames": true,
9+
"noEmit": true,
10+
"esModuleInterop": true,
11+
"module": "esnext",
12+
"moduleResolution": "node",
13+
"resolveJsonModule": true,
14+
"isolatedModules": true,
15+
"jsx": "preserve",
16+
"incremental": true
17+
},
18+
"include": ["next-env.d.ts", "additional.d.ts", "**/*.ts", "**/*.tsx"],
19+
"exclude": ["node_modules"]
20+
}

0 commit comments

Comments
 (0)