Reputation: 11
I'm developing an Api with Laravel 11 using Sanctum as the authentication method. I've set the token expiration to 7 days and I'd like the client to receive a 401 response 'Token invalid or expired' when the token expires. But this doesn't work.Instead, the client (here Postman) receives a 200 response with html content similar to the following
<!DOCTYPE html>
<html lang="en" class="style-basic">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>Laravel</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
<script type="text/javascript">
const Ziggy={"url":"http:\/\/localhost:8000","port":8000,"defaults":{},"routes":{"debugbar.openhandler":{"uri":"_debugbar\/open","methods":["GET","HEAD"]},"debugbar.clockwork":{"uri":"_debugbar\/clockwork\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"debugbar.assets.css":{"uri":"_debugbar\/assets\/stylesheets","methods":["GET","HEAD"]},"debugbar.assets.js":{"uri":"_debugbar\/assets\/javascript","methods":["GET","HEAD"]},"debugbar.cache.delete":{"uri":"_debugbar\/cache\/{key}\/{tags?}","methods":["DELETE"],"parameters":["key","tags"]},"debugbar.queries.explain":{"uri":"_debugbar\/queries\/explain","methods":["POST"]},"l5-swagger.default.api":{"uri":"api\/documentation".....
After some research, I modified the app/Exceptions/Handler file by adding the render function to return the expected response when authentication fails.
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Auth\AuthenticationException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
//
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $exception
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, Throwable $exception)
{
if ($exception instanceof AuthenticationException) {
return response()->json([
'message' => 'Token expiré ou invalide',
], 401);
}
return parent::render($request, $exception);
}
}
This is my api.php content
Route::group([
'namespace' => 'App\Http\Controllers\Api',
], function () {
// Route::middleware('api-domain')->group(function () {
Route::post('user-register', 'AuthenticationController@register')->name('user.account.register');
Route::post('user-login', 'AuthenticationController@login')->name('user.account.login');
....
Route::middleware('auth:sanctum')->group(function () {
Route::middleware('active-users')->group(function () {
Route::get('/user', 'AuthenticationController@getUserByToken')->name('user.token');
Route::get('user-logout', 'AuthenticationController@logout')->name('user.account.logout');
.....
});
});
// });
});
sanctum.php
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. This will override any values set in the token's
| "expires_at" attribute, but first-party sessions are not affected.
|
*/
'expiration' => 7 * 24 * 60,
app/Http/Kernel.php
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
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,
\App\Http\Middleware\HandleInertiaRequests::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\App\Http\Middleware\ForceJsonResponse::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'auth:sanctum',
],
];
And token creation in my controller
$token = $user->createToken($this->generateTokenName($user), [], Carbon::now()->addMinutes(config('sanctum.expiration')));
Upvotes: 1
Views: 54