미들웨어에서 토큰이 만료되었으면 갱신한뒤 response 헤더에 갱신된 토큰을 보내준다.
프론트에서는 response.data 에 refreshed_token이 있을경우 기존토큰을 버리고 이 토큰을 저장하고 사용한다.
[code]
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Closure;
use Auth;
use JWTAuth;
class Authenticate extends Middleware
{
public function handle($request, Closure $next, …$guards)
{
if ($request->is(‘api/*’)) {
try {
JWTAuth::parseToken()->authenticate();
} catch (\Exception $e) {
// 잘못된 토큰일때
if ($e instanceof TokenInvalidException) {
$status = 401;
$message = ‘This token is invalid. Try login’;
return response()->json(compact(‘status’, ‘message’), 401);
// 토큰이 만료되었을 때
} elseif ($e instanceof TokenExpiredException) {
try {
// 토큰 갱신
$refreshed_token = Auth::guard(‘api’)->refresh();
JWTAuth::setToken($refreshed_token)->toUser();
$response = $next($request);
$content = json_decode($response->content(), true);
// response.data 에 refresh 된 토큰을 추가해 준다
if (json_last_error() === JSON_ERROR_NONE) {
$content[‘refreshed_token’] = $refreshed_token;
$content = json_encode($content);
$response->setContent($content);
}
return $response;
} catch (JWTException $e) {
return response()->json([
‘code’ => 103,
‘message’ => ‘Token cannot be refreshed, Try login again’
], 401);
}
} else {
$message = ‘Authorization Token not found’;
return response()->json(compact(‘message’), 404);
}
}
return $next($request);
} else {
$this->authenticate($request, $guards);
return $next($request);
}
}
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if ($request->expectsJson() || $request->is(‘api/*’)) {
return route(‘api.unauthorized’);
}
return route(‘login’);
}}
[/code]
nuxt 에서의 처리
/plugins/axios.js
[code]
export default function ({ $axios, store }) {
// 응답 status 가 200 대가 아니면 에러처리
$axios.defaults.validateStatus = (status) => {
return status >= 200 && status < 300
}
// 요청시 header 에 토큰 실어보냄
$axios.onRequest((config) => {
config.headers.common.Authorization = `Bearer ${store.state.auth.access_token}`
})
// 토큰 refresh 되었을때 처리
$axios.interceptors.response.use(
(response) => {
const data = response.data
if (data.refreshed_token) {
store.commit(‘auth/SET_TOKEN’, data.refreshed_token)
}
return response
},
(error) => {
return Promise.reject(error)
}
)
}
[/code]