Coder Social home page Coder Social logo

Reissue JWT when expired about php-jwt HOT 12 CLOSED

firebase avatar firebase commented on August 20, 2024 1
Reissue JWT when expired

from php-jwt.

Comments (12)

fjaguado avatar fjaguado commented on August 20, 2024 36

This is how I reissue the same token updating times. I catch the 'ExpiredException' and then I try to decode again with a huge leeway:

 public static function refresh($token) {
         try{
             $decoded = JWT::decode($token, JWT_SECRET, ['HS256']);
             //TODO: do something if exception is not fired
         }catch ( \Firebase\JWT\ExpiredException $e ) {
             JWT::$leeway = 720000;
             $decoded = (array) JWT::decode($token, JWT_SECRET, ['HS256']);
             // TODO: test if token is blacklisted
             $decoded['iat'] = time();
             $decoded['exp'] = time() + self::$offset;

             return JWT::encode($decoded, JWT_SECRET);
         }catch ( \Exception $e ){
             var_dump($e);
         }
     }

from php-jwt.

DougHayward avatar DougHayward commented on August 20, 2024 10

I'm not sure if my way around this is correct, but I'll air it for opinions anyway.

What I do is issue a Token on successful authorization, with an hour validity. Then on every subsequent I check the token, and then create a new token return it to the client and save it to the file-system, overwriting the previous one. This way, as long as the user remains active their token will never be out of date.

from php-jwt.

tuupola avatar tuupola commented on August 20, 2024 8

Tokens are just Base64 encoded data with a signature. You can access header and payload with something like following:

list($header, $payload, $signature) = explode(".", $token);

print base64_decode($header) . "\n";
print base64_decode($payload) . "\n";

from php-jwt.

parmap avatar parmap commented on August 20, 2024 8

Because i run into same problem, i used little bit different solution

        try {
            $data = JWT::decode($accessToken);
        } catch (ExpiredException $e) {
            \Firebase\JWT\JWT::$timestamp = 0;
            $data = JWT::decode($accessToken);
        }
        ...

it's little bit better, because if you have non expiring refresh token, which can gain new access token, then you don't have to worry which leeway is enough, cause the condition is ($timestamp - static::$leeway) >= $payload->exp, so this solution will success with any exp higher then zero.

from php-jwt.

cottton avatar cottton commented on August 20, 2024 8

Im worried about how users above are using JWT.

JWT is meant to be stateless. They are signed - so they are immutable.
They reason why we should use them is to NOT check the storage on the server side.

// incomming JWT
if isValid(JWT)
    data = getData(JWT)
    // further checks (authorization) and execute requested action
else
    return non success 401 Unauthorized

If you request f.e. a database to check if the JWT is valid on EVERY request
then you should not use JWT.


Refesh:
If a token is not valid then you create a NEW one.
Ofc you could reuse the data inside the JWT.
BUT this would mean you have to check if nothing else failed.
In this repo you are lucky: ExpiredException gets thrown last. Means all other checks has been passed - so f.e. the signature is valid.
BUT this does NOT mean you should reuse the data from the invalid token.
Few updates later the ExpiredException gets thrown at the beginning of ::decode and all of you are using non-validated data from a manipulated JWT.

What you do if the token has been expired?

You return an error response.
The client that requested the action now has to check if and WHY the action got denied.

Draft:

// client request 
jwt = this->getJWT() // load JWT from storage
client = new HttpClient()
client->setUrl(url) // set your request target (f.e. get list of product items ...)
client->setAuthorizationHeader(jwt)
response = client->get()
if response->isSuccess()
    data response->getBody()
    // ... success handling ...
else
    // request denied
    if response->getStatusCode === 401
        // invalid token server response
        // lets get a new one
        refreshToken = this->getRefreshToken() // load refresh token from storage
        client = new HttpClient()
        client->setUrl(this->getServerRefreshUrl())
        client->setAuthorizationHeader(refreshToken)
        response = client->get()
        if response->isSuccess()
            // refresh-request success
            // received new access- AND refresh-token from server
            // store new tokens
            data = response->getBody()
            jwt = data[access_token]
            resfreshToken = data[refresh_token]
            this->saveJWT(jwt) // overwrite existing
            this->save(refreshToken) overwrite existing
            // execute actual request again (see above)
        else
            // refresh-request failure
            // need to login to receive new JWT and refresh token
            loginCredentials = this->getLoginCredentials()
            client = new HttpClient()
            client->setUrl(this->getServerLoginUrl())
            response = client->post(loginCredentials)
            if response->isSuccess()
                // login-request success
                // received access- AND refresh-token from server
                // store tokens
                data = response->getBody()
                jwt = data[access_token]
                resfreshToken = data[refresh_token]
                this->saveJWT(jwt) // overwrite existing
                this->save(refreshToken) overwrite existing   
                // execute actual request again (see above)
            else
                // invalid login attempt
                // ... handle invalid login credentials ...
    else
        // response is not 401 --further error handling (404? ...)

Ofc this needs to be written clean in functions|methods.

To answer the original question: no, you should not reuse the JWT data.
Except you can make sure that all other checks have been made - so f.e. the signature on the JWT was valid.
The server creates a new JWT and MUST use the current data from the storage.
This f.e. would prevent using expired or modified data like permissions (that has been revoked|changed).

from php-jwt.

williamqian avatar williamqian commented on August 20, 2024 4

@fjaguado so if the token was revealed,it will be used forever?

from php-jwt.

markCornejo avatar markCornejo commented on August 20, 2024 3

@parmap

 public static function refresh($token) {
         try{
             $decoded = JWT::decode($token, JWT_SECRET, ['HS256']);
             //TODO: do something if exception is not fired
         }catch ( \Firebase\JWT\ExpiredException $e ) {
             JWT::$leeway = 720000;
             $decoded = (array) JWT::decode($token, JWT_SECRET, ['HS256']);
             // TODO: test if token is blacklisted
             $decoded['iat'] = time();
             $decoded['exp'] = time() + self::$offset;

             return JWT::encode($decoded, JWT_SECRET);
         }catch ( \Exception $e ){
             var_dump($e);
         }
     }

I have tested this code and it generates a new different token. I thought that this code refreshes me the lifetime of my original token. But it generates a new one for me.
No way to refresh the same token without changing it?

from php-jwt.

SiasMey avatar SiasMey commented on August 20, 2024 2

You probably shouldnt.

The better thing and apparently more standard is to have a seperate second token in storage that is only allowed to refresh the main token.

So you have a token that expires in say ... an hour. You also have a second token that expires in 2 hours, but only has permission to refresh the main token. This will give the client an hour after their token expires to request a refreshed token using the "refresh" token that is still ok.

This interaction allows you to set up a workflow where if a client is idle for longer than a certain period, their tokens expire, but while they are active, their tokens will be kept up to date.

from php-jwt.

tyson1987 avatar tyson1987 commented on August 20, 2024

i would also like to know how to reissue a jwt token within datapower.

from php-jwt.

dperjar avatar dperjar commented on August 20, 2024

@ashraful88 That's probably not best practice. Check this out: http://stackoverflow.com/questions/3487991/why-does-oauth-v2-have-both-access-and-refresh-tokens

from php-jwt.

AmrAbdalrahman avatar AmrAbdalrahman commented on August 20, 2024

@williamqian No
this line

$decoded['exp'] = time() + self::$offset

refer to expiration date with $offset added to current time in seconds.

from php-jwt.

nmvuong92 avatar nmvuong92 commented on August 20, 2024

### ### ### ### good

from php-jwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.