Jwt-auth: Laravel Middleware - Json Reponse

Created on 10 Jun 2017  ·  10Comments  ·  Source: tymondesigns/jwt-auth

Hi,

I was wondering if anyone knows how I can get JSON Response for "Invalid Tokens" or "Expired Token" instead of the full html response. I am not sure if this is the right place to ask this, please redirect me.

Appreciate your help.

Most helpful comment

I'm facing the same problem when using Laravel 5.6 and "tymon/jwt-auth": "1.0.*"
Here's my approach to fix that.

  1. Open app\Exceptions\Handler.php
  2. Edit render method
/**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        // detect instance
        if ($exception instanceof UnauthorizedHttpException) {
            // detect previous instance
            if ($exception->getPrevious() instanceof TokenExpiredException) {
                return response()->json(['status' => 'token_expired'], $exception->getStatusCode());
            }
            else if ($exception->getPrevious() instanceof TokenInvalidException) {
                return response()->json(['status' => 'token_invalid'], $exception->getStatusCode());
            }
            else if ($exception->getPrevious() instanceof TokenBlacklistedException) {
                return response()->json(['status' => 'token_blacklisted'], $exception->getStatusCode());
            }
        }
        return parent::render($request, $exception);
    }
````

also dont forget to import all of required class.

namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

class Handler extends ExceptionHandler
{
```
Hope this could help someone :)

All 10 comments

Look at the wiki https://github.com/tymondesigns/jwt-auth/wiki/Authentication section "Global exception handling".

Hope this helps.

Tried that, but it seems that exceptions are instances of Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException, not from jwt-auth exception classes. Is there any other way to check what is the cause of the exception and send a related message in json?

I had it working like:

<?php

namespace App\Http\Middleware;

use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Middleware\GetUserFromToken;

class VerifyJWT extends GetUserFromToken
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, \Closure $next)
    {
        $user = null;
        if ($request->expectsJson()) {
            if (!$token = $this->auth->setRequest($request)->getToken()) {
                $this->tokenFailureHandler();
            }
            try {
                $user = $this->auth->authenticate($token);
            } catch (TokenExpiredException $e) {
                $this->tokenFailureHandler();
            } catch (JWTException $e) {
                $this->tokenFailureHandler();
            }

            if (!$user) {
                return $this->respond('tymon.jwt.user_not_found', 'user_not_found', 404);
            }

            $this->events->fire('tymon.jwt.valid', $user);

            return $next($request);
        }

        // If there is any custom Implementation on non Ajax
        return parent::handle($request, $next);
    }

and my App\Http\Kernel

<?php

namespace App\Http;

use App\Http\Middleware\VerifyJWT;
// .... other imports.
use Illuminate\Foundation\Http\Kernel as HttpKernel;


class Kernel extends HttpKernel
{
//... Your Kernel impl....
    protected $routeMiddleware = [
        'jwt.auth'    => VerifyJWT::class,
        'jwt.refresh' => RefreshToken::class,
    ];
}

for my $this->tokenFailureHandler() I just handled as json

private function tokenFailureHandler()
{
    return response()->json(['my_custom_key' => 'value']);
}

I'm using the dev-develop version. I have tried the various solutions provided still shows

Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException: Token Signature could not be verified.

I want to return a json error instead of the HTML error

Thanks

I had it working like this

`

namespace App\Http\Middleware;

use Closure;
use JWTAuth;
use Exception;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use App\Http\Traits\ApiTrait;

class authJWT extends BaseMiddleware
{
use ApiTrait;

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    try {
        $user = JWTAuth::parseToken()->authenticate();
    } catch (Exception $e) {
        if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
            return $this->respondWithError("Token is Invalid");
        }else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
            return $this->respondWithError(['error'=>'Token is Expired']);
        }else{
            return $this->respondWithError(['error'=>'Something is wrong']);
        }
    }
    return $next($request);
}

}`

With this extending the BaseMiddleware Class, you can return the error in json format without tampering with the vendor code.

I could see that this thread is closed but i had to re-open it as i was facing issues while using the dev-develop version

@tymondesigns Hope this will be fixed

I'm facing the same problem when using Laravel 5.6 and "tymon/jwt-auth": "1.0.*"
Here's my approach to fix that.

  1. Open app\Exceptions\Handler.php
  2. Edit render method
/**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        // detect instance
        if ($exception instanceof UnauthorizedHttpException) {
            // detect previous instance
            if ($exception->getPrevious() instanceof TokenExpiredException) {
                return response()->json(['status' => 'token_expired'], $exception->getStatusCode());
            }
            else if ($exception->getPrevious() instanceof TokenInvalidException) {
                return response()->json(['status' => 'token_invalid'], $exception->getStatusCode());
            }
            else if ($exception->getPrevious() instanceof TokenBlacklistedException) {
                return response()->json(['status' => 'token_blacklisted'], $exception->getStatusCode());
            }
        }
        return parent::render($request, $exception);
    }
````

also dont forget to import all of required class.

namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

class Handler extends ExceptionHandler
{
```
Hope this could help someone :)

При отправке запроса необходимы два заголовка, для ответа сервера в формате json
Content-Type : application/json
Accept: application/json

Faced this issue in Laravel 6.2 and tried using @nsulistiyawan code, but using

$exception->getPrevious()

always returns null. Probably because something changed in Laravel's Router implementation. So I modified the code to use UnauthorizedHttpException messages and it got the job done.

public function render($request, Exception $exception)
    {
        if ($exception instanceof UnauthorizedHttpException) {
            return response()->json(['error' => $exception->getMessage()], $exception->getStatusCode());
        }

        return parent::render($request, $exception);
    }

But it would be nice to modify the message according to the exception type. Does anyone know how to solve this now?

Faced this issue in Laravel 6.2 and tried using @nsulistiyawan code, but using

$exception->getPrevious()

always returns null. Probably because something changed in Laravel's Router implementation. So I modified the code to use UnauthorizedHttpException messages and it got the job done.

public function render($request, Exception $exception)
    {
        if ($exception instanceof UnauthorizedHttpException) {
            return response()->json(['error' => $exception->getMessage()], $exception->getStatusCode());
        }

        return parent::render($request, $exception);
    }

But it would be nice to modify the message according to the exception type. Does anyone know how to solve this now?

I have the same problem, $exception->getPrevious() get null in laravel 7, Does anyone know how to solve this now?

I'm facing the same problem when using Laravel 5.6 and "tymon/jwt-auth": "1.0.*"
Here's my approach to fix that.

  1. Open app\Exceptions\Handler.php
  2. Edit render method
/**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        // detect instance
        if ($exception instanceof UnauthorizedHttpException) {
            // detect previous instance
            if ($exception->getPrevious() instanceof TokenExpiredException) {
                return response()->json(['status' => 'token_expired'], $exception->getStatusCode());
            }
            else if ($exception->getPrevious() instanceof TokenInvalidException) {
                return response()->json(['status' => 'token_invalid'], $exception->getStatusCode());
            }
            else if ($exception->getPrevious() instanceof TokenBlacklistedException) {
                return response()->json(['status' => 'token_blacklisted'], $exception->getStatusCode());
            }
        }
        return parent::render($request, $exception);
    }

also dont forget to import all of required class.

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;

class Handler extends ExceptionHandler
{

Hope this could help someone :)

Does this work in laravel 7? $exception->getPrevious() get null

Was this page helpful?
0 / 5 - 0 ratings

Related issues

therealmjk picture therealmjk  ·  3Comments

johncloud200 picture johncloud200  ·  3Comments

lloy0076 picture lloy0076  ·  3Comments

gandra picture gandra  ·  3Comments

heroghost picture heroghost  ·  3Comments