0
votes

So I started using Tymon JWT package for Laravel for my SPA. Its all going good ( adding user, signing in, getting Auth user) but when I make an API request it only works for an hour. I understand that the token I stored on on login expires so when I make a request to the API after 60 minutes it doesnt work. My question is how do I refresh the token and restore it in my local storage? On a new request? Every 59 minutes?

AuthController.php

    public function authenticate(Request $request)
    {
        // grab credentials from the request
        $credentials = $request->only('email', 'password');

        try {
            // attempt to verify the credentials and create a token for the user
            if (! $token = JWTAuth::attempt($credentials)) {
                return response()->json(['error' => 'Sorry, we cant find you.']);
            }
        } catch (JWTException $e) {
            // something went wrong whilst attempting to encode the token
            return response()->json(['error' => 'could_not_create_token'], 500);
        }

        // all good so return the token
        $user = JWTAuth::toUser($token);

        //Fire off the login event
        event( new LoginSuccessful($user) );

        return response()->json( compact('token', 'user') );
    }

Login.vue

            axios.post('/api/authenticate',{
                email: this.email,
                password: this.password
            })
            .then(response => {

                if(response.data.error){

                    //Show the error
                    this.error = response.data.error
                    this.loading = false;

                } else {

                    this.loading = false;

                    //Store the items in storage
                    localStorage.setItem('jwt_token', response.data.token);
                    localStorage.setItem('user', JSON.stringify(response.data.user));

                    //Mutate the state
                    this.$store.commit('login');

                    //Now go to the dashboard
                    this.$router.push('dashboard');
                }

            })
            .catch(error => {

            });

in my head tag

<script>

    window.hopbak = {
        'jwt_token': localStorage.getItem('jwt_token'),
        'csrfToken': {!! json_encode( csrf_token() ) !!},
    };

</script>

in my bootstrap.js

let token = window.hopbak.jwt_token;

if (token) {

    window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;

} else {
    console.log('no token');
}
2
This is high level without any code to help, but when you receive the API token back, I would store this as well as the refresh token in local storage. Then when you are making an API call, add a catch to check if the error relates to the API token being expired and if it does then use the refresh token to get a new API token and then automatically retry the original request. - James

2 Answers

0
votes

I think you need to register the RefreshToken middleware in app/Http/Kernel.php:

protected $routeMiddleware = [
    'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken'
];

And then assign it to the routes you want to refresh the token.

Looking at the source code, I can tell that this middleware will handle the refreshing of your token in every request by adding a new token to the response header.

0
votes

JWT_TTL, JWT_REFRESH_TTL and JWT_BLACKLIST_GRACE_PERIOD values are setted in config/jwt.php file.

How does it work:

  1. The client sends the credentials (email and password) to Laravel and receives a token (JWT) in response. This token is valid for JWT_TTL minutes. During this time all requests with the header Authorization = "Bearer token" will be successful.
  2. For a request made after JWT_TTL minutes, that is, with the token expired, two situations will occur: (1) If there is less than JWT_REFRESH_TTL minutes since the creation of the token (the token carries within it the date of creation on claim IAT), then this token will be invalidated (blacklist) and a new token will be generated and sent as a response to the client. JWT_REFRESH_TTL defines how many minutes after creating the first token the new tokens can be created. For example, for JWT_REFRESH_TTL = 21600, new tokens will be generated for 15 days, after which time the user should reauthenticate. (2) The request occurs after JWT_REFRESH_TTL minutes after the first token was created. In this case, it will not be possible to generate a new token for the client and it must authenticate again. A 401 error will be sent to the client.
  3. When multiple concurrent requests are made with the same JWT, it is possible that some of them fail, due to token regeneration on every request. Set grace period in seconds to prevent parallel request failure, because the JWT will consider to be valid for JWT_BLACKLIST_GRACE_PERIOD seconds, even if it's on the blacklist.

For more details see this my explanation.