Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh token question #8

Closed
purepear opened this issue Aug 6, 2016 · 6 comments
Closed

Refresh token question #8

purepear opened this issue Aug 6, 2016 · 6 comments

Comments

@purepear
Copy link

purepear commented Aug 6, 2016

Not sure how this refresh token is supposed to work. When is _refreshToken called? And even if it's called at some point it doesn't set anything after http request to tokenUrl. Shouldn't it set the token received by the request.

function _refreshToken () {
        var _this = this;

        if (_getToken.call(this) && this.getOption('tokenType') === 'jwt') {
            _http.call(this, {
                url: this.getOption('tokenUrl'),
                method: 'get',
                success: () => {
                    var tokenJSON = _decodeToken(_getToken.call(_this)),
                        expireTime = _getTokenExpirationDate(tokenJSON).valueOf(),
                        nowTime = new Date().valueOf(),
                        offsetTime = this.getOption('tokenTimeoutOffset'),
                        timeout = expireTime - nowTime - offsetTime;

                    clearTimeout(_tokenRefreshTimeout);

                    _tokenRefreshTimeout = setTimeout(function () {
                        _refreshToken.call(_this);
                    }, timeout);
                }
            });   
        }
    }
@purepear
Copy link
Author

purepear commented Aug 6, 2016

Also.. not sure when _refreshToken decides to kick in but after some idle time the page started sending tokenUrl url requests non stop. Turns out if you set token expiration date to more than ~24 days... the representation in milliseconds is bigger than the 32bit integer that setTimeout expects .. so it fires as if timeout is 0 milliseconds. Can be fixed by sth like timeout = Math.min(expireTime - nowTime - offsetTime, 2147483647)

@fer-ri
Copy link
Contributor

fer-ri commented Aug 9, 2016

After we logged in then refresh page, then this package automatically trying to fetch and calling _refreshToken if this.loaded === false on line https://github.com/websanova/vue-jwt-auth/blob/master/vue-jwt-auth.js#L427

The problem is..this process is async, so _refreshToken and _fetch will called parallel.

This is the summary

  • User logged in, save token A in local storage
  • User refresh page
  • Package always run fetch on initial load
  • Since this is initial load, then this.loaded will false, so package will run _refreshToken with token A and in parallel call _fetch with token A too
  • _refreshToken make token A as blacklist (on server side) and get new token B
  • _fetch then will has unauthorized access because token A already blacklisted
  • _refreshToken didn't update new token B in local storage

I think we need to call _refreshToken as series ..

Thanks

@websanova
Copy link
Owner

Will have to look into it again. Will update the docs with the workflow/reasoning soon. There is also a related issue with expired tokens not being removed. So it tries to use it giving an auth error on load which is not necessary.

Will look into it next week, swamped with some client projects at the moment.

@fer-ri
Copy link
Contributor

fer-ri commented Aug 10, 2016

I did some changes and its work for replacing old token when reload page

  function _refreshToken (cb) {
    cb = cb || function () {}

    let _this = this

    if (_getToken.call(this) && this.getOption('tokenType') === 'jwt') {
      _http.call(this, {
        url: this.getOption('tokenUrl'),
        method: 'get',
        success: (res) => {
          _setToken.call(this, res.json()[this.getOption('tokenVar')])

          let tokenJSON = _decodeToken(_getToken.call(_this))
          let expireTime = _getTokenExpirationDate(tokenJSON).valueOf()
          let nowTime = new Date().valueOf()
          let offsetTime = this.getOption('tokenTimeoutOffset')
          let timeout = expireTime - nowTime - offsetTime

          clearTimeout(_tokenRefreshTimeout)

          _tokenRefreshTimeout = setTimeout(function () {
            _refreshToken.call(_this)
          }, timeout)

          return cb()
        },
        error: (res) => {
          return cb()
        }
      })
    } else {
      return cb()
    }
  }

...

    fetch (cb) {
        cb = cb || function () {}

        if (!this.loaded) {
          _refreshToken.call(this, () => {
            this.setLoadedAsTrue(cb)
          })
        } else {
          this.setLoadedAsTrue(cb)
        }
      },

      setLoadedAsTrue (cb) {
        if (this.authenticated === null && _getToken.call(this)) {
          if (!document.cookie.match(/rememberMe/)) {
            _removeToken.call(this)

            this.loaded = true

            return cb()
          }

          this.authenticated = false

          _fetch.call(this, cb)
        } else {
          this.loaded = true

          return cb()
        }
      },

@FerchoCarcho
Copy link

FerchoCarcho commented Aug 29, 2016

Hello @ghprod , I think your solution isnt working when you want to /register /login , refresh the page because as the install function is being called on every refresh, function _fetch isnt being triggered so no user is set. Please check your response.
_fetch.call(this, cb)

@websanova
Copy link
Owner

This has now been reworked a bit in the new v1.0.x-dev version.

However by default it will still do a refresh on each init. If you want to disable it you must override the expiredToken method.

expiredToken: function () { return false; }

If you set the token in the header or via param during the user (or any other) request it will automatically get sniffed out and set. So you could put it wherever you like if you wanna go some other route.

Or you could also call $auth.refresh() manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants