ホームページ > バックエンド開発 > PHPチュートリアル > Laravel での Socialite 認証の実装とテスト

Laravel での Socialite 認証の実装とテスト

DDD
リリース: 2025-01-03 11:17:42
オリジナル
150 人が閲覧しました

Implementing & testing Socialite authentication in Laravel

Laravel Socialite は、開発者がアプリケーションに OAuth および OAuth2 ソーシャル認証を実装するのに役立つファーストパーティの Laravel パッケージです。 Facebook、Twitter、Google、LinkedIn、GitHub、GitLab、Bitbucket のサポートが組み込まれています。 Socialite は、コミュニティ パッケージを通じて他のプロバイダーをサポートできます。

この投稿は次の内容になります:

  • Socialite が行うことと行わないことを説明します。
  • Socialite を介して Google 認証を新しい Laravel プロジェクトに統合する方法を示します。
  • Socialite のテスト例を示します。

TLDR: 完成したプロジェクトは私の GitHub でご覧いただけます。完成したコードを読むだけなら、ぜひ見てください。

Laravel Socialite は何をし、何をしませんか?

Socialite は小さなパッケージであり、そのメイン API は主に 2 つの主要なメソッドで構成されています。

  • Socialite::driver($authProvider)->redirect() は、ユーザーを指定された認証プロバイダーにリダイレクトし、必要な情報を URL パラメーター経由でプロバイダーに渡します。
  • Socialite::driver($authProvider)->user() は、認証プロバイダーから返されたユーザー データを取得し、エンドポイントで利用できるようにします。

スコープとオプションのパラメーターを設定するための追加のサポート方法があります。これらについては、Socialite のドキュメントで読むことができます。

Socialite は次のことをしません: これらの機能の実装は開発者に任されています:

  • ❌ ソーシャル認証データを保存するために必要なデータベース テーブルまたは列を作成します。
  • ❌ 認証プロセス中に存在しないユーザーを作成します。
  • ❌ OAuth フローが成功した後にユーザーを認証します。
  • ❌ OAuth トークンを更新します。

前提条件: Google Cloud プロジェクトの作成

ユーザーが Google 経由で認証できるようにする小規模な Socialite プロジェクトをセットアップします。そのためには、Google アプリを作成する必要があります。

まず新しい Google Cloud プロジェクトを作成し、次にプロジェクトの OAuth 同意画面を構成します。 ユーザー タイプ外部に設定し、次のスコープを有効にします:

  • .../auth/userinfo.email
  • .../auth/userinfo.profile

同意画面を設定した後、Google Cloud 認証情報ページにアクセスして OAuth 2.0 クライアント ID を作成します。 クライアント IDクライアント シークレット を保管しておいてください。これらはプロジェクトの後半で使用します。

Socialite を使用した最小限の Laravel プロジェクトのセットアップ

新しい Laravel プロジェクトを作成します:

laravel new socialite-tests
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

インストーラーから次のオプションを選択します:

 ┌ Would you like to install a starter kit? ────────────────────┐
 │ No starter kit                                               │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which testing framework do you prefer? ──────────────────────┐
 │ Pest                                                         │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which database will your application use? ───────────────────┐
 │ SQLite                                                       │
 └──────────────────────────────────────────────────────────────┘

 ┌ Would you like to run the default database migrations? ──────┐
 │ Yes                                                          │
 └──────────────────────────────────────────────────────────────┘
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

プロジェクト ディレクトリに移動し、Socialite をインストールします。

laravel new socialite-tests
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

新しい移行を作成します。

 ┌ Would you like to install a starter kit? ────────────────────┐
 │ No starter kit                                               │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which testing framework do you prefer? ──────────────────────┐
 │ Pest                                                         │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which database will your application use? ───────────────────┐
 │ SQLite                                                       │
 └──────────────────────────────────────────────────────────────┘

 ┌ Would you like to run the default database migrations? ──────┐
 │ Yes                                                          │
 └──────────────────────────────────────────────────────────────┘
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

database/migrations に新しく作成した移行ファイルに次のコードを配置します。

cd socialite-tests
composer require laravel/socialite
ログイン後にコピー

この移行により、ユーザーが認証に成功したときに Socialite によって提供されるフィールドが追加されます。私たちの実装では、簡単にするためにこれらのフィールドをユーザー テーブルに直接追加しています。 Google よりも多くのプロバイダーをサポートしたい場合は、ユーザーごとに複数のプロバイダーを保存できる別のテーブルを作成するとよいでしょう。

Google 経由でのみ認証する場合、ユーザーは決してパスワードを設定しないため、パスワードを null 可能に設定しています。アプリでソーシャル認証パスワード認証が許可されている場合、ユーザーがパスワードを使用してログインしようとするときに、パスワードが空白または null でないことを検証する必要があります

移行を実行します。


php artisan make:migration add_socialite_fields_to_users
ログイン後にコピー
config/services.php で、次のコード ブロックを services 配列の最後に追加します。有効な Socialite サービス名の完全なリストは、構成ドキュメントで確認できます。


<?php
// database/migrations/2024_12_31_075619_add_socialite_fields_to_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('google_id')->default('');
            $table->string('google_token')->default('');
            $table->string('google_refresh_token')->default('');

            // If your app allows both password and social logins, you
            // MUST validate that the password is not blank during login.
            // If you do not, an attacker could gain access to an account
            // that uses social login by only knowing the email.
            $table->string('password')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('google_id');
            $table->dropColumn('google_token');
            $table->dropColumn('google_refresh_token');
            $table->string('password')->nullable(false)->change();
        });
    }
};
ログイン後にコピー
「前提条件」セクションで作成した Google アプリの認証情報を使用して、以下を .env に追加します。


php artisan migrate
ログイン後にコピー
routes/web.php の内容を次のコードに置き換えます。


// config/services.php

'google' => [
    'client_id' => env('GOOGLE_CLIENT_ID'),
    'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    'redirect' => '/auth/google/callback',
],
ログイン後にコピー
このファイルの新しいコードは次のルートを実装します:

    適切な情報を使用してソーシャル ログインのために Google にリダイレクトします。
  • Google からのコールバックを処理します。このルートは、ログイン時にユーザーを作成または更新し、認証してホームページにリダイレクトします。
  • 認証されたユーザーをログアウトします。
最後に、resources/views/welcome.php の内容を次のマークアップで置き換えます。


# .env

GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
ログイン後にコピー
これが完了したら、開発サーバーを実行してアプリを手動でテストできます。


<?php
// routes/web.php

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
use Laravel\Socialite\Facades\Socialite;
use Laravel\Socialite\Two\InvalidStateException;
use Laravel\Socialite\Two\User as OAuth2User;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/auth/google/redirect', function () {
    return Socialite::driver('google')->redirect();
});

Route::get('/auth/google/callback', function () {
    try {
        /** @var OAuth2User $google_user */
        $google_user = Socialite::driver('google')->user();
    } catch (InvalidStateException $exception) {
        abort(400, $exception->getMessage());
    }

    $user = User::updateOrCreate([
        'email' => $google_user->email,
    ], [
        'google_id' => $google_user->id,
        'name' => $google_user->name,
        'google_token' => $google_user->token,
        'google_refresh_token' => $google_user->refreshToken,
    ]);

    Auth::login($user);
    return redirect('/');
});

Route::get('/auth/logout', function () {
    Auth::logout();
    return redirect('/');
});
ログイン後にコピー

Google でログイン リンクをクリックすると、OAuth2 フローが実行され、ホームページにリダイレクトされ、Google から新しく作成されたユーザーに関する情報が表示されます。

社交界の人々を害虫でテストする

私たちの手動テストは

機能しますが、将来この機能を誤って壊さないことを確認するために自動テストを希望します。

次のコマンドを使用して、新しいテスト ファイルを作成できます。


<!-- resources/views/welcome.php -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Laravel Socialite Testing Example</title>
</head>
<body>
    <h1>Laravel Socialite Testing Example</h1>
    @if (auth()->check())
        <p>User is authenticated.</p>
        <p>Name: {{ auth()->user()->name }}</p>
        <p>Email: {{ auth()->user()->email }}</p>
        <p><a href="/auth/logout">Logout</a></p>
    @else
        <p>User is not authenticated.</p>
        <p>
            <a href="/auth/google/redirect">Login with Google</a>
        </p>
    @endif
</body>
</html>
ログイン後にコピー
新しく作成したtests/Feature/AuthRoutesTest.phpの内容を次のものに置き換えます。


php artisan serve
ログイン後にコピー
テストの仕組み

リダイレクト ルートをテストするときは、Socialite が正しい URL にリダイレクトし、正しい URL パラメーターを渡すことをテストします。

コールバック ルートをテストするとき、Socialite を模擬します。モッキングは私の好みのオプションではありません。理想的な世界では、Socialite を別の OAuth2 実装に置き換えることができ、テストは引き続き機能します。ただし、アクセス トークンを追加するために Socialite が送信する認可付与リクエストに接続する簡単な方法はありません。このため、モックは Socialite をテストするための最も現実的なアプローチです。

Fluent API を Mockery 経由でモックするには面倒です。終了呼び出しから開始して、逆方向に作業する必要があります。

これは、コールバック エンドポイントが呼び出す Socialite メソッドです。

laravel new socialite-tests
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

Mockery を介してこれを嘲笑する方法は次のとおりです:

 ┌ Would you like to install a starter kit? ────────────────────┐
 │ No starter kit                                               │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which testing framework do you prefer? ──────────────────────┐
 │ Pest                                                         │
 └──────────────────────────────────────────────────────────────┘

 ┌ Which database will your application use? ───────────────────┐
 │ SQLite                                                       │
 └──────────────────────────────────────────────────────────────┘

 ┌ Would you like to run the default database migrations? ──────┐
 │ Yes                                                          │
 └──────────────────────────────────────────────────────────────┘
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

最後に、OAuth フローの外部でコールバック URL に直接移動すると 400 ステータス コードが返されることを確認するテストがあります。 Socialite::driver('google')->user() への呼び出しを try/catch ブロック内のコールバック エンドポイントにラップしました。 Socialite 呼び出しを try/catch ブロックでラップしておらず、誰かがブラウザにコールバック URL を入力した場合、エンドポイントは HTTP 500 ステータス コードの例外をスローします。チームが 500 ステータス コードの監視を設定している場合、深夜に誰かにページングが行われる可能性があります。

まとめ

これは最小限の統合であり、他にも実装できるものはたくさんあります。ユーザーの電子メールが変更される可能性があるソーシャル プロバイダーとの統合を実装している場合、電子メール アドレスと一致するため、この実装は機能しません。ユーザーがアプリ内でメール アドレスを変更できる場合、この実装も同じ理由で機能しません。ただし、Socialite をテストする方法を理解したので、これらのシナリオのテストを作成し、それらが合格するように基礎となる実装を変更できます。

独自の実装の構築方法、テスト方法、何を考慮する必要があるかを理解する前に、Socialite に関するブログ記事やフォーラムの投稿をたくさん読みました。ここでその一部について謝意を表したいと思います。

  • Stefan Zweifel による Laravel Socialite 搭載アプリの統合テストの書き方
  • ServerSideUp フォーラム: ソーシャライトのベスト プラクティス、会話
  • スタック オーバーフロー: Laravel ソーシャルライトをテストする方法
  • スタック交換: ソーシャル ログインを一致する電子メールにリンクするかどうか
  • スタック交換: 接続されたソーシャル アカウントと潜在的な孤立者への対処

さらに詳しく知りたい場合は、これらをお読みください。また、複数のソーシャル プロバイダーの処理、ユーザーがメール アドレスを変更したときの処理、または更新トークンの処理について詳しく説明するこの投稿のパート 2 に興味がある場合はお知らせください。

以上がLaravel での Socialite 認証の実装とテストの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート