概要

本記事では、Laravelを使用してGoogleログイン機能を実装する手順を解説します。Googleログインを組み込むことで、ユーザーはGoogleアカウントを使用して簡単にログインできるようになります。

所要時間

1時間

環境

Mac OS Venture
PHP 8.2.6
Laravel 10.12.0
Breeze 1.21
Socialite 5.6

流れ&学べること

  1. Dockerを使用してLaravelの開発環境をセットアップする方法
  2. Laravel Breezeを使用してログイン機能を追加する方法
  3. Laravel Socialiteを使用してGoogleログイン機能を追加する方法

Dockerインストールしていない方用

Dockerないよ!って人は、まずインストールしてください

Docker Desktop

Macの方で、Homebrewで管理してる方は、以下でインストールできます

brew install --cask docker

ちなみにDockerはLinux環境で動くので、Windowsの方はDockerを入れる前にWSLを入れる必要があります

Laravel Sail

Sailとは?

一言で言うと「Laravelの環境構築をしてくれるツール」です
なので、ポチポチするだけで以下の画面をブラウザで開くことができます

image.png

https://laravel.com/docs/10.x/sail

環境構築

プロジェクトを作成したいディレクトリに移動して、任意のアプリケーションの名前を決め、以下コマンドを叩いてください

curl -s https://laravel.build/{アプリケーションの名前} | zsh

パスワード入力が求められ、入力し以下の画面になればOKです
image.png

次にDocker Desktopを起動しておき、sailを起動します

cd {アプリケーションの名前} && ./vendor/bin/sail up

初回の立ち上げは結構時間かかります

Docker DesktopでStatusが全部Runnigになってればオッケーです!

image.png

ブラウザでlocalhostにアクセスすると、Laravelのウェルカム画面が表示されます

image.png

毎回、sailを起動するのに./vendor/bin/sail upと入力するのは手間なので、エイリアスを登録しておきます

echo "alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'" >> ~/.zshrc

これで以降は、sail upで立ち上がります
止める時は、sail stopかDocker Desktopの停止ボタンのどちらかで停止してください

Breeze

Breezeとは?

Laravel Breezeは、Laravelの認証機能を簡単に追加するためのライブラリです
Breezeを使用することで、ログイン・登録機能を簡単に実装することができます
以下の画面の右上に
image.png
ログインと登録をつけてくれます
image.png

Breezeのインストール

まずは、以下コマンドでコンテナの中に入りましょう

sail shell

もしくは

docker exec -it {アプリケーションの名前} bash

で中に入れます
ちなみに、ここでbashなのは、コンテナ内がデフォルトでbashだからです
気になる人はコンテナの中でecho $SHELLしてみてください
今後、記述コードがbashとなっているものはコンテナ内でコマンドを実行してください

以下コマンドで、Breezeをインストールしてください。composer.jsonファイルにBreezeがインストールされているかも確認してください。

composer require laravel/breeze

次に、ログイン画面のBladeファイルを持ってきたいので、以下コマンドを入力してください

php artisan breeze:install

実行すると対話形式で3つ聞かれるので、答えてください
Bladeスタックと、ダークモード対応、テストは特にしないのでnoを選択

Which stack would you like to install?
blade ............................................... 0
react ............................................... 1
vue ................................................. 2
api ................................................. 3
❯ 0

Would you like to install dark mode support? (yes/no) [no]
❯ yes

Would you prefer Pest tests instead of PHPUnit? (yes/no) [no]
❯ no

これにより、ログイン・登録画面などが自動的に生成されます
localhostにアクセスすると、作成されていることが確認できます
スクリーンショット 2023-05-25 14.40.33.png

DBの準備

一旦、アカウント登録するためDBの準備をします
まず、migrationを実行します

php artisan migrate

次に、envを参照しDBクライアントに接続したら、localhostで右上のRegisterで入力し、

image.png

こちらの画面に遷移できれば、Breezeのインストールは完了です

image.png

DBの中身も一応確認すると、入ってますね

スクリーンショット 2023-05-25 14.53.04.png

Googleログイン

ここからが今回のメインです
先ほどまでで作った、ログイン画面にGoogleログインを実装していきます

Socialiteのインストール

Laravel Socialiteは、Laravelフレームワークでソーシャルメディア認証(Social Authentication)を簡単に実装するためのオフィシャルなパッケージです

https://laravel.com/docs/10.x/socialite

コンテナ内で、以下コマンドでSocialteをインストールしてください

composer require laravel/socialite

次に、config/app.phpファイル

GCコンソールで認証情報登録

以下URLからGoogle Cloudのコンソール画面にいき認証情報の登録を行います

https://console.cloud.google.com

新たにプロジェクトを作成し、APIとサービス認証情報をクリックし、認証情報を作成をクリック
※初めての場合、OAuth 同意画面でアプリケーション名だけ入力して同意してください
image.png

OAuth クライアント ID の作成をクリック
image.png

アプリケーションの種類ウェブアプリケーションを選択し、
承認済みの JavaScript 生成元http://localhost
承認済みのリダイレクト URIhttp://localhost/auth/google/callback
と入力し、作成
image.png

作成後に出るモーダルからクライアントIDクライアントシークレットを控えておく(マスクがうまくできるか心配で切り抜きました、、)
image.png
↓この右側にあるものを控える
image.png

Laravel側で設定

控えたものを、.envファイルの一番下に以下の形で記述

GOOGLE_KEY="******************************"
GOOGLE_SECRET="******************************"
GOOGLE_REDIRECT_URI="http://localhost/auth/google/callback"

次に、service/config.appにGoogleとの連携のための設定を記述します

    'google' => [
        'client_id' => env('GOOGLE_KEY'), 
        'client_secret' => env('GOOGLE_SECRET'), 
        'redirect' => env('GOOGLE_REDIRECT_URI'), 
      ],

コントローラー
Googleアカウントを使用してログイン機能を実装するためのコントローラを作成します

php artisan make:controller GoogleLoginController

GoogleLoginController.phpファイルの中身は以下のように書き換えます

<br /><?php

namespace App\Http\Controllers;

use Laravel\Socialite\Facades\Socialite;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Exception;
use Illuminate\Support\Facades\Log;

class GoogleLoginController extends Controller
{
    public function redirectToGoogle()
    {
        return Socialite::driver('google')->redirect();
    }

    public function handleGoogleCallback()
    {
        try {
            $socialiteUser = Socialite::driver('google')->user();
            $email = $socialiteUser->email;

            $user = User::firstOrCreate(['email' => $email], [
                'name' => $socialiteUser->name,
            ]);

            Auth::login($user);

            return redirect()->intended('dashboard');
        } catch (Exception $e) {
            Log::error($e);
            throw $e;
        }
    }
}



ルーティング

web.phpGoogleLoginControllerを追加し、認証用のルートを定義します
web.php

use App\Http\Controllers\GoogleLoginController;

Route::get('/auth/google', [GoogleLoginController::class, 'redirectToGoogle'])
    ->name('login.google');

Route::get('/auth/google/callback', [GoogleLoginController::class, 'handleGoogleCallback'])
    ->name('login.google.callback');


ビュー

ログイン画面のBladeファイルを以下のように変更します
login.blade.php

<x-guest-layout>
    <!-- Session Status -->
    <x-auth-session-status class="mb-4" :status="session('status')" />

    <form method="POST" action="{{ route('login') }}">
        @csrf

        <!-- Email Address -->
        <div>
            <x-input-label for="email" :value="__('Email')" />
            <x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
            <x-input-error :messages="$errors->get('email')" class="mt-2" />
        </div>

        <!-- Password -->
        <div class="mt-4">
            <x-input-label for="password" :value="__('Password')" />

            <x-text-input id="password" class="block mt-1 w-full"
                            type="password"
                            name="password"
                            required autocomplete="current-password" />

            <x-input-error :messages="$errors->get('password')" class="mt-2" />
        </div>

        <!-- Remember Me -->
        <div class="block mt-4">
            <label for="remember_me" class="inline-flex items-center">
                <input id="remember_me" type="checkbox" class="rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800" name="remember">
                <span class="ml-2 text-sm text-gray-600 dark:text-gray-400">{{ __('Remember me') }}</span>
            </label>
        </div>

        <div class="flex items-center justify-between mt-4">
            <div>
                @if (Route::has('password.request'))
                    <a class="underline text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:focus:ring-offset-gray-800" href="{{ route('password.request') }}">
                        {{ __('Forgot your password?') }}
                    </a>
                @endif
            </div>

            <div>
                <x-primary-button>
                    {{ __('Log in') }}
                </x-primary-button>
            </div>
        </div>
    </form>

    <div class="flex items-center justify-end mt-4">
        <a href="{{ route('login.google') }}" class="ml-3 inline-flex items-center">
            <img src="https://developers.google.com/identity/images/btn_google_signin_dark_normal_web.png" style="margin-left: 3em;">
        </a>
    </div>
</x-guest-layout>


マイグレーション

Googleログイン時はパスワードは使用しないので、パスワードをNULL許容するようにpasswordカラムを変更いたします
以下コマンドでマイグレーションファイルを生成します

php artisan make:migration modify_password_column_nullable_in_users_table --table=users

生成されたマイグレーションファイルの中身を以下のように書き換えます

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class ModifyPasswordColumnNullableInUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('password')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('password')->nullable(false)->change();
        });
    }
}


マイグレートします

php artisan migrate

ログイン確認

ログイン画面にGoogleログインが出ており、
image.png
ログインし、
image.png
この画面に辿り着ければ完了です!お疲れ様でした!
image.png

おわり

見ていただきありがとうございます!
Laravel Sailやソーシャルログインの実装が意外と簡単にできてびっくりしました。
OAuthが雰囲気でしかわかっていないのでこれからちゃんと学ぼうと思います。