Authentication
In this first part we'll implement user authentication with the pocketbase social OAUTH providers 
I'll use google and GitHub but they support a dozen more.
- Obtaining client id and client secret from the providers setting up GitHub OAUTH
then enable the respective providers in the pocketbase admin dashboard
- frontend integration using the pocketbase client
const authData = await pb.collection('devs').authWithOAuth2(
    'google',
    'CODE',
    'VERIFIER',
    'REDIRECT_URL',
    // optional data that will be used for the new account on OAuth2 sign-up
    {
      'name': 'test',
    },
);
to get the required arguments we need to fetch the enabled providers
the start function
first we get some icons for the respective providers
import { TheIcon } from '@denniskinuthia/tiny-pkgs';
import { FaGithub,FaGoogle } from 'react-icons/fa'
const providerIcons={
github:FaGithub,
google:FaGoogle
}
then
const providers = await client.collection("devs").listAuthMethods()
initiate login function using:
const startLogin = (prov:ProvType) => {
   localStorage.setItem("provider",JSON.stringify(prov));
  const redirectUrl = "http://localhost:3000/redirect";
  const url = prov.authUrl + redirectUrl;
      // console.log("prov in button === ", prov)
      // console.log("combined url ==== >>>>>>  ",url)
    if (typeof window !== "undefined") {
      window.location.href = url;
    }
  };
note: the redirect URL should match what you provided in the setup process: once you've hosted your website you can use your actual domain instead of localhost
then we'll map over them and render out a button for each provider
    <div className="w-full h-fit md:h-full flex flex-wrap items-center justify-center gap-2 ">
      {provs &&
        provs?.map((item:any) => {
          return (
            <div
              key={item.name}
              onClick={() => startLogin(item)} 
              className="p-2 w-[50%] md:w-[30%] cursor-pointer
               bg-slate-600 rounded-lg hover:bg-slate-800 
             capitalize text-xl font-bold flex items-center justify-center gap-2"
            >
            <TheIcon
            iconstyle="" 
            Icon={providerIcons[item.name as keyof typeof providerIcons]}
            size={'30'}
            />
              {item.name}
            </div>
          );
        })}
    </div>
finally the redirect component
remember to define a route for it in your react router config
Click to expand Redirect.tsx
Redirect.tsx
import React, { useEffect } from 'react'
import { useNavigate } from 'react-router-dom';
import { PBUser } from '../../utils/types/types';
import { useQueryClient } from '@tanstack/react-query';
import { client } from './../../utils/pb/config';
import { LoadingRipples } from '@denniskinuthia/tiny-pkgs';
import { redirect_url } from '../../utils/env';
import { login_url } from './../../utils/env';
interface RedirectProps {
user?:PBUser
}
export const Redirect: React.FC<RedirectProps> = ({user}) => {
const queryClient = useQueryClient()
const navigate = useNavigate()
const local_prov = JSON.parse(localStorage.getItem('provider') as string)
const url = new URL(window.location.href);
const code = url.searchParams.get('code') as string
const state = url.searchParams.get('state') as string
// this hasto match what you orovided in the oauth provider , in tis case google
let redirectUrl = redirect_url
useEffect(()=>{
    const pbOauthLogin=async()=>{
   client.autoCancellation(false)
    const oauthRes = await client.collection('devs')
    .authWithOAuth2(local_prov.name, code, local_prov.codeVerifier, redirectUrl)
        await client.collection('devs').update(oauthRes?.record.id as string, {
            avatar: oauthRes.meta?.avatarUrl,
            accessToken: oauthRes.meta?.accessToken
        })
    queryClient.setQueryData(['user'], client.authStore.model)
    navigate('/')
    }
    if (local_prov.state !== state) {
      const url = login_url
     if (typeof window !== 'undefined') {
            window.location.href = url;
        }
    }
    else {
    pbOauthLogin().catch((e) => {
    console.log("error logging in with provider  == ", e)
    })
    }
},[])
return (
 <div className='w-full h-full flex items-center justify-center'>
<LoadingRipples/>
</div>
);
}
Note: I used client.autoCancellation(false) to avoid the OAUTH request getting auto cancelled in dev mode because of react strict mode
finally we can put in place route AUTH guards , I prefer to do it at the root layout level inside which every other route is nested
Click to expand RootLayout.tsx
RootLayout.tsx
import React from 'react'
import { Outlet, useNavigate } from 'react-router-dom';
import { Toolbar } from '../../components/toolbar/Toolbar';
import { PBUser } from '../../utils/types/types';
interface RootLayoutProps {
user : PBUser
test_mode:boolean
}
export const RootLayout: React.FC = ({user,test_mode}) => {
    const navigate = useNavigate()
    React.useEffect(() => {
        if (!user?.email&&!test_mode) {
            navigate('/auth')
        }
    }, [user?.email])
return (
);
}
 
 
              


 
    
Top comments (0)