
Laravelのミドルウェア機能を利用して実装していきます😊
LaravelのMiddlewareは
- リクエストデータ → Middleware → コントローラ → モデル → コントローラ → レスポンス
もくじ
トークンの検証用Middleware CheckToken
ミドルウェアの作成
$ php artisan make:middleware CheckRefreshToken
ミドルウェアの実装
app/Http/Middleware/CheckRefreshToken.php
<?php
namespace App\Http\Middleware;
use Closure;
class CheckToken
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
雛形ができたな!
カスタマイズしていく
app/Http/Middleware/CheckRefreshToken.php
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Illuminate\Support\Facades\Config;
class CheckRefreshtoken
{
/**
* リクエストのヘッダーのトークンを検証
*
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$string = $token = JWTAuth::getToken();
// ヘッダーにAuthorizationが存在するかをチェック
if ((!$request->header('Authorization'))) {
return response()->json([
'error' => Config::get('error.headerAuthorizationMissing')
]);
}
try {
// トークンに含まれているユーザは存在するかをチェック
if (!$user = JWTAuth::parseToken()->authenticate()) {
return response()->json([
'error' => Config::get('error.invalidToken')
]);
}
} catch (TokenInvalidException $e) {
// 無効なリフレッシュトークンによるエラー
return response()->json([
'error' => Config::get('error.invalidRefreshToken')
]);
} catch (TokenExpiredException $e) {
// リフレッシュトークンの有効期限切れによるエラー
return response()->json([
'error' => Config::get('error.expiredRefreshToken')
]);
} catch (JWTException $e) {
// その他の原因によるトークンのエラー
return response()->json([
'error' => Config::get('error.tokenSomethingWentWrongError')
]);
}
// コントローラにリクエストを送る
$response = $next($request);
return $response;
}
}
$response = $next($request);
ここで$next()クロージャを利用してコントローラにリクエストを送っています。
それからエラーハンドリングを行うので非同期的な実装になっています。
app/Http/Middleware/CheckAccessToken.php
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Config;
class CheckAccessToken
{
/**
* リクエストのヘッダーのトークンを検証
*
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$string = $token = JWTAuth::getToken();
// ヘッダーにAuthorizationが存在するかをチェック
if ((!$request->header('Authorization'))) {
return response()->json([
'error' => Config::get('error.headerAuthorizationMissing')
]);
}
try {
// トークンに含まれているユーザは存在するかをチェック
if (!$user = JWTAuth::parseToken()->authenticate()) {
return response()->json([
'error' => Config::get('error.invalidToken')
]);
}
} catch (TokenInvalidException $e) {
// 無効なアクセストークンによるエラー
return response()->json([
'error' => Config::get('error.invalidAccessToken')
]);
} catch (TokenExpiredException $e) {
// アクセストークンの有効期限切れによるエラー
return response()->json([
'error' => Config::get('error.expiredAccessToken')
]);
} catch (JWTException $e) {
// その他の原因によるトークンのエラー
return response()->json([
'error' => Config::get('error.tokenSomethingWentWrongError')
]);
}
// コントローラにリクエストを送る
$response = $next($request);
return $response;
}
}
コンフィグの設定
エラーメッセージのレスポンスデータを定義します。
config/error.php
<?php
return [
'failedValidationError' => [
'code' => 400001,
'message' => 'リクエストの形式が異なります。'
],
'tokenSomethingWentWrongError' => [
'code' => 401000,
'message' => 'トークンのその他のエラーです。'
],
'headerAuthorizationMissing' => [
'code' => 401001,
'message' => 'authorizationヘッダが無い/空です。'
],
'invalidAccessToken' => [
'code' => 401002,
'message' => 'トークンが無効です。'
],
'expiredAccessToken' => [
'code' => 401003,
'message' => 'トークンが有効期限切れです。'
],
'tokenValidDate' => [
'code' => 401004,
'message' => 'トークンの発行日時がパスワード最終更新日時より前です。'
],
'wrongIdOrPassword' => [
'code' => 401005,
'message' => 'ログインidまたはパスワードが間違っています。'
],
'lockAccount' => [
'code' => 401006,
'message' => 'アカウントがロックされています。'
],
'refreshTokenValidDate' => [
'code' => 401007,
'message' => 'リフレッシュトークンが無効です。'
],
'refreshTokenExpireDate' => [
'code' => 401008,
'message' => 'リフレッシュトークンが有効期限切れです。'
],
・・・
コンフィグの反映
$ php artisan config:clear $ php artisan config:cache
ミドルウェアの登録
routes/api.phpで利用できるようにKernel.phpに定義します。
app/Http/Kernel.php
・・・
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+ 'jwt_auth' => \Tymon\JWTAuth\Http\Middleware\Authenticate::class,
+ 'jwt_refresh' => \App\Http\Middleware\CheckRefreshtoken::class,
+ 'jwt_access' => \App\Http\Middleware\CheckAccessToken::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
+ \App\Http\Middleware\CheckRefreshtoken::class,
+ \App\Http\Middleware\CheckAccessToken::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
}
ルーティング設定
api/V1_0/refresh-tokenを定義します。
routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::prefix('v1_0')->group(function () {
Route::middleware([
'jwt_refresh', // JWTリフレッシュトークン検証 - \App\Http\Middleware\CheckRefreshToken::class
])->group(function () {
Route::post('/refresh-token', 'Api\V1_0\RefreshTokenController@refreshToken');
});
Route::group([
"middleware" => 'guest:api', // 認証不要なAPIとして設定
], function () {
Route::post('/users/me', 'Api\V1_0\RegisterController@register');
Route::post('/login', 'Api\V1_0\LoginController@login');
Route::post('/login/guest', 'Api\V1_0\GuestLoginController@login');
});
});
@see
- https://github.com/tymondesigns/jwt-auth/issues/872
- https://blog.pusher.com/laravel-jwt/
- https://qiita.com/yh1224/items/bd00e85d5c53350e93ca
- https://dev-yakuza.github.io/laravel/jwt-user-info/



Laravel:6
tymon/jwt-auth: 1.0.0-rc.5
WebAPIにてJWTを実装しています。
ミドルウェアにて、トークンのチェックをしたく、参考にさせていただきました。
ありがとうございます。
トークンの発行やトークンのチェックは上手く動き、
問題なさそうなのですが、VSCodeデバッグ時にログイン処理を行うと、必ず下記例外が発生します。
Tymon\JWTAuth\Exceptions\JWTException: The token could not be parsed from the request
ログイン処理時は、認証チェックは動かないはずなのですが、
なぜでしょうか?
ルーティングは下記のようにしています。
// ゲスト
Route::group([‘guest’,’api’],function ()
{
// ログイン
Route::post(‘login’, ‘Auth\APILoginController@login’);
});
// JWT認証チェック
Route::middleware([‘api’,’jwt_access’])->group(function ()
{
// ユーザー登録
Route::post(‘register’, ‘Auth\APILoginController@register’);
// ユーザー変更
// ユーザー削除
// ログアウト
Route::post(‘logout’, ‘Auth\APILoginController@logout’);
// リフレッシュ
Route::post(‘refresh’, ‘Auth\APILoginController@refresh’);
// ログインユーザー情報
Route::post(‘me’, ‘Auth\APILoginController@me’);
});
参考になられたみたいで良かったです☺️
下記かな?
https://stackoverflow.com/questions/39218757/laravel-jwt-auth-the-token-could-not-be-parsed-from-the-request
ご提示された解像度ではこれ以上は難しいです、
ごめんなさい😭
少し先ですが1月25日に秋葉原で勉強会やるのでご都合よろしければ、
懇親会でご状況を確認することはできます🐱🌟
https://8989work.connpass.com/event/161585/
返信ありがとうございます。
結論から言うと、VSCodeのデバック時に、左側のブレークポインにて、
EverythingをOFFにすると、例外で止まる減少は起きなくなりました。
ただ、ライブラリにて例外が発生するのは、まぁ気になりますが、
実害なさそうなので、これで良しとします。
ありがとうございました:D
☺️