waiting-for-dev/devise-jwt

Not possible to sign in multiple different users from the same API client?

jbwl opened this issue · 2 comments

jbwl commented

Maybe this is possible already so I don't want to file a bug report.

My use case is to "impersonate" another user from my client (a Vue web app with Axios):

  • First, I log into the Web app as an admin user. The authentication endpoint /users/sign_in returns this admin user's token, which is stored in the web app to make requests (User A).
  • As an admin in this web app, I want to "impersonate" another user (User B). From the viewpoint of the web app, this affords that I have an endpoint in my Rails backend that will authenticate the user (ideally without a password) and return that user's token. Which again is stored by the web app as an "impersonation token".
  • In the web app, I can now choose as which "user" I am talking to the Rails backend. As long as I'm impersonating User B, the web app will send that user's token to the Rails backend and should therefore be scoped to that user's account. When I "stop impersonating", the web app will switch back to User A's token for Backend requests.

From the Backend's point of view (Rails 6 API app with devise-jwt), this should be no different than signing in with two
separate users from the same web app running in the same browser.

This doesn't seem to be possible with Devise-JWT because:

  • When I am signed in as User A to the web app, then of course the "impersonate another sign in" request to Rails will have User A's token, and User B's sign-in credentials in the body.
  • This request seems to be handled by devise-jwt like this: It recognizes the User A's token and authenticates as it should, but it ignores the supplied credentials (username, password) for User B and does no authentication from those supplied credentials.
  • Therefore, sign-in response has only User A's token, but not User B's token, and therefore the web app will not be able to "impersonate" User B (meaning it never receives that user's token to store for further requests).

What I would like to achieve is to have a sign-in endpoint in my app that will first authenticate User A (the admin) from the supplied token, but then also authenticate User B whose credentials (ideally no password, just a username) are supplied in the POST body's data. The sign-in response should bear User B's token instead of User A.

Any tips or pointers how to do this on the backend side with Devise-JWT are welcome!

Hi @jbwl,

This request seems to be handled by devise-jwt like this: It recognizes the User A's token and authenticates as it should, but it ignores the supplied credentials (username, password) for User B and does no authentication from those supplied credentials.

devise is built on top of warden, which uses a cascade of authentication strategies until one of them succeeds. If you manage to put devise's :database_authenticatable strategy before warden-jwt_auth's one, I think your flow should be possible.

Another issue is that maybe your use case would be better achieved with a role system.

jbwl commented

Thank you for this clarification, now I know where to look! And thank you for the great library.