[memo] Vagrant + Laravel5.3 に laravel/passport 導入で躓いた事

[Laravel 5.3 API認証(Passport)](https://readouble.com/laravel/5.3/ja/passport.html)
基本的な導入はここと同じ事をしました。
少し違う事といえば　view側とサーバ側を別々にしているので `access-control-allow-origin`の対応に関しては少し処理を加えました。

# CORs

- `php artisan make:middleware Cors`でmiddlewareの追加
- `App\Http\Middleware\Cors.php` を以下の記述

````php
  public function handle($request, Closure $next)
  {
    $response = $next($request);
    $response->headers->set('Access-Control-Allow-Origin', '許可するドメイン' );
    $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE' );
    $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, X-XSRF-TOKEN' );
    return $response;
  }
```

- `App/Http/Kernel.php`に `Cors::class`の追加

```php
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
        \App\Http\Middleware\Cors::class
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'cors',
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'cors' => \App\Http\Middleware\Cors::class
    ];
```

- `App\Providers\AuthServiceProvider.php` の `Passport::routes();`部分を以下に修正

```php
      Route::group([ 'middleware' => 'cors' ], function() {
        Passport::routes();
      });
```

# 躓いた箇所
## 現象
アクセストークンを取得はできるが、その取得したトークンをヘッダーに入れてリクエストを出したときに、 `auth:api`のmiddlewareの処理でunauthorizedになった事。

## 調べて行く間にわかった事
- `vendor/laravel/passport/src/Guards/TokenGuard.php`内にある

```php
    /**
     * Get the user for the incoming request.
     *
     * @param  Request  $request
     * @return mixed
     */
    public function user(Request $request)
    {
        if ($request->bearerToken()) {
            return $this->authenticateViaBearerToken($request);
        } elseif ($request->cookie(Passport::cookie())) {
            return $this->authenticateViaCookie($request);
        }
    }
```

- `$request`内のヘッダー情報に `Authorization`が入っていなかったが、そのほかのヘッダー情報は問題なく入っていた。
- しかし、 `getallheaders()`には問題なく `Authorization`がはいっていた。

# 解決
## 原因
基本$_SERVERから `Authorization`の値は取得できないが

`public/.htaccess` で

```php
    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
```

上記記述で$_SERVERから `Authorization`が取得できるようになる。<-これまもともと記述されていた。
しかし、vagrantをつかっている場合、 `.htaccess`を無効にしてしまっていると、上記記述が反映されない。 <- これが今回の根本の原因。

## 対応
`/etc/httpd/conf.d/vhost.conf`　に上記記述を追加してあげる。

以上で無事解決した。

#追記

## refresh token を使用してaccess tokenの更新を行う際の注意事項

```js

{
    "client_id": 2,
    "client_secret": "oauth_clientsのid2の値",
    "grant_type": "refresh_token",
    "scope": "",
    "refresh_token": "access token取得時に取得したrefresh token"
}
```

上記をPOSTすると取得できるが、headerの `Content-Type` を `application/x-www-form-urlencoded` ではなく `application/json`　にし、パラメータをJsonにして送る。でないと、`refresh_token` の値の中に `+`が含まれているので、それがphp 側で受け取る際にスペースになってしまい、404になってaccess tokenが発行されない。