Code Monkey home page Code Monkey logo

Comments (21)

petejohanson avatar petejohanson commented on August 25, 2024 8

Thinking about this for my own scenario, I wonder if something like the following would work:

var refreshPromise;
jwtInterceptorProvider.tokenGetter = function(config) {
  if (refreshPromise) {
    return refreshPromise;
  }

  var token = window.localStorage.getItem('access_token');
  if (jwtHelper.isExpired(token)) {
    refreshPromise = refreshToken();
    return refreshPromise.then(r => {
      refreshPromise = null;
      return r;
    }, err => {
      refreshPromise = null;
      throw err;
    });
  }

  return token;
}

Re-using the promise created for refreshing the token should let your subsequent requests "queue up" until the token is refreshed, then all the awaiting requests would get the new token.

Caveats: I'm planning on trying this approach, but I'm not sure if the internals of angular-jwt will somehow conflict w/ this idea.

Authors: Thoughts?

from angular-jwt.

ajoslin103 avatar ajoslin103 commented on August 25, 2024 2

thanks to you both -- I know I'll hit this issue again soon

from angular-jwt.

GabrielGil avatar GabrielGil commented on August 25, 2024 2

Hey @zbjornson!!

You are definitely right, and actually I had modify like so in my code, but forgot to modify the example. I am fixing my previous comment and the PR I got open to include this in the documentation.

Thank you!

from angular-jwt.

ajoslin103 avatar ajoslin103 commented on August 25, 2024 1

that project finished with an acceptance on the login JWT expiring in 2hrs, rather than auto-renewing

and I’m not using Angular anymore, I’ve moved on to Aurelia

I hope to use JWT again in soon in which case I’ll have another go at starting from your snippet

thanks
al;

On Apr 27, 2016, at 10:47 AM, Pete Johanson [email protected] wrote:

@ajoslin103 https://github.com/ajoslin103 if you want to create a gist of your version and link it here, we can see if we can offer some advise?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub #57 (comment)

from angular-jwt.

zbjornson avatar zbjornson commented on August 25, 2024 1

Appreciate the examples and discussion here!

I had to modify @GabrielGil's approach slightly to store the new promise created by then, otherwise jwtInterceptor made the http request before the refresh promise had fully resolved (the network request has the header "Authorization: [object Object]")

angular.module('app', ['angular-jwt'])
.config(function Config($httpProvider, jwtInterceptorProvider) {
    var refreshPromise;
    jwtInterceptorProvider.tokenGetter = ['jwtHelper', '$http', function(jwtHelper, $http) {
        if (refreshPromise) {
            return refreshPromise;
        }
        var idToken = localStorage.getItem('id_token');
        if (jwtHelper.isTokenExpired(idToken)) {
            var refreshToken = localStorage.getItem('refresh_token');
            // This is a promise of a JWT id_token
            refreshPromise = $http({
                url: '/delegation',
                // This makes it so that this request doesn't send the JWT
                skipAuthorization: true,
                method: 'POST',
                data: { 
                    grant_type: 'refresh_token',
                    refresh_token: refreshToken 
                }
            }).then(function(response) {
                var id_token = response.data.id_token;
                localStorage.setItem('id_token', id_token);
                refreshPromise = null
                return id_token;
            });
            return refreshPromise
        } else {
            return idToken;
        }
    }];
    $httpProvider.interceptors.push('jwtInterceptor');
})

from angular-jwt.

justechn avatar justechn commented on August 25, 2024

The best thing you can do is refresh your tokens before the expire. That way you will not run into this problem. If you have a 15 min expire, refresh your token at 13 or 14 min.

from angular-jwt.

petejohanson avatar petejohanson commented on August 25, 2024

I've just implemented something as I described in my previous comment, and it seems to work as expected. Multiple "pending" requests get queue'd up if you re-use the promise representing the in-progress refresh, and then clear the saved pending request after the refresh completes.

from angular-jwt.

ajoslin103 avatar ajoslin103 commented on August 25, 2024

that looks good, I've been running into the async problem (I've lots of calls all using the jwt) -- I'd be interested in your working solution if you cared to post it.

from angular-jwt.

GabrielGil avatar GabrielGil commented on August 25, 2024

@petejohanson's solution seems nice to me and works just fine. 💃

from angular-jwt.

ajoslin103 avatar ajoslin103 commented on August 25, 2024

@petejohanson -- could you share your final code?

from angular-jwt.

petejohanson avatar petejohanson commented on August 25, 2024

Unfortunately my final solution is more complicated because of other requirements, and is for work so I can't share here. However, the essence of the working version I implemented is exactly like the sample I posted previously.

You would just need to fill in the actual implementation of your refreshToken function to return a proper promise.

from angular-jwt.

GabrielGil avatar GabrielGil commented on August 25, 2024

Exactly, well, I just got your idea. My implementation differs as well a little. But the essence of your snippet is the essence of the solution. Thank you again!

from angular-jwt.

ajoslin103 avatar ajoslin103 commented on August 25, 2024

Mine didn't work so well -- I'll have to go back and compare it to your direction -- thanks anyway

from angular-jwt.

petejohanson avatar petejohanson commented on August 25, 2024

@ajoslin103 if you want to create a gist of your version and link it here, we can see if we can offer some advise?

from angular-jwt.

GabrielGil avatar GabrielGil commented on August 25, 2024

@ajoslin103 I can't really share my final code, but this is a modified version of the example shown on the README.md of the repo, and the solution suggested by @petejohanson

This example stamps subsequent calls after a token expired, and resumes then to be sent with the new token after the promise has been resolved. (Thus only one call to the refresh endpoint is performed).

angular.module('app', ['angular-jwt'])
.config(function Config($httpProvider, jwtInterceptorProvider) {
  var refreshPromise;
  jwtInterceptorProvider.tokenGetter = ['jwtHelper', '$http', function(jwtHelper, $http) {
    if (refreshPromise) {
      return refreshPromise;
    }
    var idToken = localStorage.getItem('id_token');
    var refreshToken = localStorage.getItem('refresh_token');

    if (jwtHelper.isTokenExpired(idToken)) {
      // This is a promise of a JWT id_token
      refreshPromise = $http({
        url: '/delegation',
        // This makes it so that this request doesn't send the JWT
        skipAuthorization: true,
        method: 'POST',
        data: { 
            grant_type: 'refresh_token',
            refresh_token: refreshToken 
        }
      }).then(function(response) {
        var id_token = response.data.id_token;
        localStorage.setItem('id_token', id_token);
        refreshPromise = null
        return id_token;
      });
      return refreshPromise;
    } else {
      return idToken;
    }
  }];
  $httpProvider.interceptors.push('jwtInterceptor');
})

Note the difference with the example on the main page that we store the $http promise in the variable that is gonna be checked on subsequent tokenGetter calls

I really hope this helps ;)

from angular-jwt.

GabrielGil avatar GabrielGil commented on August 25, 2024

😅

from angular-jwt.

petejohanson avatar petejohanson commented on August 25, 2024

I think @GabrielGil's updates to the README.md should be integrated there, this seems like a common enough need.

from angular-jwt.

GabrielGil avatar GabrielGil commented on August 25, 2024

I've created a pull request after your suggestions guys (#77) :D

from angular-jwt.

dzuluaga avatar dzuluaga commented on August 25, 2024

Thanks @petejohanson. Your solution worked for me. My suggestion is to update all examples with the approach described here. Otherwise, you'll get 429 too many requests. Here are two sources, which require to be updated as they have missing the outer refreshPromise:

https://github.com/auth0/angular-jwt#using-promises-on-the-tokengetter-refresh-token-example
https://auth0.com/blog/2014/10/01/handling-jwts-on-angular-is-finally-easier/

Cheers!

from angular-jwt.

pabloleone avatar pabloleone commented on August 25, 2024

I realized that the backend should return a 200 response code even if token can't be refreshed because the JWT package will loop forever as it isn't expecting a failing request (second parameter of then method). We're using the JWT package for Laravel and it's implementation returns an exception (401) when the token is completely expired and ready to blacklist. Which philosophy is the right one?

from angular-jwt.

stale avatar stale commented on August 25, 2024

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you have not received a response for our team (apologies for the delay) and this is still a blocker, please reply with additional information or just a ping. Thank you for your contribution! 🙇‍♂️

from angular-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.