How to Use Google OAuth2 with Laravel Socialite for User Authentication

Arlind Musliu cofounder at Lucky Media
Arlind Musliu

January 14, 2025 · 5 min read

How to Use Google OAuth2 with Laravel Socialite for User Authentications

Integrating Google OAuth2 into your Laravel application is an excellent way to offer users a seamless login experience using their Google accounts. Laravel Socialite simplifies this process by providing a straightforward way to authenticate with various providers, including Google. This guide will walk you through setting up Google OAuth2 in your Laravel app and we also have another guide for Microsoft OAuth2 integration.

Besides the official Laravel Socialite package that supports Google, Facebook, X, LinkedIn, GitHub, GitLab, Bitbucket, and Slack, the community package SocialiteProviders also supports integrations like Apple, Steam, Instagram, Discord, Reddit, Snapchat, Telegram, Threads, TikTok, Yahoo, Dropbox, Twitch, Asana, Trello, Zoom, Spotify and many more.

We will also save the user’s last login method on that specific device, so we can show it to them on their next login attempt. This will help prevent users from registering for multiple accounts with both Google and Microsoft.

microsoft google oauth login laravel socialite

Step 1: Create a Google Cloud Project

To use Google OAuth2, you need to have a Google Cloud Project. Here’s how to set it up:

Create a Google Cloud Project

  • Go to the Google Cloud Console.

  • Click on the link that says "Create or select a project".

  • Enter a name for your project and click "Create".

google socialite create a new project laravel oath socialite

Enable APIs and Services

  • From the Dashboard, navigate to the "Quick Access" section.

  • Click on "APIs & Services".

google console project api and services laravel oath socialite
  • Select "OAuth consent screen" from the left sidebar.

  • If prompted, choose Go to new experience to access the updated interface.

google console project oauth consent screen laravel oath socialite
  • Fill in the following information:

    • App Name: Enter your application's name, for example "socialite"

    • Support Email: Provide an email address for user support.

    • User Type: Choose "External" to allow any Google user to authenticate.

    • Contact Email: Enter a contact email for Google to reach you.

  • Complete the setup by clicking "Save and Continue" and agreeing to the terms.

google console project app information laravel oath socialite

Choose "External" for the audience:

google console socialite project audience laravel oath

Create OAuth Client Credentials

  • Go to the "Credentials" tab in the APIs & Services section.

  • Click on "Create Credentials" and select "OAuth client ID".

google console project api and services credentials laravel oath socialite

If you can’t continue with the next step, wait a few minutes and then try again.

Configure OAuth Client

  • Choose "Web application" as the application type.

  • Under "Authorized redirect URIs", add the URLs where Google will send users after they authenticate. For local development, you might use http://localhost:8000/auth/google/callback. For production, use your app’s URL, like https://socialite.com/auth/google/callback.

  • Click "Create" to generate the credentials.

google console project authorized URIs laravel oath socialite

Retrieve Your Client ID and Secret

  • After creation, you’ll see a dialog with your new client ID and client secret.

  • Copy these values and add them to your Laravel .env file.

google console project get client secret laravel oath socialite

Step 2: Install Laravel Socialite Package

To enable OAuth2 authentication with providers like Google in your Laravel application, you’ll need to install the Laravel Socialite package. Follow these steps:

Install Laravel Socialite

Use Composer to install the Socialite package:

composer require laravel/socialite

Update Environment Variables

Add the necessary environment variables for Google to your .env file. You’ll use the client IDs and secrets obtained from the project creation step:

GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:8000/auth/google/callback

Step 3: Configure Laravel Backend

Update the services file

Add configurations for Google OAuth services at the config/services.php file:

return [

    // Rest of the code

    'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect' => env('GOOGLE_REDIRECT_URI'),
    ],
];

Set Up Routing

Define routes for redirecting to Google and handling the callbacks on the routes/auth.php file:

use App\Http\Controllers\Auth\LoginUserViaSocialiteController;
use Illuminate\Support\Facades\Route;

// Rest of the code

Route::get('auth/{provider}/redirect', [LoginUserViaSocialiteController::class, 'create'])->where('provider', 'google|microsoft');
Route::get('auth/{provider}/callback', [LoginUserViaSocialiteController::class, 'store'])->where('provider', 'google|microsoft');

Create the Controller

Implement the LoginUserViaSocialiteController controller methods to handle OAuth redirection and callback:

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;

class LoginUserViaSocialiteController extends Controller
{
    public function create($provider)
    {
        // Redirect the user to the Google/Microsoft login page
        return Socialite::driver($provider)->redirect();
    }

    public function store($provider)
    {
        // Get the user from the Google/Microsoft callback
        $socialiteUser = Socialite::driver($provider)->user();

        // Check if the user exists
        $user = User::where('email', $socialiteUser->getEmail())->first();

        // If the user does not exist, do not log them in and redirect them to the login page
        if (!$user) {
            return redirect()->route('login');
        }

        // Update the user's socialite_id and socialite_token
        $user->update([
            'socialite_id' => $socialiteUser->getId(),
            'socialite_token' => $socialiteUser->token,
        ]);

        // Log the user in
        Auth::login($user);

        // Redirect the user to the dashboard
        return redirect(route('dashboard'));
    }
}

Step 4: Add Authentication Buttons in the Frontend

Create Login View

In your login view, add buttons for Google login. Also, include logic to display the tooltip indicating the last used login method.

import Checkbox from '@/components/checkbox'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import InputError from '@/components/ui/input-error'
import InputLabel from '@/components/ui/input-label'
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip'
import GuestLayout from '@/layouts/guest-layout'
import { Head, Link, useForm } from '@inertiajs/react'
import { FormEventHandler } from 'react'

import { useLocalStorage } from '@/hooks/useLocalStorage'
import SVG from 'react-inlinesvg'

export default function Login({
  status,
  canResetPassword,
}: {
  status?: string
  canResetPassword: boolean
}) {
  const { data, setData, post, processing, errors, reset } = useForm({
    email: '',
    password: '',
    remember: false,
  })

  const { setItem, getItem } = useLocalStorage('lastLoginMethod')

  const submit: FormEventHandler = (e) => {
    e.preventDefault()

    post(route('login'), {
      onFinish: () => {
        reset('password')
        setItem('Email')
      },
    })
  }

  const handleSocialLogin = (
    e: React.MouseEvent<HTMLSpanElement>,
    method: string,
    url: string
  ) => {
    e.preventDefault()

    setItem(method)
    window.location.href = url
  }

  return (
    <GuestLayout>
      <Head title="Log in" />

      {status && (
        <div className="mb-4 text-center font-medium text-green-600 text-sm">
          {status}
        </div>
      )}

      <div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
        <div className="flex flex-col space-y-2 text-center">
          <h1 className="font-semibold text-2xl tracking-tight">
            Log in to your account
          </h1>
          <p className="text-muted-foreground text-sm">
            Enter your email below to create your account
          </p>
        </div>

        <div className="grid gap-6">
          <form onSubmit={submit}>
            <div className="grid gap-2">
              <InputLabel htmlFor="email" value="Email" className="sr-only" />
              <Input
                id="email"
                type="email"
                name="email"
                value={data.email}
                placeholder="name@example.com"
                className="mt-1 block w-full"
                autoCapitalize="none"
                autoComplete="email"
                autoCorrect="off"
                onChange={(e) => setData('email', e.target.value)}
              />
              <InputError message={errors.email} className="mt-2" />
            </div>

            <div className="mt-4">
              <InputLabel
                htmlFor="password"
                value="Password"
                className="sr-only"
              />
              <Input
                id="password"
                type="password"
                name="password"
                value={data.password}
                className="mt-1 block w-full"
                autoComplete="current-password"
                onChange={(e) => setData('password', e.target.value)}
              />
              <InputError message={errors.password} className="mt-2" />
            </div>

            <div className="mt-4 block">
              <label
                htmlFor="remember"
                className="flex items-center justify-between"
              >
                <div>
                  <Checkbox
                    name="remember"
                    checked={data.remember}
                    onChange={(e) => setData('remember', e.target.checked)}
                  />
                  <span className="ms-2 text-gray-600 text-sm">
                    Remember me
                  </span>
                </div>
                {canResetPassword && (
                  <Link
                    href={route('password.request')}
                    className="rounded-md text-gray-600 text-sm underline hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
                  >
                    Forgot your password?
                  </Link>
                )}
              </label>
            </div>

            <LastLoginMethod defaultOpen={getItem() === 'Email'}>
              <Button className="mt-4 w-full" disabled={processing}>
                Sign In with Email
              </Button>
            </LastLoginMethod>
          </form>

          <div className="relative">
            <div className="absolute inset-0 flex items-center">
              <span className="w-full border-t" />
            </div>
            <div className="relative flex justify-center text-xs uppercase">
              <span className="bg-background px-2 text-muted-foreground">
                Or continue with
              </span>
            </div>
          </div>

          <div className="flex flex-col space-y-2">
            <LastLoginMethod defaultOpen={getItem() === 'Google'}>
              <Button
                asChild
                type="button"
                variant="outline"
                className="w-full"
                onClick={(e) =>
                  handleSocialLogin(e, 'Google', '/auth/google/redirect')
                }
              >
                <span className="hover:cursor-pointer">
                  <SVG src="/svg/google.svg" className="mr-2 size-5" />
                  Login with Google
                </span>
              </Button>
            </LastLoginMethod>

            <LastLoginMethod defaultOpen={getItem() === 'Microsoft'}>
              <Button
                asChild
                type="button"
                variant="outline"
                className="w-full"
                onClick={(e) =>
                  handleSocialLogin(e, 'Microsoft', '/auth/microsoft/redirect')
                }
              >
                <span className="hover:cursor-pointer">
                  <SVG src="/svg/microsoft.svg" className="mr-2 size-5" />
                  Login with Microsoft
                </span>
              </Button>
            </LastLoginMethod>

            {getItem() !== undefined ? (
              <p className="my-4 text-center font-medium text-gray-600 text-sm">
                Your last login method was with: {getItem()}
              </p>
            ) : null}
          </div>
        </div>
      </div>
    </GuestLayout>
  )
}

Store and Retrieve User’s Last Login Method:

  • When a user logs in via any method, store their choice (Google, Microsoft, or email) in the session or user profile.

  • Display this information as a tooltip or message in the login view.

This component uses a tooltip to provide feedback on the last used login method.

const LastLoginMethod = ({
  children,
  defaultOpen,
}: {
  children: React.ReactElement
  defaultOpen: boolean
}) => {
  return (
    <TooltipProvider>
      <Tooltip defaultOpen={defaultOpen}>
        <TooltipTrigger asChild>{children}</TooltipTrigger>
        <TooltipContent side="right">
          <p>Last used</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  )
}

Note: Use localhost instead of .test

As for the development mode, don’t use a `.test` URL for this project. We’ve configured the Google project to work with http://localhost:8000/. You’ll need to serve your app through `php artisan serve` and access it with `localhost`. If you want to skip the frontend code and only test the backend, simply visit the route http://localhost:8000/auth/google/redirect and it should redirect you to the Google authentication page.

Conclusion

You can now integrate Google OAuth2 into your Laravel application using the official Laravel Socialite package. This allows users to sign in with their Google accounts, making the login process more seamless and enhancing the security of your application.


Bring Your Ideas to Life 🚀

If you need help with a Laravel project let’s get in touch.

Lucky Media is proud to be recognized as a leading Laravel Development Agency

Technologies

Laravel
Arlind Musliu cofounder at Lucky Media
Arlind Musliu

Cofounder and CFO of Lucky Media

Stay up-to-date

Be updated with all news, products and tips we share!

Let’s chat

We partner with a limited number of brands each quarter to ensure senior-level attention on every project.

lokman and arlind headshots
Teamwork