🦔

モバイルアプリからAPIでGoogle Loginする(Laravel Socialite)

2021/05/14に公開

今回はスマホアプリからGoogleログインを実現するための方法を試してみたので、解説します。

前提として、スマホアプリ側でGoogle APIを叩いてアクセストークンを既に取得している状態です。

1. Google Cloud PlatformでWebクライアントを作成する

  1. Google Cloud Platformにアクセスし、プロジェクトを作成する
  2. Webクライアントを作成する
  3. クライアントID, クライアントシークレットをゲットする

この流れで行きたいと思います。

1-1. Google Cloud Platformにアクセスし、プロジェクトを作成する

Google Cloud Platformにアクセスしてプロジェクトを作成してください。
ここはネット上にもたくさん情報がありつまづきポイントがないかと思うので説明しません。

1-2. Webクライアントを作成する

  1. 左側のメニューから「認証情報」をクリック
  2. 「認証情報を作成」をクリック
  3. 「OAuthクライアントID」をクリック

  1. アプリケーションの種類は「ウェブアプリケーション」で良いと思います

  1. 名前は何でも良いです。モバイルアプリからAPIでGoogleログインする想定なのでリダイレクトURLも不要です。

1-3. クライアントID, クライアントシークレットをゲットする

クライアントID, クライアントシークレットが発行されるので、メモしておきます。

2. Laravel Socialiteをインストール&設定する

2-1. Laravel Socialiteをインストールします

これでインストールできます。

composer require laravel/socialite 

2-2. .envにクライアントID・クライアントシークレットを書く

.envの末尾に追記してください

クライアントIDとクライアントシークレットは、Google Cloud Platformから取得したものをいれてください。

GOOGLE_CLIENT_ID=**************
GOOGLE_CLIENT_SECRET=***********

2-3. configでenv情報を参照する

config/service.php でenv情報を参照します。

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Third Party Services
    |--------------------------------------------------------------------------
    |
    | This file is for storing the credentials for third party services such
    | as Mailgun, Postmark, AWS and more. This file provides the de facto
    | location for this type of information, allowing packages to have
    | a conventional file to locate the various service credentials.
    |
    */

    'mailgun' => [
        'domain' => env('MAILGUN_DOMAIN'),
        'secret' => env('MAILGUN_SECRET'),
        'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
    ],

    'postmark' => [
        'token' => env('POSTMARK_TOKEN'),
    ],

    'ses' => [
        'key' => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    ],

    // ここから追記する
    'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
    ],
];

3. 会員登録を行う

3-1. 前提

■ DB
usersテーブルにユーザー情報が格納されている

  • emailカラム ... メールアドレス

■ 登録API

インプットパラメータ

  • google_auth_token ... Googleアカウントのアクセストークン

3-2. 実装する

public function register(Request $request)
{
    // アクセストークンをもとにgoogleアカウントを取得
    $googleOAuthToken = $request->google_oauth_token;
    
    try {
        $user = Socialite::driver('google')->userFromToken($googleOAuthToken);
    } catch (Exception $e) {
        Log::warning($e->getMessage());
        return response("エラーが発生しました。お使いのGoogleアカウントが有効でない可能性があります。");
    }
    
    // ユーザーが既に登録されているかどうかを取得する
    $email = $user->getEmail();
    $existsUser = User::where("email", $email)->first();
    
    if ($existsUser) {
        return response()->error("このアカウントは既に登録されています。");
    }

    $newUser = User::create(["email" => $email]); // google_oauth_tokenは保存する必要がないと思われるので保存しない。
    
    .
    .
    .
    // その後の会員登録処理
}

4. ログインを行う

4-1. 前提

■ ログインAPI
インプットパラメータ

  • google_auth_token ... Googleアカウントのアクセストークン

4-2. 実装する

public function login(Request $request)
{
    $googleOAuthToken = $request->google_oauth_token;
    $user = Socialite::driver('google')->userFromToken($googleOAuthToken);
    $existsUser = User::where("email", $email)->first();

    if (!$existsUser) {
        return response()->error("ユーザーが見つかりません。");
    }
    
    Auth::login($existsUser);

    .
    .
    .
    // その後のログイン処理
}

5. 会員登録とログインのテストを書く

5-1. 会員登録のテストを書く

public function testRegister()
{
    $email = $this->faker->unique()->safeEmail();
    
    $abstractUser = Mockery::mock('Laravel\Socialite\Two\User'); // Socialiteで取得するユーザーのMock
    $abstractUser->shouldReceive('getEmail')->andReturn($email);

    // SocialiteのProviderのMock, userFromTokenメソッドの返り値指定
    $provider = Mockery::mock('Laravel\Socialite\Contracts\Provider');
    $provider->shouldReceive('userFromToken')
        ->andReturn($abstractUser);

    Socialite::shouldReceive('driver')
        ->with('google')
        ->andReturn($provider);

    $response = $this->post('/api/auth/register', [
        'google_oauth_token' => $this->faker->uuid()
    ]);
    
    // アサート処理
}

※ログインも同じ要領でSocialite系のMockと返り値を指定すると書けます

終わりに

だいたいはSocialiteでリダイレクトしてトークンを取得してログインする方法が多いと思いますが、
モバイルアプリからLaravelにリクエストを送る際の方法がわからなかったので、試行錯誤してやってみました。

だいぶわかりにくくなってしまったかもしれませんが、モバイルアプリ→LaravelでGoogleログインを実装することがあればぜひ参考にしてみてください。

Discussion