Free preview
Configure Auth0
Part of End to End React with Prisma 2
Objective: Let's set up Auth0 so we have a way to verify who is making the request so we can tell if they have access to or not.
Create an account with Auth0 and then create a new single page application. Go to settings and copy the Domain, Client ID, Client Secret to the following environmental variables in the .env file in the project root (not the prisma folder).
.env
DATABASE_URL=postgresql://user:password@endpoint:5432/database_name
AUTH0_CLIENTID=your_auth0_client_id
AUTH0_DOMAIN=your_auth0_domain
AUTH0_CLIENT_SECRET=your_auth0_client_secret
AUTH0_SCOPE='openid profile'
AUTH0_COOKIE_SECRET='some_greater_than_40_character_string_can_be_anything'
BACKEND_ADDRESS=http://localhost:3000
Install the Auth0 Nextjs package:
npm install --save @auth0/nextjs-auth0 dotenv @apollo/client graphql
utils/apolloClient.ts
import { useMemo } from 'react'
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
import getConfig from 'next/config'
const { publicRuntimeConfig } = getConfig()
const { BACKEND_URL } = publicRuntimeConfig
let apolloClient
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: new HttpLink({
uri: BACKEND_URL, // Server URL (must be absolute)
credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
}),
cache: new InMemoryCache({}),
})
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient()
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
// Get existing cache, loaded during client side data fetching
const existingCache = _apolloClient.extract()
// Restore the cache using the data passed from getStaticProps/getServerSideProps
// combined with the existing cached data
_apolloClient.cache.restore({ ...existingCache, ...initialState })
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
export function useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState])
return store
}
utils/auth0.ts
import { initAuth0 } from '@auth0/nextjs-auth0'
import getConfig from 'next/config'
const { serverRuntimeConfig } = getConfig()
const { auth, cookieSecret } = serverRuntimeConfig
export default initAuth0({
...auth,
session: {
cookieSecret,
cookieLifetime: 60 * 60 * 8,
storeIdToken: false,
storeAccessToken: false,
storeRefreshToken: false,
},
oidcClient: {
httpTimeout: 2500,
clockTolerance: 10000,
},
})
next.config.js
require('dotenv').config()
const {
AUTH0_CLIENTID,
AUTH0_DOMAIN,
AUTH0_CLIENT_SECRET,
AUTH0_SCOPE,
AUTH0_COOKIE_SECRET,
BACKEND_ADDRESS,
} = process.env
module.exports = {
publicRuntimeConfig: {
BACKEND_URL: `${BACKEND_ADDRESS}/api/graphql`,
},
serverRuntimeConfig: {
auth: {
domain: AUTH0_DOMAIN,
clientId: AUTH0_CLIENTID,
clientSecret: AUTH0_CLIENT_SECRET,
scope: AUTH0_SCOPE,
redirectUri: `${BACKEND_ADDRESS}/api/callback`,
postLogoutRedirectUri: `${BACKEND_ADDRESS}/`,
},
cookieSecret: AUTH0_COOKIE_SECRET,
},
}
Make sure to restart the server by pressing ctrl+c on the terminal window and starting it back up again with npm run dev.
pages/api/login.ts
import auth0 from '../../utils/api/auth0'
export default async function login(req, res) {
try {
await auth0.handleLogin(req, res, {})
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
}
pages/api/logout.ts
import auth0 from '../../utils/api/auth0'
export default async function logout(req, res) {
try {
await auth0.handleLogout(req, res)
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
}
pages/api/me.ts
import auth0 from '../../utils/api/auth0'
export default async function me(req, res) {
try {
await auth0.handleProfile(req, res)
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
}
pages/callback.ts
import auth0 from '../../utils/api/auth0'
export default async function callback(req, res) {
try {
await auth0.handleCallback(req, res, { redirectTo: '/' })
} catch (error) {
console.error(error)
res.status(error.status || 500).end(error.message)
}
}