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
の追加
/**
* 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();
部分を以下に修正
Route::group([ 'middleware' => 'cors' ], function() {
Passport::routes();
});
躓いた箇所
現象
アクセストークンを取得はできるが、その取得したトークンをヘッダーに入れてリクエストを出したときに、 auth:api
のmiddlewareの処理でunauthorizedになった事。
調べて行く間にわかった事
-
vendor/laravel/passport/src/Guards/TokenGuard.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
で
# 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の更新を行う際の注意事項
{
"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が発行されない。