ueberauth/guardian

VerifyHeader but from two cookies

root-talis opened this issue · 5 comments

Recently in a personal project of mine I've been diving into modern approaches for authentication for browser single-page applications. Many sources suggest that using JWT for this purpose is a valid approach, however, storing it in a location that is available to JS is unacceptable, for it can be stolen and used to impersonate the user.

A common techinque I've encountered is splitting the token into two cookies:

  1. header and payload in a short-lived cookie that is available to JS (so that the SPA can decode it and use the information from the token, like user ID and roles);
  2. secret in a long-lived HttpOnly SameSite cookie (so that JS doesn't have access to the part of the token it cannot effectively use anyway).

Here's an article describing this approach (they use the term signature instead of secret):
https://medium.com/lightrail/getting-token-authentication-right-in-a-stateless-single-page-application-57d0c6474e3

I have made a simple VerifyHeader-based implementation of a plug to fetch the token from those two cookies. If you are interested, I can write proper tests and make a pull-request.

Disclaimer: I am not a security expert, and despite having plenty of experience in enterprise development, I'm new to Elixir.

While I understand the above strategy, I have hard to time to see the benefit over the current aproch where the full token is stored in a secure httpOnly same-site cookie. What is the actally benefit of having the token split in two?

The benefit is that the "header.payload" part is accessible from JS, and thus the frontend can use any information which is stored in it (for example, to judge about the user's permissions), while the secret part still remains hidden from JS.

I can see that, but for me, it still seems quite a narrow use case that could be solved by just sending the permissions together with the jwt, but maybe I am wrong, what does rest of @ueberauth/developers think?

I don't think it is a good idea to keep adding more and more info to JWT to store any random information people want, especially from the clients.

Being said, I am not opposed to it either, as long as the implementation doesn't affect drastically the internals of the existing one, would propose to have another module if that is the case.

PR welcome

yordis commented

Often, the use cases come from misusing JWT as an authorization token (not an authentication/identifier token) and misusing roles as permissions checks or adding too many claims to the JWT to avoid an endpoint that would return such information.

Here is a link to one of the most mature write-ups: https://hackernoon.com/you-probably-dont-need-oauth2openid-connect-heres-why.

If you need such a use case, I would strongly encourage you to think about the situation and make sure you are making the right decision.


I am going to close this for. I am not saying I am right. I believe the use case presented in the blog post should be avoided.

Please take the lead and open a pull request if you feel strongly about it.