概要
Socialiteを使って取得したトークンを用いてGoogleのAPIを実行し情報を取得する方法を簡単に記載する。
前提
- コードは下記の内容が完了しているところから修正を行う
- トークンはDBで保持する
方法
-
下記の様なマイグレーションファイルを作成
database/migrations/2025_06_04_054743_create_oauth_tokens_table.php<?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::create('oauth_tokens', function (Blueprint $table) { // カラム定義 $table->id(); $table->unsignedBigInteger('user_id'); $table->string('access_token'); $table->string('refresh_token')->nullable(); $table->timestamps(); // 外部キー制約 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('oauth_tokens'); } };
-
下記のようなモデルを用意
app/Models/OauthToken.php<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class OauthToken extends Model { /** @use HasFactory<\Database\Factories\OauthTokenFactory> */ use HasFactory; protected $fillable = [ 'user_id', 'access_token', 'refresh_token', ]; }
-
マイグレーションを実行する
-
ルーティングを下記の様に修正
routes/web.php<?php use App\Http\Controllers\OauthController; use Illuminate\Support\Facades\Route; Route::get('/', function () { return view('welcome'); })->name('home'); Route::middleware([ 'auth:sanctum', config('jetstream.auth_session'), 'verified', ])->group(function () { Route::get('/dashboard', function () { return view('dashboard'); })->name('dashboard'); }); // Googleの認証ページへのリダイレクト Route::get('/auth/redirect', [OauthController::class, 'redirectToGoogle'])->name('google.redirect'); // Googleからのコールバックを受け取る Route::get('/auth/callback', [OauthController::class, 'handleGoogleCallback'])->name('google.callback'); Route::get('/google-cloud-storage-infos', [OauthController::class, 'googleCloudStorageInfos'])->name('google.cloud.storage.infs');
-
OauthControllerを作成して下記のように記載
app/Http/Controllers/OauthController.php<?php namespace App\Http\Controllers; use App\Models\OauthToken; use Illuminate\Http\Request; use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Log; use Illuminate\Support\Str; use Laravel\Socialite\Facades\Socialite; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Http; class OauthController extends Controller { public function __construct(protected OauthToken $oauthToken) { } /** * Googleの認証ページへのリダイレクトを行う * * @return RedirectResponse Googleの認証ページへのリダイレクトレスポンス */ public function redirectToGoogle(): RedirectResponse { return Socialite::driver('google') ->scopes(['email', 'profile', 'https://www.googleapis.com/auth/cloud-platform.read-only']) ->with(['access_type' => 'offline', 'prompt' => 'consent']) ->redirect(); } /** * Googleからのコールバックを受け取る * * @return RedirectResponse リダイレクトレスポンス */ public function handleGoogleCallback(): RedirectResponse { try { $googleUser = Socialite::driver('google')->user(); $accessToken = $googleUser->token; $refreshToken = $googleUser->refreshToken; } catch (\Exception $e) { Log::error($e); return redirect(route('home')); } // ユーザーが既に存在するか確認 $user = User::where('email', $googleUser->getEmail())->first(); if (!$user) { // ユーザーが存在しない場合、新規作成 $user = User::create([ 'name' => $googleUser->getName(), 'email' => $googleUser->getEmail(), 'google_id' => $googleUser->getId(), 'password' => Hash::make(Str::random(16)), ]); } // ユーザーをログインさせる Auth::login($user); try { DB::beginTransaction(); // 同様のuser_idのレコードがあったら削除 $this->oauthToken->where('user_id', $user->id)->delete(); // 新しいトークンを挿入 $this->oauthToken->create([ 'user_id' => $user->id, 'access_token' => $accessToken, 'refresh_token' => $refreshToken, ]); DB::commit(); } catch (\Exception $e) { DB::rollBack(); Log::error('トークンの保存中にエラーが発生しました', ['exception' => $e]); return redirect(route('home'))->with('error', 'トークンの保存中にエラーが発生しました'); } // リダイレクト先を指定 return redirect(route('dashboard')); } public function googleCloudStorageInfos() { $oauthToken = $this->oauthToken->where('user_id', Auth::user()->id)->first(); $accessToken = $oauthToken->access_token; try { $response = Http::withToken($accessToken)->get('https://www.googleapis.com/storage/v1/b', [ 'project' => 'Google CloudのプロジェクトID' // .envで持ちたいね ]); if ($response->successful()) { $buckets = $response->json(); return response()->json($buckets); } else { Log::error('Google Cloud API request failed', ['response' => $response->body()]); return response()->json(['error' => 'Failed to retrieve Google Cloud resources'], 500); } } catch (\Exception $e) { Log::error('Exception occurred while fetching Google Cloud resources', ['exception' => $e]); return response()->json(['error' => 'An error occurred while fetching Google Cloud resources'], 500); } } }
-
一旦ログアウトし、
/auth/redirect
にアクセスし、ログイン後/google-cloud-storage-infos
にアクセスし下記のようにJSONでGoogle Cloud Storageのバケット一覧が表示されることを確認(自身のCloud Storageにはバケットが無いので空で表示された)