I've gone around the multiple posts around the same issue and it can't seem to cover my case.
My idea:
I'm using JWT to authenticate users and my idea is to determine that whenever a token is nearly expiration date, I want to return a new token within the headers (Header Authorization).
I've got this middleware made, just to test some things out
public function handle($request, Closure $next)
{
try {
$user = JWTAuth::parseToken()->authenticate();
$claims = JWTAuth::getPayload(JWTAuth::getToken())->toArray();
if ($claims['exp'] - (strtotime(date("Y-m-d H:i:s"))) <= 900) {
$token = JWTAuth::refresh(JWTAuth::getToken());
header('Authorization: Bearer ' . $token);
}
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException) {
return $this->response([], 'Authorization Token is Invalid', 401);
} elseif ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException) {
try {
$token = JWTAuth::refresh(JWTAuth::getToken());
header('Authorization: Bearer ' . $token);
return $this->response([], 'Authorization Token is Expired', 401);
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
return $this->response([], 'Authorization Token is Invalid', 401);
}
} else {
return $this->response([], 'Authorization Token not found', 401);
}
}
return $next($request);
}
So far so good, testing with POSTMAN I get my desirable outcome. However, I went along to write down an acceptance test in order to test that indeed, this is correct.
public function testUserReceivesNewTokenInHeaderWhenExpiresAtIsWithin15Minutes()
{
//Arrange
$token = JWTAuth::claims(['exp' => strtotime("+1 minutes", strtotime(date('Y-m-d H:i:s')))])->fromUser($this->user);
$this->headers['HTTP_Authorization'] = "Bearer $token";
//Act
$response = $this->get('/api/justAnotherURL', $this->headers);
//Assert
$response->assertStatus(200);
$this->assertTrue($response->headers->has('Authorization'));
}
I set the exp
date to be within the next minute (so it enters the validation above), it does enter as expected, but when it reaches Header(Authorization: Bearer $token)
, it throws an Exception
:
Cannot modify header information - headers already sent by (output started at /var/www/project/vendor/phpunit/phpunit/src/Util/Printer.php:109)
As far as my research goes (and attempts), it's something about outputting the request on the console, but I've been unsuccessful so far.
Related post: How to fix "Headers already sent" error in PHP
Small notes:
this->response
is my own custom response to the request, you can ignore that
Tried @runInSeparateProcess
from another post and error dissapears, but the header isn't set (default header is returned)
Edit: I've tried placing the header at the top of the file, before the try catch and it remains the same (I was wondering if jwt would make some output without me knowing) and this is the only middleware being used atm