1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

laravel ✕ OAuth2.0 Socialiteを使って取得したトークンを使ってAPIを実行してみる

Last updated at Posted at 2025-06-04

概要

Socialiteを使って取得したトークンを用いてGoogleのAPIを実行し情報を取得する方法を簡単に記載する。

前提

  • コードは下記の内容が完了しているところから修正を行う

  • トークンはDBで保持する

方法

  1. 下記の様なマイグレーションファイルを作成

    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');
        }
    };
    
  2. 下記のようなモデルを用意

    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',
        ];
    }
    
  3. マイグレーションを実行する

  4. ルーティングを下記の様に修正

    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');
    
  5. 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);
            }
        }
    }
    
  6. 一旦ログアウトし、/auth/redirectにアクセスし、ログイン後/google-cloud-storage-infosにアクセスし下記のようにJSONでGoogle Cloud Storageのバケット一覧が表示されることを確認(自身のCloud Storageにはバケットが無いので空で表示された)

    CleanShot 2025-06-04 at 16.26.34@2x.jpg

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?