Google Oauth Authentication from Scratch in Laravel
Login with Google from Scratch in Laravel 10 In this step-by-step guide, we'll learn how to implement Google authentication in Laravel 10 without relying on any external authentication packages. Instead, we'll use Google's OAuth 2.0 API endpoints directly, making the integration more customizable. This method ensures better control over the Google login process and enhances user experience with a smooth, secure authentication flow.
Table of Contents
Step 2: Basic Authentication
Run the following commands to add authentication scaffolding:
composer require laravel/ui
php artisan ui bootstrap --auth
npm install
This will set up basic authentication views and routes, which you can customize.
Step 3: Configure Google OAuth 2.0 Credentials
Set up a project on Google Developers Console and add your Authorized Redirect URI, e.g., http://127.0.0.1:8000/auth/google/callback
Step 4: Configure Environment Variables
In your .env file, add:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=http://127.0.0.1:8000/auth/google/callback
These values will be used for the OAuth 2.0 flow to authenticate users via Google.
Step 5: Database Migration Setup
We need to update the users table to store additional information for Google login, such as the google_id and picture_url. Modify the create_user_table migration file as follows:
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('google_id')->nullable();
$table->string('picture_url')->nullable();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->rememberToken();
$table->timestamps();
});
Now, update the User model to include the new fields in the $fillable array:
protected $fillable = [
'name',
'email',
'google_id',
'picture_url'
]
Run this command to add tables in db.
php artisan migrate
Step 6: Create the Google Login Controller
Next, create a new controller to handle the Google login logic:
php artisan make: controller GoogleController
In this controller, we’ll implement two main methods: one to redirect to Google's OAuth service, and another to handle the callback.
public function redirectToGoogle()
{
$clientId = env('GOOGLE_CLIENT_ID');
$redirectUri = env('GOOGLE_REDIRECT_URI');
$scope = 'email%20profile'; // Requesting email and profile permissions
// Redirect to Google's OAuth 2.0 authorization endpoint
return redirect("https://accounts.google.com/o/oauth2/auth?client_id=$clientId&redirect_uri=$redirectUri&response_type=code&scope=$scope");
}
Purpose: This function generates a URL that directs the user to Google's OAuth 2.0 login page.
- clientId: The GOOGLE_CLIENT_ID from your .env file (your app's identifier in Google's OAuth system).
- redirectUri: The URL to which Google will redirect the user after authorization, specified by GOOGLE_REDIRECT_URI in the .env file.
- scope: This specifies what user data you're requesting permission for (email and profile in this case).
- OAuth Flow: Redirects the user to the Google authorization page where the user can grant your app permission to access their data.
public function handleGoogleCallback(Request $request)
{
$code = $request->query('code');
if (empty($code)) {
return response()->json(['error' => 'Authorization code not provided'], 400);
}
$clientId = env('GOOGLE_CLIENT_ID');
$clientSecret = env('GOOGLE_CLIENT_SECRET');
$redirectUri = env('GOOGLE_REDIRECT_URI');
$response = Http::post('https://accounts.google.com/o/oauth2/token', [
'code' => $code,
'client_id' => $clientId,
'client_secret' => $clientSecret,
'redirect_uri' => $redirectUri,
'grant_type' => 'authorization_code',
]);
$tokens = $response->json();
if (isset($tokens['access_token'])) {
$accessToken = $tokens['access_token'];
$userData = $this->getUserData($accessToken);
$user = $this->findOrCreateUser($userData);
$userRecord = User::where('email', $user['email'])->first();
if ($userRecord) {
Auth::login($userRecord, true);
return redirect('/'); // Redirect the logged-in user
} else {
return redirect()->route('login');
}
}
return response()->json(['error' => 'Failed to obtain access token']);
}
private function getUserData($accessToken)
{
$response = Http::get('https://www.googleapis.com/oauth2/v3/userinfo', [
'access_token' => $accessToken,
]);
return $response->json();
}
Purpose:
- When Google redirects back to your app, it includes a code (authorization code) in the URL.
- The code is exchanged for an access token by making a POST request to Google's OAuth token endpoint:
- client_id, client_secret, code, redirect_uri, and grant_type are required to request the token.
- If successful, the response contains an access_token which will be used to access the user’s Google profile.
- This function retrieves the authenticated user’s profile data from Google using the access token.
private function findOrCreateUser($userData)
{
$user = User::where('email', $userData['email'])->first();
if (!$user) {
$user = User::create([
'google_id' => $userData['sub'], // Google ID
'name' => $userData['name'],
'email' => $userData['email'],
'picture_url' => $userData['picture'], // Profile picture
]);
}
return $user;
}
Step 7: Define Routes for Google Authentication
In routes/web.php, define the routes for Google login and the callback:
Auth::routes();
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index']);
Route::get('auth/google', [GoogleController::class, 'redirectToGoogle']);
Route::get('auth/google/callback', [GoogleController::class, 'handleGoogleCallback']);
Step 8: Customize the Login View for Google Sign-In
Update the resources/views/auth/login.blade.php file to add a "Login with Google" button:
<a href="{{ url('auth/google') }}" class="btn btn-primary"><strong>Login with Google</strong></a>
Run and Test Your Application
php artisan serve
npm run dev