Laravel JWT tokens are Invalid after refresh them in a authentication JWT approach

前端 未结 1 1881
眼角桃花
眼角桃花 2021-02-14 23:15

EDIT:

Read the discussion about the bug at: https://github.com/tymondesigns/jwt-auth/issues/83

MY ORIGINAL QUESTION:

I\

相关标签:
1条回答
  • 2021-02-14 23:34

    When I get this issue, the solution that I found to get my project working was to generate a new token with data from older token on each new request.

    My solution, that works for me, is bad, ugly, and can generate more issues if you have many async requests and your API(or business core) server is slow.

    For now is working, but I will investigate more this issue, cause after 0.5.3 version the issue continues.

    E.g:

    Request 1 (GET /login):

    Some guest data on token
    

    Request 2 (POST /login response):

    User data merged with guest data on old token generating a new token
    

    Procedural code example(you can do better =) ), you can run this on routes.php out of routes, I say that is ugly haha:

    // ----------------------------------------------------------------
    // AUTH TOKEN WORK
    // ----------------------------------------------------------------
    $authToken = null;
    $getAuthToken = function() use ($authToken, $Response) {
        if($authToken === null) {
             $authToken = JWTAuth::parseToken();
        }
        return $authToken;
    };
    
    $getLoggedUser = function() use ($getAuthToken) {
        return $getAuthToken()->authenticate();
    };
    
    $getAuthPayload = function() use ($getAuthToken) {
        try {
            return $getAuthToken()->getPayload();
        } catch (Exception $e) {
            return [];
        }
    };
    
    $mountAuthPayload = function($customPayload) use ($getLoggedUser, $getAuthPayload) {
        $currentPayload = [];
        try {
            $currentAuthPayload = $getAuthPayload();
            if(count($currentAuthPayload)) {
                $currentPayload = $currentAuthPayload->toArray();
            }
            try {
                if($user = $getLoggedUser()) {
                    $currentPayload['user'] = $user;
                }
                $currentPayload['isGuest'] = false;
            } catch (Exception $e) {
                // is guest
            }
        } catch(Exception $e) {
            // Impossible to parse token
        }
    
        foreach ($customPayload as $key => $value) {
            $currentPayload[$key] = $value;
        }
    
        return $currentPayload;
    };
    
    // ----------------------------------------------------------------
    // AUTH TOKEN PAYLOAD
    // ----------------------------------------------------------------
    try {
        $getLoggedUser();
        $payload = ['isGuest' => false];
    } catch (Exception $e) {
        $payload = ['isGuest' => true];
    }
    
    try {
        $payload = $mountAuthPayload($payload);
    } catch (Exception $e) {
        // Make nothing cause token is invalid, expired, etc., or not exists.
        // Like a guest session. Create a token without user data.
    }
    

    Some route(simple example to save user mobile device):

    Route::group(['middleware' => ['before' => 'jwt.auth', 'after' => 'jwt.refresh']], function () use ($getLoggedUser, $mountAuthPayload) {
        Route::post('/session/device', function () use ($Response, $getLoggedUser, $mountAuthPayload) {
            $Response = new \Illuminate\Http\Response();
            $user = $getLoggedUser();
    
            // code to save on database the user device from current "session"...
    
            $payload = app('tymon.jwt.payload.factory')->make($mountAuthPayload(['device' => $user->device->last()->toArray()]));
            $token = JWTAuth::encode($payload);
            $Response->header('Authorization', 'Bearer ' . $token);
    
            $responseContent = ['setted' => 'true'];
    
            $Response->setContent($responseContent);
            return $Response;
        });
    });
    
    0 讨论(0)
提交回复
热议问题