Pocketbase OAuth on NextJS

Pocketbase OAuth on NextJS

A simple tutorial on implementing Google & GitHub OAuth in NextJS using Pocketbase

·

9 min read

A brief introduction to Pocketbase & NextJS

Most of you folks must have already heard about Pocketbase and also about Next.JS and that's why you are here in the first place. But for the newbies out there here's a small intro.

Pocketbase is an “Open Source backend for your next SaaS and Mobile app in 1 file” and that's true literally!! It is written in the Go language and it consists of:

  • embedded database (SQLite) with real-time subscriptions

  • built-in files and users management along with S3 support

  • an Admin dashboard UI built using Svelte

  • and a simple REST-ish API

At the time of writing this Pocketbase is in beta at version 0.13.1 and is in active development. They’ve also created client-side SDKs for JavaScript and Dart. Do check out their documentation and GitHub. I love the amazing stuff their team is building. Also, you can play a little bit around the gopher on their website which is pretty cool 😄.

NextJs website

Next.JS is a JavaScript framework developed by the Vercel team which lets you build amazing web apps using React with server-side and static rendering. Nowadays it is much more than that and is the go-to React Framework. NextJs for me has made working with React honestly a fun and enjoyable experience.

Installing Pocketbase

Now onto the fun part. Let's install pocketbase on our local system.
Go on to their official docs and then download the zip file specific to your OS which is just around 14 MB!! I downloaded the Linux version for my system.

Now create a new folder in your system like pocketbase-oauth and unzip the downloaded zip file in that folder. You can find the pocketbase executable in the folder and that’s it — the entire backend in 1 file.

To start our pocketbase just open a new terminal in the folder and then type:

./pocketbase serve

You will get an output similar to this if the server started successfully.

2023/03/05 21:06:13 Server started at http://127.0.0.1:8090
➜ REST API: http://127.0.0.1:8090/api/
➜ Admin UI: http://127.0.0.1:8090/_/

If you go to the Admin UI url from the terminal at http://127.0.0.1:8090/_/ output you will be greeted with the following webpage:

Pocketbase Admin create

This is a one-time configuration. You need to provide an admin email and a password to create an admin account which is required to log into the admin page. After login, you can view something like this:

If you get up to this point… Congrats🎉. You have successfully installed and set up Pocketbase in your system.

Configuring Google OAuth

For adding google auth to pocketbase first we need to create a new project in google cloud which is free. Give any project name that you like and click on create. You will be greeted with the project dashboard.

Now to set up google oAuth in pocketbase we need a Client ID and Client Secret. For that, we need to go to the OAuth consent screen from the side menu > APIs & Services > OAuth consent screen.

Oauth consent screen

Select User Type as External and click on create. Now fill the first page with details about our app. You can provide any details that you like. Only the App Name, User support email, and developer email are required to be filled in for our purpose. The rest of the details must be required if you are building a production application.

On the next page for scopes click on ADD OR REMOVE SCOPES and then select the following three scopes from the drawer on the right and then click on update for OAuth to work:

OAuth scopes

After updating the scopes save and continue to the next page to add Test users, which is completely optional. Save and continue into the Summary page and then go to the dashboard.

Now go to the Credentials page from the left menu > Create Credentials > OAuth client ID.

OAuth client ID

Now, select the application type as a Web application and then provide a name. For Authorized JavaScript origins and Authorized redirect URIs set the values as the following:

Setting authorized URIs

Now click on create. The OAuth client will be created and a pop-up modal will appear displaying your Your Client ID and Your Client Secret. Do not close the modal yet, or copy the values, or you can access these values later under OAuth 2.0 Client IDs on the same page.

Google OAuth Client ID and secret

Now go back to our Pocketbase admin panel then go to Settings > Auth providers > Google, enable it, and paste our client ID and client secret we got earlier. And then save these changes.

Setup google oauth

Configuring GitHub OAuth

Phew… Configuring Google OAuth was a real pain😅. But for GitHub, this process is much easier. So let's start. First, click on your GitHub avatar and go to Settings > Developer settings > OAuth Apps and then click on New OAuth App. Or just go directly to this link which does the same. Now fill out the form with the following details and then register.

GitHub OAuth

The Application name can be whatever you like. Now we must generate our Client ID and Client Secret for GitHub. Click on Generate a new client secret and you will get something similar to this.

GitHub OAuth Client ID and secret

Copy both the Client ID and Client secret and go to our Pocketbase admin panel and then Settings > Auth providers > GitHub, enable it, and then paste in the Client ID and secret we got earlier. Now click save changes and that's it. We have successfully enabled both Google and GitHub OAuth in Pocketbase🎉🎉

Some things to note: If you have noticed I have pasted http://localhost:3000/signin as redirect url and authorization callback url in Google and GitHub respectively because by default NextJs runs on port 3000. If your NextJS application is running on a different port, change these urls accordingly. Also when running in production changes these values to your website URL.

Some more minor configs with Pocketbase

This part is optional. If we need to collect the profile image from Google or GitHub accounts which are used to sign in to our applications. For that, we need to add a new field avatarUrl in the Users collection. Go to Pocketbase Admin Ui and then to Collections > Users > Edit collection (settings icon) > New field and then provide type URL and field name avatarUrl and then save the changes.

Configuring avatarUrl

Create a new NextJS project

Now that we have set up our Pocketbase successfully we can begin creating our NextJS app. Here I’m using NextJs version 13.2 with TypeScript, but without the app directory which is currently experimental. Also, I’m using pnpm for this tutorial instead of npm or yarn which is completely up to your preference. To create a new project type:

pnpm create next-app --typescript

Provide a project name and continue with the defaults. Open the project folder in VSCode (or any IDE that you are using). Start the NextJS development server using:

npm run dev

The server now starts at http://localhost:3000. You can view the website by going to this URL.

Default NextJS starter page

Now we need to install the Pocketbase SDK as a dependency on this project. For that use:

pnpm install pocketbase

And that's it, our basic project creation is done. Now let's continue by configuring our Pocketbase SDK.

Configuring Pocketbase in NextJS

First, create a .env.local file in the project root folder and add the following env for Pocketbase:

NEXT_PUBLIC_PB_URL=http://localhost:8090

Now create a new lib folder in the project root and create a new file pocketbase.ts as follows:

Basically, in this file Pocketbase is configured with the URL we provided in the env and exports the pb object to be used anywhere within our app. Also, I’ve set pb.autoCancellation to false only when the server is in development mode. Auto cancellation is a feature of pocketbase that cancels duplicated requests. For more details check out here. But since NextJs uses React strict mode, every component is rendered twice and this auto cancellation feature can result in request failure in NextJS even if the request was processed fine.

Setting up OAuth in our app

Now let's create an AuthWrapper which holds all the authentication states, user data, and helper functions and use the useContext hook to make it globally available to our application. For that create a new folder contexts and then a new file AuthWrapper.tsx as follows:

Here we are exporting googleSignIn, githubSignIn, setUserData, and signOut functions along with the user object storing the user data via a new usePbAuth hook which is created using the useContext hook so that we can use them globally in our application. Also, I have created types for the user object and context. To use these functions we can just import the usePbAuth hook and destructure them inside any component as follows:

const { user, googleSignIn, githubSignIn, setUserData, signOut } = usePbAuth()

Now we need to wrap our app in pages/_app.tsx with the AuthWrapper we just exported. For that, we can wrap the <Component/> as follows:

Now we can create our signin page. There we can implement both our sign-in logic as well as two buttons for signing in via Google and GitHub OAuth. You can copy the following code to the pages/signin.tsx file.

As you can see there are two buttons Sign in with Google and Sign in with GitHub. On clicking either one of these buttons the page will be redirected to their respective sign-in pages. On signing in from those pages we will be redirected back to our signin page. If you check the current page URL you can see a lot of parameters that contain our login information which will be handled by the useEffect block. There we extract the data from the parameters and provide them to the Pocketbase OAuth login function. On successful login get our name and avatarUrl from the response and store it in our Pocketbase database. We have successfully completed our task🎉

View our profile on sign in

Now that our OAuth sign-in part is completed we can edit our pages/index.tsx file to display the SignIn button, our profile details, and the SignOut button. So edit the index.tsx file as follows:

Here the page will display the SignIn button which when clicked redirects to the sign-in page. If the user is signed in, then the user details will be shown similarly to this:

User details

Username is automatically generated by Pocketbase. We can change them later. This is just a basic implementation. The entire code for this tutorial is available on my GitHub:

Go check out my website at abilsavio.dev to know more about me and the cool stuff I’m building.