Middleware para extender token y cookie en Laravel
<?php
namespace App\Http\Middleware;
use App\Auth\CreateTokenService;
use App\Http\Controllers\Auth\CreateTokenCookie;
use Closure;
use Illuminate\Support\Facades\Log;
use ReallySimpleJWT\Exception\ValidateException;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Http\Request;
class ExtendCookieToken
{
use CreateTokenCookie;
/** @var CreateTokenService */
protected $createTokenService;
/**
* ExtendCookieToken constructor.
* @param CreateTokenService $tokenService
*/
public function __construct(CreateTokenService $tokenService)
{
$this->createTokenService = $tokenService;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $next($request);
try {
return $this->extend($response, $request);
} catch (ValidateException $e) {
Log::error($e->getMessage());
return $response;
}
}
/**
* Encrypt the cookies on an outgoing response.
*
* @param Response $response
* @param Request $request
* @return Response
* @throws ValidateException
*/
protected function extend(Response $response, Request $request): Response
{
if (strpos($request->getUri(), 'logout')) {
return $response;
}
try {
$cookie = $this->searchCookieToken($response);
if (is_null($cookie)) {
return $this->createCookieIfNotPresent(
$request,
$response
);
}
$token = $cookie->getValue() ?? '';
if ($token === '') {
return $response;
}
$newToken = $this->createTokenService->regenerateToken($token);
$response->headers->setCookie(
$this->duplicateWithNewExpireTime($cookie, $newToken)
);
Log::info('cookies', $response->headers->getCookies());
return $response;
} catch (ValidateException $e) {
return $response;
}
}
protected function createCookieIfNotPresent(
Request $request,
Response $response
): Response
{
$user = $request->user();
$cookie = $this->createTokenCookie($user);
$response->headers->setCookie($cookie);
return $response;
}
/**
* @param Response $response
* @return Cookie|null
*/
protected function searchCookieToken(Response $response): ?Cookie
{
$cookies = $response->headers->getCookies();
if (empty($cookies)) {
return null;
}
foreach ($cookies as $cookie) {
if ($cookie->getName() === 'token') {
return $cookie;
}
}
return null;
}
/**
* Duplicate a cookie with a new value.
*
* @param Cookie $cookie
* @param string $value
* @param int|null $newExpire
* @return Cookie
*/
protected function duplicateWithNewExpireTime(
Cookie $cookie,
string $value,
int $newExpire = null
) {
$defaultExpireTime = time() + $this->createTokenService->getTokenExpireTime();
$expires = is_null($newExpire) ? $defaultExpireTime : $newExpire;
return new Cookie(
$cookie->getName(), $value, $expires,
$cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(),
$cookie->isHttpOnly(), $cookie->isRaw(), $cookie->getSameSite()
);
}
}