開発環境
Laravel Framework 9.7.0
PHP 8.1.3
Sailを使用
Laravel Socialiteをインストールする
sail composer require laravel/socialite
SocialiteのLINEプロバイダーを追加する
composer require socialiteproviders/line
LINE Developersで取得した値を.envファイルに追記する
LINE_CLIENT_ID='取得したチャンネルID'
LINE_CLIENT_SECRET='取得したチャネルシークレット'
LINE_REDIRECT_URI='(アプリのURL)/login/line/callback'
※開発時にngrokを使用して設定した際のリダイレクトURIの一例↓↓
LINE_REDIRECT_URI='https://75ef-118-238-203-22.ngrok.io/login/line/callback'
config/services.phpに設定を追記する(LINE以外も同様)
config/services.php
'line' => [
'client_id' => env('LINE_CLIENT_ID'),
'client_secret' => env('LINE_CLIENT_SECRET'),
'redirect' => env('LINE_REDIRECT_URI')
],
app/EventServiceProvider.phpにイベントを追記する(LINE以外も同様)
app/EventServiceProvider.php
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
// 下記を追加、先にLINE以外が追加してあればLINEの部分を追加
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
'SocialiteProviders\\Line\\LineExtendSocialite@handle',
],
];
保存したい値を入れる,テーブル、カラムを用意しておく(一例)
database/migrations/2014_10_12_000000_create_users_table.php
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique()->nullable(); // 変更
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable(); // 変更
$table->enum('provider', ['line','任意で追加 twitter等']);
$table->string('provided_user_id'); // 各プロバイダーから帰るuidを入れる
$table->rememberToken();
$table->timestamps();
});
}
マイグレーションファイルを変更したらsail php artisan migrateでテーブルを作成
sail php artisan migrate
テーブルに合わせてModelを変更する(一例)
app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
'provider', // 追加
'provided_user_id',// 追加
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
ルーティングを追加(一例)
routes/web.php
// プロバイダーへのリダイレクト処理のルート
Route::get('/login/{provider}', [LoginController::class, 'redirectToProvider']);
// プロバイダーからのコールバック時のルート
Route::get('/login/{provider}/callback', [LoginController::class, 'handleProviderCallback']);
Route::get('/{any?}', function () {
return view('welcome');
})->where('any', '^(?!api\/)[\/\w\.-]*');
コントローラーの実装(一例)
app/Http/Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Exception;
use Laravel\Socialite\Facades\Socialite;
class LoginController extends Controller
{
public function __construct()
{
$this->middleware('guest')->except('logout');
}
// リダイレクトの処理の追加
public function redirectToProvider($provider)
{
return Socialite::driver($provider)->redirect();
}
// プロバイダーからのコールバック時の処理の追加
public function handleProviderCallback($provider)
{
$provided_user = Socialite::driver($provider)->stateless()->user();
$user = User::where('provider', $provider)
->where('provided_user_id', $provided_user->id)
->first();
if ($user === null) {
$user = User::create([
'name' => $provided_user->name,
'provider' => $provider,
'provided_user_id' => $provided_user->id,
]);
}
Auth::login($user);
}
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => 'required',
]);
if(Auth::attempt($credentials)) {
$request->session()->regenerate();
return response()->json(['name' => Auth::user()->email], 200);
}
throw new Exception('ログインに失敗しました。再度お試し下さい');
}
public function logout()
{
Auth::logout();
return response()->json(['message' => 'Logged out'], 200);
}
}