Laravel Socialiteを使用してソーシャルログイン を実装する

Laravel Socialiteを使用してソーシャルログインでの登録・ログイン機能を実装していきます。

# Googleの設定
[GoogleAPIs](https://console.developers.google.com/cloud-resource-manager?pli=1)
上記にアクセスして、『プロジェクトを作成』を選択する

### 新しいプロジェクト
プロジェクト名：　適宜
場所：　組織なし
を入力して『作成』を押下

### Google Cloud Platform
利用規約をチェックし『同意して続行』を押下

### 左上ハンバーガーメニュー/『APIとサービス』/『OAUTH同意画面』を選択する

### OAuth同意画面
UserType： 外部を（適宜）選択し『作成』を押下

アプリケーション名：　適宜
『保存』を押下

### サイドメニュー/『認証情報認証情報を作成』/『OAuthクライアントID』を選択する

### OAuthクライアントIDの作成
アプリケーションの種類：　『ウェブアプリケーション』をチェック
名前：適宜
承認済みのリダイレクトURI：　http://localhost/login/google/callback
『作成』を押下

### OAuthクライアントを作成しましたと表示されるので下記のファイルへ追記する
```laravel/.env
GOOGLE_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
```
うまく動作しない場合
APP_URL=http://localhost:10080などAPP_URLを細かく指定すると動作する可能性があります。

## Laravel Socialiteをインストール
```
$ docker-compose exec workspace composer require laravel/socialite
```

## configファイルを編集
```laravel/config/services.php
 'google' => [
        'client_id' => env('GOOGLE_CLIENT_ID'),
        'client_secret' => env('GOOGLE_CLIENT_SECRET'),
        'redirect' => env('APP_URL') . '/login/google/callback',
    ],
```
returnの中に上記を追記する

## Googleへのリダイレクト処理
```laravel/routes/web.php
Route::prefix('login')->name('login.')->group(function () {
    Route::get('/{provider}', 'Auth\LoginController@redirectToProvider')->name('{provider}');
    Route::get('/{provider}/callback', 'Auth\LoginController@handleProviderCallback')->name('{provider}.callback');
});
Route::prefix('register')->name('register.')->group(function () {
    Route::get('/{provider}', 'Auth\RegisterController@showProviderUserRegistrationForm')->name('{provider}');
    Route::post('/{provider}', 'Auth\RegisterController@registerProviderUser')->name('{provider}');
});
```

## ログインコントローラーにアクションメソッドを追加
下記をコントローラー内に追記する

```laravel/app/Http/Controllers/Auth/LoginController.php
use App\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Laravel\Socialite\Facades\Socialite;
// 省略 
public function redirectToProvider(string $provider)
    {
        return Socialite::driver($provider)->redirect();
    }
public function handleProviderCallback(Request $request, string $provider)
    {
        $providerUser = Socialite::driver($provider)->stateless()->user();

        $user = User::where('email', $providerUser->getEmail())->first();

        if ($user) {
            $this->guard()->login($user, true);
            return $this->sendLoginResponse($request);
        }
        return redirect()->route('register.{provider}', [
            'provider' => $provider,
            'email' => $providerUser->getEmail(),
            'token' => $providerUser->token,
        ]); 
    }
```

## ログイン画面のBladeを編集
```laravel/resources/views/auth/login.blade.php
<a href="{{ route('login.{provider}', ['provider' => 'google']) }}" class="btn btn-block btn-danger">
  <i class="fab fa-google mr-1"></i>Googleでログイン
</a>
```

## ユーザー登録コントローラーにアクションメソッドを追加
下記をコントローラー内に追記する

```laravel/app/Http/Controllers/Auth/RegisterController.php
use Illuminate\Http\Request;
use Laravel\Socialite\Facades\Socialite;
// 省略
 public function showProviderUserRegistrationForm(Request $request, string $provider)
    {
        $token = $request->token;

        $providerUser = Socialite::driver($provider)->userFromToken($token);

        return view('auth.social_register', [
            'provider' => $provider,
            'email' => $providerUser->getEmail(),
            'token' => $token,
        ]);
    }

public function registerProviderUser(Request $request, string $provider)
    {
        $request->validate([
            'name' => ['required', 'string', 'alpha_num', 'min:3', 'max:16', 'unique:users'],
            'token' => ['required', 'string'],
        ]);
        
        $token = $request->token;

        $providerUser = Socialite::driver($provider)->userFromToken($token);
        $user = User::create([
            'name' => $request->name,
            'email' => $providerUser->getEmail(),
            'password' => null,
        ]);

        $this->guard()->login($user, true);

        return $this->registered($request, $user)
            ?: redirect($this->redirectPath());
    }
```

```laravel/views/auth/register.blade.php
<a href="{{ route('login.{provider}', ['provider' => 'google']) }}" class="btn btn-block btn-danger">
  <i class="fab fa-google mr-1"></i>Googleで登録
</a>
```

以上でGoogleアカウントで登録・ログインができるようになりました。