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

Reloading the app causes 401 Unauthorised on first api call after token is validated #481

Open
2 of 9 tasks
rmcsharry opened this issue Oct 21, 2018 · 9 comments
Open
2 of 9 tasks

Comments

@rmcsharry
Copy link

rmcsharry commented Oct 21, 2018

I'm submitting a...

  • [x ] Regression (a behavior that used to work and stopped working in a new release)
  • [x ] Bug report

Current behavior

If an existing and logged in user:

  1. the user reloads the app using browser refresh,
  2. then the token is validated correctly,
  3. but the next call to the API fails as 401 Unauthorized.
  4. all following calls succeed

Expected behavior

First request after reloading the app (ie. browser refresh) should not result in 401.

Environment

Angular-Token version: 6.0.3 & 6.0.4
Angular version: 6.1.7
Rails 5.1.6
devise_token_auth 0.2.0
Bundler

  • Angular CLI (Webpack)

Browser:

  • Chrome (desktop) version XX
  • Chrome (Android) version XX
  • Chrome (iOS) version XX
  • Firefox version XX
  • Safari (desktop) version XX
  • Safari (iOS) version XX
  • IE version XX
  • Edge version XX

Other
After the validate_token is called and a new token is sent back by the API, that token is written to localstorage. But the next api call (to get data) does not use it, it is still using the previous token.

The Rails api throws the error "Filter chain halted as authenticate_user! redirected".

The next api request succeeds.

What is also strange is that if I add this test method to see what happens in the Rails application_controller, I get the output shown by "->":

  before_action :test
  respond_to :json
  include Devise::Controllers::Helpers
  include DeviseTokenAuth::Concerns::SetUserByToken
  
  def test
    puts '****'
    puts request.env["HTTP_ACCESS_TOKEN"] -> shows the token (ie the old one)
    puts request.env["access-token"] -> shows nothing
    authenticate_user!
  end
@rmcsharry
Copy link
Author

rmcsharry commented Oct 21, 2018

One (awful) workaround I tried is that on the component that is reloaded I added a timer to delay calling
the service that gets the data for that component.

I tested this and it works, but obviously it is impractical to add this to 50+ components.

It seems the data request to the API is being intercepted to add the headers, but this is happening before the token is updated in localstorage.

Since previous versions did not have interceptors (the api calls were wrapped directly by angular2-token), so you were always 100% certain of injecting the latest token. Not anymore it seems :(

@rmcsharry
Copy link
Author

rmcsharry commented Oct 21, 2018

Possible solution:

I think that before line 20 of the interceptor we need to check if validate_token call has finished and only get token from storage after it has completed.

I am not entirely sure how to achieve that - somehow the interceptor needs to only allow a request if there are no current validate_token calls in-flight.

@rmcsharry
Copy link
Author

rmcsharry commented Oct 21, 2018

It seems this is a common problem, some suggested solutions are here.

I'd like to update the library to fix this bug...but not sure of time/skill required, I might have a go next week.

In the meantime, the quickest/easiest workaround without updating the library is to add retry(1) - or more than 1 retry, up to you - to every http call
eg:

    return this.http.get(this.proposalsUrl, {params: params}).pipe(
      map((response: HttpResponse<TYPE>) => response), retry(2),
      catchError((response: HttpErrorResponse) => this.apiError.handleError(response))
    );

@rmcsharry
Copy link
Author

The retry only works sometimes 👎

It causes some requests to get cancelled, which then causes token invalidation problem which again results in a 401 unauthorized. So this issue is basically related to this one.

So now I'm not sure if the fix should be done in this library or the devise_token_auth gem :(

@SimonBrazell
Copy link

@rmcsharry did you ever find a solution to this? I believe I'm experiencing it now myself, might have to find another solution...

@crazybob9
Copy link

I have the same issue, has anyone found a way to fix it?

@rmcsharry
Copy link
Author

@SimonBrazell No, I never found a solution, my app still does this 👎

@SimonBrazell
Copy link

All good @rmcsharry I found out I was actually encountering a different issue of my own creation.

I was setting apiBase programatically based on a value stored in local storage which wasn't available before the first API call, so the API was correctly responding with a 401 as the token wasn't present in the default tenant (multi-tenant app) forcing sign out and the user to login again.

Once I fixed this all seems to be working fine, although perhaps I'm just yet to encounter your issue...

@ldsk-trifork
Copy link

Bump.

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