laravel socialiteでOauth機能を追加したのでその過程をまとめる
環境構築はsail
laravel/socialiteのインストール
compooser require laravel/socialite
次にconfig/services.php
にクライアントの設定をした
//グーグル認証のクライアント設定
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_REDIRECT_URI'),
],
また、googleのクライアントのキーを取らなければいけないためgoogle consoleからoauth同意画面で設定して、認証情報を追加した。
この時にリダイレクトURL
を設定しておかないと認証することができなくなる。
次に認証機能をまとめるSocialiteコントローラーを作成した
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
class SocialiteController extends Controller
{
//認証のリダイレクト処理
public function redirect($provider)
{
return Socialite::driver($provider)->redirect();
}
//認証のコールバック処理
public function callback($provider)
{
$user = Socialite::driver($provider)->user();
dd($user);
}
}
web.php
にリダイレクト用のルーティングとコールバック用のルーティングも追加する
//Google認証のルーティング
Route::get('/redirect/{provider}', [SocialiteController::class, 'redirect']);
Route::get('/callback/{provider}', [SocialiteController::class, 'callback']);
次に現在のuser
テーブルではpassword
カラムがあるがoauth認証だけの想定であればそもそも必要ないためpassword
カラムは消す
./vendor/bin/sail artisan make:migration remove_password_column_from_users_table --table=users
マイグレーションファイル
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('password');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('password')->nullable();
});
}
};
それと同時にuser
テーブルにはprovider_id
やtoken
を持てるようにしたかったため追加する
./vendor/bin/sail artisan make:migration add_provider_columns_to_users_table --table=users
マイグレーションファイル
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('provider')->nullable()->after('email');
$table->string('provider_id')->nullable()->after('provider');
$table->string('avatar')->nullable()->after('provider_id');
$table->string('token')->nullable()->after('avatar');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('provider');
$table->dropColumn('provider_id');
$table->dropColumn('avatar');
$table->dropColumn('token');
});
}
};
またコントローラーではDBを触る処理を書きたくなかったためApp/Servives/SocialiteUserController
にサービスクラスを追加して以下のようにした
<?php
namespace App\Services;
use App\Models\User;
class SocialiteUserService
{
//userが存在するか確認し、存在しない場合は新規作成するサービスクラス
public function findOrCreateUser($providerUser,$provider)
{
return User::firstOrCreate(
['email' => $providerUser->getEmail()],
[
'name' => $providerUser->getName(),
'provider' => $provider,
'provider_id' => $providerUser->getId(),
'avatar' => $providerUser->getAvatar(),
'token' => $providerUser->token,
]
);
}
}
そしてSocialiteコントローラーにDIしてメソッドを委託する形で使うようにした
<?php
namespace App\Http\Controllers;
use App\Services\SocialiteUserService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;
class SocialiteController extends Controller
{
protected $socialiteUserService;
public function __construct(SocialiteUserService $socialiteUserService)
{
$this->socialiteUserService = $socialiteUserService;
}
//認証のリダイレクト処理
public function redirect($provider)
{
return Socialite::driver($provider)->redirect();
}
//認証のコールバック処理
public function callback($provider)
{
$user = Socialite::driver($provider)->user();
//socialiteUserServiceクラスのインスタンスを生成してfindOrCreateUserメソッドを呼び出して登録
$user = $this->socialiteUserService->findOrCreateUser($user, $provider);
//ログイン処理
Auth::login($user, true);
return redirect('/home');
}
}
最後に
今回はstatefulな認証でできるようにしたが、spaなどの構成のときはstatelessになるので、token認証でoauth認証するようにしたい。
その際の記述としては、
Socialite::driver($provider)->stateless()->redirect()
と加えるだけでできそう。
参考
https://readouble.com/laravel/9.x/ja/socialite.html
https://zenn.dev/takumi_n/articles/laravel-socialite-password