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

No Authorization Header on registrations#update #21

Closed
timscott opened this issue Jun 25, 2017 · 4 comments
Closed

No Authorization Header on registrations#update #21

timscott opened this issue Jun 25, 2017 · 4 comments
Assignees
Labels

Comments

@timscott
Copy link

A JWT is meant to hold information about the user. So when a a user is updated via Devise registrations#update, the token is likely to fall into an invalid state on the client. Hence it seems expected to return an updated token when the registration is updated. Otherwise the user would need to log in after the registration is updated, which is not a natural user experience.

Does this make sense, and is it something devise-jwt can support? If not, is there an idiomatic way to handle this?

@waiting-for-dev
Copy link
Owner

Hi @timscott .

Your reasoning makes sense. However, personally I'm against encoding information which is subject to change into the JWT. With JWT technology, there is nothing the server can do to revoke a single token, so if the information on it becomes obsolete there is no way to be sure that the client won't use it again fraudulently.

I added a thin revocation layer on top of this library. But this revocation layer is useful when the client wants to revoke a token, usually on sign out. If the client doesn't send the JWT token you (as application developer) want to become expired to the server, there is nothing the server can do. So, in your scenario, if you want to be sure that the staled token is not going to be reused, you should configure your registrations#update path as both a revocation path and a dispatch path.

As I generally consider it a bad practice, I'm not going to include it in the library default behavior. However, if you still want to implement it, it should be possible configuring registrations#update path as both dispatch_requests and revocation_requests (look at the Configuration reference section in the Readme).

@waiting-for-dev
Copy link
Owner

waiting-for-dev commented Jun 26, 2017

However, if you need to differentiate a success response from a response to some error in the form, as I guess it would be usually the case, you would need to do more handwork.

From the controller, you should call the revocation strategy (whether a blacklist model or the user model itself) revoke_jwt method if there are no errors, along with adding a new token to the response using underlying warden-jwt_auth library:

Warden::JWTAuth.UserEncoder.new.call(user, scope)

Let me know if you need more guiding with this.

@timscott
Copy link
Author

timscott commented Jun 26, 2017

Thanks for the rapid reply! I added this to my config:

jwt.dispatch_requests = [
  ['PATCH', %r{^/auth$}]
]

Now when I make call to PATCH /auth (which is the route for registrations#update) I am getting back an updated token. I get the token in the case of a valid request (204) or a bad request (422). I understand that I should only update the token on the client in the case of success.

So this seems to work fine for me with no other changes on the server. Is there something else I need to do? (I guess I did not quite understand your advice about the controller.)

UPDATE: I think I understand now. If I want to treat updating a registration as sign out and back in, then it's not enough to just configure that route as also a revocation_requests, since I do not want to revoke on a bad request. Did I get it right now?

@waiting-for-dev
Copy link
Owner

waiting-for-dev commented Jun 27, 2017

UPDATE: I think I understand now. If I want to treat updating a registration as sign out and back in, then it's not enough to just configure that route as also a revocation_requests, since I do not want to revoke on a bad request. Did I get it right now?

Correct. You will have to revoke it manually from the controller code. But it is not difficult:

token = request.headers['Authorization']
payload = Warden::JWTAuth::TokenDecoder.new.call(token)
MyRevocationStrategy.revoke_jwt(payload, current_user)

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

No branches or pull requests

2 participants