Laravel・PHP入門

未経験Ruby->PHPer初心者

【Laravel】GoogleのOAuth認証でログイン機能を実装する(PHP)

LaravelのSocialiteに感動したのでメモ。

【やりたいこと】
GoogleのOAuthAPIを用いてログイン機能を実装する

※ログインのみ、GoogleAPIを用いて判定、
ユーザ情報はGoogle APIから取得する。

また、今回はuserの新規作成は割愛します。ログインのみ。
emailで管理ユーザか否か判定します。
※必要な方は、ログイン時にユーザがいなければcreateしてください。

【環境】
Laravel5.5
PHP7.2
Google API

【前提】
php artisan make:auth 実施済(なければ叩いてください)
Usersテーブル(もしくはauthに対応したテーブル)が存在する
DBは接続済み
ログインできるGoogleアカウントがある

やってみます。


Laravelは公式で、GoogleFacebookTwitterなど
様々なソーシャル認証を使用できるパッケージを持っています。(神)

Google

OAuth情報を取得・設定

この辺りは、Qiitaや記事がたくさんありますので割愛。
Google developerコンソールで、プロジェクト作成します。
Google OAuth 2.0 認証を使ったログインの実装 - Qiita
GoogleのOAuth2.0を使ってプロフィールを取得【PHP】 - FaMirror Project

・クライアントID(自動発行)
・クライアントシークレット(自動発行)
・リダイレクト先 (自分で設定)Ex.https://samplesample.jp/login/google/callback

が今後必要になります。

※redirectは、ログイン後にアクセスするURLになります。ご自身で設定ください。

※使用できるURLに制限があります!
.comや.jpなど、パブリックドメインのみ使用可能。(プライベートはlocalhostのみ)
これでかなりハマりました。。。
apacheいじって、.jpに変更したらgoogleが許してくれました。
もしgoogleから not foundなどのエラーが吐かれた場合、ここに問題ある可能性あります。

Google側の必要情報が取得できたら、
それらを認証できるよう、APIを有効にしていきます。

APIの有効化

Google のdeveloperコンソール、左側メニューのライブラリを選択。
Google Cloud Platform

Google + API
Google Drive API
・Contacts API

この3つが必要になりますので、全て有効にしてください。

f:id:fresh_engineer:20180110014305p:plain

こういうものですね。
これで、Google側の設定は完了です。

Laravelの設定

Socialiteパッケージをインストール

まずは、composerでinstallしましょう。

composer require laravel/socialite

Configの設定変更

コントローラでSocialiteを使用するため、
providerとaliasに登録しておきます。

config/app.php

<?php
Laravel\Socialite\SocialiteServiceProvider::class,

/.../

'Socialite' => Laravel\Socialite\Facades\Socialite::class,


config/service.php

<?php
'google' => [
         'client_id' => env('GOOGLE_CLIENT_ID'),
         'client_secret' => env('GOOGLE_CLIENT_SECRET'),
         'redirect' => env('APP_URL').'/login/google/callback',
],

シークレットなど隠すために、.envファイルで設定します。

.envファイル

<?php
APP_URL=(自分のwebアプリURL(上の方に既存))
...
GOOGLE_CLIENT_ID=(自分のクライアントID|新規作成)
GOOGLE_CLIENT_SECRET=(自分のクライアントシークレット|新規作成)


以上で設定が完了しました。
Controller/Model/Viewを実装します。

Laravelで実装

Route実装

まずはControllerにアクセスできるよう、Routeを設定しましょう。

<?php
// ログイン前アクセス可能(Google OAuth認証)
 Route::group(['prefix' => '/login/google', 'namespace' => 'Auth'], function ($router) {
     $router->get('/', 'LoginController@index')->name('login');
     $router->get('/redirect', 'LoginController@getRedirect');
     $router->get('/callback', 'LoginController@getCallback');
 });

Controller実装

AuthでLoginコントローラがあるはずなので、
Loginコントローラを編集します。

app/Http/Controller/Auth/LoginController.php

<?php

use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use App\Models\User as UserModel; 
// 私はModelディレクトリ配下にUserModelを置いてるので
use Socialite; // Socialite使用可能にする

 class LoginController extends BaseController
 {
 use AuthenticatesUsers;

private $user_model;

public function __construct(UserModel $user_model)
{
    $this->middleware('guest:admin')->except('logout');
    $this->user_model = $user_model; //Usermodelをインスタンス化
}


     /**
      * エラーの有無を確認して、ログインページにリダイレクト
      *
      * @return response
      * @access public
      */
     public function index()
     {
         Auth::logout();
         return $this->render();
     }

    /**
     * Google認証ページヘユーザーをリダイレクト
     *
     * @return \Illuminate\Http\Response
     * @access public
     */
    public function getRedirect()
    {
        return Socialite::driver('google')->redirect();
    }

   /**
      * Googleからユーザー情報を取得、ログイン権限があればログイン
      *
      * @return \Illuminate\Http\Response
      * @access public
      */
     public function getCallback()
     {
         $email = Socialite::driver('google')->stateless()->user()->email;
         $user = $this->user_model->getAdminUserFromEmail($email);
         // すでに登録しているユーザとemailが一致するか確認

         if ($user === null) {
             return redirect()
                 ->route('login')
                 ->with('message', 'ログイン権限がありません。');
         }

        Auth::login($user, true); //弾かれなければ$userオブジェクトを用いてログイン
         return redirect($this->redirectTo); //ログイン後リダイレクト
      }
  }

Model実装

そしてこのUserModelでemailからユーザの有無判定。
(パスワードは使用しないので、消してしまって大丈夫です。)

<?php
     /**
      * 特定のEmailから管理ユーザを取得
      *
      * @param str $email
      * @return object
      * @access public
      */
     public function getAdminUserFromEmail(string $email)
     {
         return $this->where('email', $email)
                      ->first();
      }

Viewの実装

最後に、Viewを設定して、、、

<a href="/login/google/redirect" class="btn btn-google">Sign in using Google+</a>


ログインできれば、完了です!
な、なんて便利なんでしょう・・・!!!!涙