laravelでGoogle OAuth2を使ってみた。

# league/oauth2-clientを使ってgoogleのoauth2を実装します。
https://github.com/thephpleague/oauth2-client

## Google OAuth2 認証情報作成
https://console.developers.google.com/apis/credentials
認証後のリダイレクトURLを指定する必要があり、先にURLを決めておく必要があります。
## 利用API選定
https://console.developers.google.com/apis/library
APIを選択し、「有効にする」をクリックする。
名前を表示するため、Google+ APIを有効にしました。
https://console.developers.google.com/apis/api/plus/overview

## ライブラリインストール
comporser.jsonに、oauth2-client, oauth2-googleを追記。

```json:comporser.json
     "require": {
         "php": ">=5.6.4",
         "laravel/framework": "5.3.*",
         "league/oauth2-client": "~1.0",
         "league/oauth2-google": "~1.0"
     },
```

composerでinstallする。

```:
$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing guzzlehttp/promises (1.3.0)
    Loading from cache

  - Installing psr/http-message (1.0.1)
    Loading from cache

  - Installing guzzlehttp/psr7 (1.3.1)
    Loading from cache

  - Installing guzzlehttp/guzzle (6.2.2)
    Loading from cache

  - Installing ircmaxell/security-lib (v1.1.0)
    Loading from cache

  - Installing ircmaxell/random-lib (v1.2.0)
    Loading from cache

  - Installing league/oauth2-client (1.4.2)
    Loading from cache

  - Installing league/oauth2-google (1.0.1)
    Loading from cache

Writing lock file
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized class loader
The compiled class file has been removed.
```

## 実装
利用しやすいようaliasを貼る。
※ フルパスでクラスを利用する人は、必要ない。

```php:config/app.php
    'aliases' => [
...
        'OAuthClient2Google' => League\OAuth2\Client\Provider\Google::class,
    ],
];
```

routesを編集
トップページをTopsControllerを利用するよう修正。
ログインページとGoogleからの戻り先のページを定義する。

```php:routes/web.php
Route::get('/', 'TopsController@index');
Route::get('/login/new', 'Auth\SessionsController@newly');
Route::get('/omniauth_callbacks', 'Auth\SessionsController@create');
```

トップページコントローラを作る。

```php:app/Http/Controllers/TopsController.php
class TopsController extends Controller
{
   public function __construct()
   {
     parent::__construct();
   }

   public function index()
   {
     return view('welcome');
   }
}
```

ログインコントローラを作る。
元々あるLoginControllerをSessionsControllerにコピーします。（Rails利用者なので、なんとなくSessionsControllerにしました。深い理由はありません。）

```
$ cp app/Http/Controllers/Auth/LoginController.php app/Http/Controllers/Auth/SessionsController.php
$ mkdir resources/views/auth
$ mkdir resources/views/auth/sessions
```

Providerを継承元のControllerに定義する。

```php:app/Http/Controllers/Controller.php
  protected $provider;
  public function __construct()
  {
    $clientId = '認証情報登録時に発行されたクライアントID';
    $clientSecret = '認証情報登録時に発行されたクライアントシークレット';
    $redirectUri = 'http://localhost:8000/omniauth_callbacks';

    session_start();
    $this->provider = new \OAuthClient2Google([
      'clientId' => $clientId,
      'clientSecret' => $clientSecret,
      'redirectUri' => $redirectUri
    ]);
  }
```

ログイン用のコントローラでログインする。
ログイン後は、"/"へリダイレクトします。

```php:app/Http/Controllers/Auth/SessionsController.php
  protected $redirectTo = '/';

  public function newly()
  {
    $authUrl = $provider->getAuthorizationUrl();
    $_SESSION['oauth2state'] = $provider->getState();
    return redirect($authUrl);
  }
  public function create()
  {
    if (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
      throw new Exception('invalid state');
    }
    $token = $this->provider->getAccessToken('authorization_code', [
        'code' => $_GET['code']
    ]);

    $_SESSION['token'] = serialize($token);

    return redirect($this->redirectTo);
  }
```

/login/new でアクセスし、Google側へリダイレクトすることを確認。



ログイン後のトップページでユーザ情報を取得するようコントローラを改修

```php:app/Http/Controllers/TopsController.php
class TopsController extends Controller
{
   public function __construct()
   {
     parent::__construct();
   }

   public function index()
   {
     return $this->isLogin() ? $this->top() : $this->welcome();
   }
   public function welcome()
   {
     return view('welcome');
   }
   private function top()
   {
     $token = unserialize($_SESSION['token']);
     $user = $this->provider->getResourceOwner($token);

     return view('top', ['user' => $user]);
   }
   private function isLogin()
   {
     return !empty($_SESSION['token']);
   }
}
```

ログイン後のviewを作成

```php:resources/views/top.blade.php
 <pre>
 <?php print_r($user); ?>
 <?php print_r(get_class_methods($user)); ?>
 </pre>
 <?php echo $user->getId(); ?><br />
 <?php echo $user->getName(); ?><br />
 <?php echo $user->getFirstName(); ?><br />
 <?php echo $user->getLastName(); ?><br />
 <?php echo $user->getEmail(); ?><br />
 <img src="<?php echo $user->getAvatar(); ?>" /><br />
```

ログイン後のページでエラーが出る場合は、利用API選定が完了していません。

```
Something went wrong: Access Not Configured. Google+ API has not been used in project xxxxxxxxxxxx before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/plus/overview?project=xxxxxxxxxxxx then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
```

URL（ https://console.developers.google.com/apis/api/plus/overview?project= ）に飛んで、「有効にする」というリンクをクリックしてください。

次はメールを送ってみます。