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

Always Set Headers in Batch Mode #702

Closed
codez opened this issue Aug 15, 2016 · 10 comments
Closed

Always Set Headers in Batch Mode #702

codez opened this issue Aug 15, 2016 · 10 comments

Comments

@codez
Copy link
Contributor

codez commented Aug 15, 2016

The response headers are only set if we are not in batch request:

https://github.com/lynndylanhurley/devise_token_auth/blob/master/app/controllers/devise_token_auth/concerns/set_user_by_token.rb#L121

This causes issues with Rails' Etag support and XHR Requests: If there are no token_auth headers and Rails returns a 304 Not Modified, the browser (Chrome) will use a cached response, including all headers of the cached response (access-token, client, ...). There is no way in the client to distinguish these cached headers from server-set ones. Eventually, a cached client id is stored and used in the subsequent request, resulting in a 401.

I moved the linked line (121) after the if-block, causing the headers always to be set, then everything worked as expected.

@booleanbetrayal
Copy link
Collaborator

@codez - would you mind putting a PR together for this?

cc: @lynndylanhurley

@lynndylanhurley
Copy link
Owner

Not sure if this helps, but you can append ?unbatch=true to the token validation request to break out of a batch request.

@lynndylanhurley
Copy link
Owner

Also there is a reason we can't set the auth header with each batched request. Sometimes requests are returned out of order, and in those cases we don't want to persist invalidated tokens on the client.

@codez
Copy link
Contributor Author

codez commented Aug 16, 2016

It seems to be a Chrome-only problem. Only if a header is missing in a 304 response, Chrome uses the cached header. If the header is set, it will be used.

The work around seems to be to send empty but existing headers in this case, which may be handled by the client accordingly. This would respect @lynndylanhurley's point.

@steveclarkin
Copy link

steveclarkin commented Aug 30, 2016

We ran into this exact issue today when we switched from a self-signed HTTPS cert (using during testing) to a proper CA signed cert on Heroku. While using a self-signed cert, Heroku doesn't seem to enable caching and never sends 304's. As soon as we installed a proper CA signed cert, we started getting 304's, which exposed this issue.

Seeing the issue in both Chrome and Safari.

@booleanbetrayal
Copy link
Collaborator

Has anyone here had a chance to test #703 in conjunction with ng-token-auth and j-toker, yet? I have been swamped.

@lynndylanhurley
Copy link
Owner

I've also been swamped. I'll take a look ASAP, but I can't give an ETA.

@steveclarkin
Copy link

steveclarkin commented Sep 11, 2016

Just as a workaround until this is tested/fixed, adding the following to a before_filter in the ApplicationController appears to fix the issue (we're using an Ember frontend with a custom ESA authenticator/authorizer).

class ApplicationController < ActionController::API
    include DeviseTokenAuth::Concerns::SetUserByToken

    before_filter :set_response_headers

        ...

    def set_response_headers
        # TODO: Remove this once the following issue is fixed in DTA
        # https://github.com/lynndylanhurley/devise_token_auth/issues/702
        # response.headers["Cache-Control"] = "no-cache, no-store"
        if user_signed_in? and response.headers[DeviseTokenAuth.headers_names[:"access-token"]].nil?
            auth_header = {}
            auth_header[DeviseTokenAuth.headers_names[:"access-token"]] = ' '
            auth_header[DeviseTokenAuth.headers_names[:"expiry"]] = ' '
            response.headers.merge!(auth_header)
        end
    end

@neontuna
Copy link

neontuna commented Nov 8, 2016

@steveclarkin just wanted to thank you for the workaround here. I'm developing a frontend using VueJS and the vue-auth plugin and this did the trick after several hours of pulling my hair out trying to figure out why I kept getting my token bounced.

@andoq
Copy link

andoq commented Apr 20, 2017

I think you also need to set the auth_header of client to return ' '. The client header will change if any request is made without passing in a client, such as the case where the client has logged out and logged back in, and then hits a url that has a 304.

I've been struggling to figure this out for a week, and the workaround of setting the headers to ' ' works. I'm not using jtoker, I'm in react, and so am handling the auth headers in my own code, and had to update my client code to handle this.

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

6 participants