End to End React with Prisma 2
Start at the beginning and work your way through this project. The code for each step as well as the finished project can be found in the Github repository.
3. Configure Auth0
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_nameAUTH0_CLIENTID=your_auth0_client_idAUTH0_DOMAIN=your_auth0_domainAUTH0_CLIENT_SECRET=your_auth0_client_secretAUTH0_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
ts
import { useMemo } from 'react'import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'import getConfig from 'next/config'const { publicRuntimeConfig } = getConfig()const { BACKEND_URL } = publicRuntimeConfiglet apolloClientfunction 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 hereif (initialState) {// Get existing cache, loaded during client side data fetchingconst 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 Clientif (typeof window === 'undefined') return _apolloClient// Create the Apollo Client once in the clientif (!apolloClient) apolloClient = _apolloClientreturn _apolloClient}export function useApollo(initialState) {const store = useMemo(() => initializeApollo(initialState), [initialState])return store}
utils/auth0.ts
ts
import { initAuth0 } from '@auth0/nextjs-auth0'import getConfig from 'next/config'const { serverRuntimeConfig } = getConfig()const { auth, cookieSecret } = serverRuntimeConfigexport default initAuth0({...auth,session: {cookieSecret,cookieLifetime: 60 * 60 * 8,storeIdToken: false,storeAccessToken: false,storeRefreshToken: false,},oidcClient: {httpTimeout: 2500,clockTolerance: 10000,},})
next.config.js
js
require('dotenv').config()const {AUTH0_CLIENTID,AUTH0_DOMAIN,AUTH0_CLIENT_SECRET,AUTH0_SCOPE,AUTH0_COOKIE_SECRET,BACKEND_ADDRESS,} = process.envmodule.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
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
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
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
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)}}