Laravel 5.3 API認証(Passport)
基本的な導入はここと同じ事をしました。
少し違う事といえば view側とサーバ側を別々にしているので access-control-allow-origin
の対応に関しては少し処理を加えました。
CORs
-
php artisan make:middleware Cors
でmiddlewareの追加 -
App\Http\Middleware\Cors.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が発行されない。