How to add Google authentication to your Next.js + Liveblocks app with NextAuth.js
Learn how to use NextAuth.js to integrate Google authentication with your Next.js + Liveblocks application—enabling personalization with users' names, photos, and more throughout your product.
Many users own or use Google products, making it practical to use Google for
Single Sign-On (SSO) and authentication. SSO provides access to valuable
metadata that we can use for personalization in collaborative workspaces.
Additionally, implementing Single Sign-On improves security by allowing users to
bypass entering their password repeatedly.
Because we build the majority of our Liveblocks examples with Next.js (including
the Starter Kit), we recommend using Next.js providers
for authentication. If you don’t want to use
NextAuth.js, you can use the
Google Platform Library
for Google Single Sign On. Authentication providers and the client library are
the only officially supported ways to include Google SSO as of March 2023.
We will be updating the
Live Avatar Example to include Google
authentication. The Live Avatar Example is a Next.js application that uses
Liveblocks to create a collaborative avatar stack. The application is a great
starting point for adding authentication because it is a simple application that
uses Liveblocks to create a collaborative experience. These are the steps we
will take to add Google authentication to the Live Avatar Example:
NextAuth.js has the concept of Providers: services such as GitHub, Google,
etc. utilizing OAuth, which allows you to log in to your application using
existing credentials.
Similar to our Starter Kit guide in which we
detail how to get authentication credentials for GitHub and Auth0, we will
create Google credentials to enable Google as a provider.
First, navigate to Google Console. If
you do not already have an account setup, you need to create a Google account
and an associated project which is where you will generate credentials from.
Once you have created the new project, navigate to APIs and Services. From
the lefthand navigation, select Credentials and then + CREATE CREDENTIALS
from the top portion of the page. Select "CONFIGURE CONSENT SCREEN."
Set the "User Type" as External, and then Save. On the page that opens, fill
out your application information, setting your application domain to
http://localhost:3000 (or your production domain). Once you have filled out
the information, click Save.
The next page that will open is Scopes. Here, you can update the scopes to
access different information from a user's account. For more information, you
can review the
Google documentation.
For this example, we will use userinfo.email and userinfo.profile (these
pieces include the profile image, email, and name).
On the Test Users screen, you can add the Google accounts of people you will
allow to access your app. If you do not add a user to your list, they can
still log in with Google; however, their profile image will be empty.
Navigate back to Credentials and select + CREATE CREDENTIALS and select
OAuth client ID. On the next page, select Web application as the Application
type.
Name your client, and update Authorized JavaScript origin to
http://localhost:3000 and Authorized redirect URIs to
http://localhost:3000/api/auth/callback/google. Note that we use
localhost:3000 for local development, but you will want to update this
portion of the URI when your app is in production. At this point, you will
want to save your CLIENT_ID and CLIENT_SECRET. The CLIENT_SECRET will
not be revealed again; if you lose the value, you will have to regenerate it.
Now that we have the credentials for Google, we can bring them into our
Liveblocks application and use this information to set up our NextAuth.js
provider and populate our avatar profiles.
For this example, we will use the
Live Avatar Stack as the baseline for
implementing authentication. After cloning the Liveblocks repo, you should
navigate to the Live Avatar example like so:
First run npm install next-auth, npm install @svgr/webpack --save-dev, and
finally, npm install from this directory level to install all package
dependencies necessary for this example.
Generate two encrypted tokens for your Next.js app: a JWT_SECRET and a
NEXTAUTH_SECRET. The JWT_SECRET is used for local development with Next.js,
while the NEXTAUTH_SECRET is used in production.
To generate these values, we can run the following command:
openssl rand -base64 32 and copy the output of each for adding to your
env.local file.
In your env.local file, add the following values, and populate them:
$LIVEBLOCKS_SECRET_KEY="<your secret from the dashboard>"GOOGLE_CLIENT_ID="<your client id from the google console>"GOOGLE_CLIENT_SECRET="<your client secret from the google console>"NEXTAUTH_SECRET="<your NextAuth.js secret generated in the console in the previous step>"NEXTAUTH_URL="http://localhost:3000"JWT_SECRET="<your JWT secret generated in the console in the preivious step>"
Next we will create the next-auth-d.ts file which will expose the
SessionType to submodules across our app:
import{ User }from"../types";import NextAuth from"next-auth"; declaremodule"next-auth"{/** * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context */interfaceSession{ user: User;}}
The User type defined above is not defined by default, so we should add its
definition to a new types.ts file at the root directory level.
We will now add the Google Provider to pages/api/auth/[...nextauth].ts. This
file configures the authorization to Google, which will be called when we
implement sign-in and sign-out functionality further on in this tutorial.
Now that we have updated our authentication provider and ensured the types
defined from NextAuth.js are accessible, we will wrap our app in the
SessionProvider. Wrapping our application with the SessionProvider makes the
session object that NextAuth.js generates available across the various
components of your app. In our case, the session object would include your
Google email, name, and profile image.
At this point, we still have a few wiring pieces to hook up, namely,
authentication from Liveblocks where we will use the information provided by
Google to update our Liveblocks users, which will populate our Avatars.
We will be updating the file pages/api/auth.ts to do so.
First, we will create a utility function to import into our auth file. If you’re
familiar with the Starter Kit, you may have realized that this function is also
used there.
Create the following file in the pages/api/auth directory:
Now in pages/auth/auth.ts, update the auth function to use the session and to
pass that information to Liveblocks. We’re removing the random names and instead
using the profile data from Google.
Your auth.ts file should look like the following:
import{ authorize }from"@liveblocks/node";import{ NextApiRequest, NextApiResponse }from"next";import{ getServerSession }from"./auth/getServerSession";import{ User }from"../../types"; constAPI_KEY= process.env.LIVEBLOCKS_SECRET_KEY; exportdefaultasyncfunctionauth(req: NextApiRequest, res: NextApiResponse){if(!API_KEY){return res.status(403).end();}const session =awaitgetServerSession(req, res); const anonymousUser: User ={ name:"Anonymous", email:"none", image:"N/A",};const{ name, email, image }= session?.user ?? anonymousUser; // We're generating users and avatars here based off Google SSO metadata.//This is where you assign the// user based on their real identity from your auth provider.// See https://liveblocks.io/docs/api-reference/liveblocks-node#authorize for more informationconst response =awaitauthorize({ room: req.body.room, secret:API_KEY, userId:`user-${email}`, userInfo:{ name: name, picture: image,},});return res.status(response.status).end(response.body);}
Now that we have established connections between Liveblocks and Google, we need
to bring sign-in and redirect functionality into our room. First, we will set up
a redirect that checks for a user’s session before allowing them into a
Liveblocks room, and then we will create a sign-in page.
Update pages/index.tsx to getServerSideProps and enable redirect.
When running the app locally, you may notice that the avatar images are not
loading. This is because the referrer policy is set to
strict-origin-when-cross-origin by default. To fix this, update the referrer
policy on the Avatar component to no-referrer in components/Avatar.tsx:
importReactfrom"react";importstylesfrom"./Avatar.module.css"; constIMAGE_SIZE=48; exportfunctionAvatar({ picture, name }){return(<divclassName={styles.avatar}data-tooltip={name}><imgsrc={picture}height={IMAGE_SIZE}width={IMAGE_SIZE}className={styles.avatar_picture}referrerPolicy="no-referrer"/></div>);}
Before creating the sign-in page, we will add the Google SVG and configure our
local environment to use it.
Create a new folder called public in the project's root, and inside it, create
a folder called icons. Inside the icons folder, create a file called
google.svg and copy the following code into it:
Now we need to create a sign-in page. Users will be redirected to the sign-in
page if they are not logged in. We will use the next-auth/react package to
handle the authentication.
Create the signin page:
importstylesfrom"../components/SignIn.module.css"; import{GetServerSideProps}from"next";import{ getProviders }from"next-auth/react";import{ useSession, signIn }from"next-auth/react";import{ getServerSession }from"./api/auth/getServerSession";importButtonfrom"../components/Button";importGoogleIconfrom"../public/icons/google.svg"; interfaceProps{ providers:Awaited<ReturnType<typeof getProviders>>;} exportdefaultfunctionlogin({ providers }:Props){const{ data: session }=useSession();if(!session)return(<divclassName={styles.signin}><ButtonclassName={styles.googlebutton}onClick={()=>signIn("google")}><GoogleIcon/> Sign in with Google</Button></div>);} // If not logged in redirect to signinexportconst getServerSideProps:GetServerSideProps=async({ req, res })=>{const session =awaitgetServerSession(req, res);const providers =awaitgetProviders();console.log(providers); if(session){return{ redirect:{ permanent:false, destination:"/",},};} return{ props:{ providers },};};
We have completed the process of styling and adding the sign-in and sign out
functionality to the app. Now that we have completed these steps, we can run the
app and see our changes.
npm run dev
Open the console to localhost:3000, and you will see the sign-in screen.
We hope that this tutorial gives you the tools to populate avatars in a way that
enhances your collaborative experience while improving your understanding of how
authentication can work with NextAuth.js providers. Additionally, the
Starter Kit is pre-configured with NextAuth.js, which means you
can follow this tutorial to integrate personal data from Google into the
preconfigured avatars. If you want to checkout the source code for this example,
you can view it on
GitHub.
If you have any feedback or suggestions for future updates, please don’t
hesitate to reach out to us via email,
Twitter, or in our
Discord community.