Skip to content

Not returning headers on error #1002

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

Closed
nicholasshirley opened this issue Oct 30, 2017 · 5 comments
Closed

Not returning headers on error #1002

nicholasshirley opened this issue Oct 30, 2017 · 5 comments

Comments

@nicholasshirley
Copy link

nicholasshirley commented Oct 30, 2017

I working on a sample project that is using Vue/devise_token_auth/Rails API and I'm noticing that there are certain conditions where it's possible to send invalid data and get an error return which doesn't return headers (though they have been changed in the DB). In each case, the next request will fail because the user is sending old headers.

This is the repo I'm working with.

These are two situations that I can consistently replicate the behavior:

Calls to /validate_token eventually return 304 without the headers. If I look at the rails logs though, I can see that the token was updated. Interestingly, the logs say that it responded with 200, but Chrome disagrees.

Sending incorrect data to /password will return 422 without headers (again, changed in the DB). This works for sending the wrong current password, sending no current password or mis-matched new passwords.

  • Version: 0.1.42
  • Devise Version: 4.3.0

The repo has a full log of the changes from each generator, but these are the most relevant I think:

  • The Api is running under an api namespace
  • Omniauthable and confirmable are removed, but other than that everything is as it comes out of the generator
  • password is required to change the password
@zachfeldman
Copy link
Contributor

Hey @nicholasshirley, looking forward to seeing your Vue integration.

I know a lot of people run Devise Token Auth with change_headers_on_each_request set to false. Are you able to make your integration work with this setup?

Obviously it's not the best long-term solution, but it may get the Vue integration up and running, at least.

@nicholasshirley
Copy link
Author

I had another project that we ended up doing this to get it working. Not changing headers on each request would certainly get the error rate down for the Vue example. If the headers don't change on each request then the only issue I could think of would be cases where the user might have a valid token from a previous session (so they would get user information returned for the first /validate_token request when the component is mounted), but don't get new headers. This will display the app as if they are logged in, but their next action will return 401 so they will have to log in again. I don't know how often that would occur, most of the errors I have are not on the first page load, but after refreshing. I will update the example for this case and see how it does.

I would be curious though if someone else can replicate this behavior. Having the Rails log and Chrome network tag disagree about what status code was sent seems weird, as does devise_token_auth occasionally not sending headers. In the sample, there's nothing changing between requests, but the response is different which doesn't seem like it should be the case, but maybe this is my not understanding something about how the Gem works or how Rack/Rails is dealing with requests.

@zachfeldman
Copy link
Contributor

"If the headers don't change on each request then the only issue I could think of would be cases where the user might have a valid token from a previous session (so they would get user information returned for the first /validate_token request when the component is mounted), but don't get new headers. This will display the app as if they are logged in, but their next action will return 401 so they will have to log in again."

Yeah, we actually check for a 401 on our app before we render any components that depend on the state of people being logged in or not.

I'd imagine the behavior you're describing in your last paragraph is happening....but could you maybe give some examples of requests/response parameters? Might help us get to the bottom of the issue a bit better.

@nicholasshirley
Copy link
Author

For the /validate_token endpoint this is what axios is sending:

axios.get(VALIDATE_URL)
      .then((response) => {
        Store.login(response.data.data);
      })

headers are saved and sent from local storage each request. The only change is the updated headers. Send it several times (and possibly with enough speed) and the server will update the headers, but fail to send new ones back. I can see in the logs that the token is updated in the DB, but never sent in Chrome's network tab.

The params for the /password endpoint are correctly formatted data (e.g. if you pass good params it will update the password and return headers), but if you pass the wrong current password, no current password or mis-matched new passwords it will update the token and fail to send it back.

I have turned off token changes in other commits, but this branch has the repo at the state where tokens were still changing. Basically login and hit refresh on the main page until you get an error or try to update the password with wrong info. Actually, after I set up that branch I was able to trip it a third way by having 2 closely spaced requests to different endpoints. The second request updates the token in the DB, but they are not sent back as headers.

@nicholasshirley
Copy link
Author

Well, as so often happens, I think the problem this time was between the keyboard and the chair. The axios interceptors weren't savings new headers on error so of course the next request after any error had stale headers.

Closing. Thanks for the support!

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

2 participants