Use of JWT in httpOnly cookie #4632

Responses to the discussion on Github


luwes1y ago

Author

The providers all return an access token. If the signed in user is to make any requests to the provider API (via Strapi) that access token also has to be stored somewhere. Currently there seems no way to get that access token from the user-permissions service.


derrickmehaffy1y ago

Collaborator

@luwes the JWTs are not stored by Strapi, they are generated on the fly and decrypted per request.

While I agree it’s not a good idea to store them in localStorage, there isn’t nothing stopping anyone from using httpOnly cookies.

@lauriejim thoughts on adding something to the docs? Personally I feel that goes beyond the realm of Strapi itself (as it’s not really a problem of strapi) that being said I have been all in favor of storing user session information to prevent hijacking/repeater attacks in which someone takes a JWT and uses it (from say a different IP Address than it was requested for).

To do the above ^^^ would related to my Discussion topic on actual storage of the JWT in something like Redis with a fallback to either memory or the database. #3866

Edit: Side note the JWT is “cleaned” from being passed to any other part of strapi other than the users-permissions plugin.


luwes1y ago

Author

Thanks for your reply. Makes sense mostly. So we as strapi users would need to add extensions/users-permissions/controllers/Auth.js and add a httpOnly cookie there (can only be created by the server) with the JWT token.

To have authorization to the 3rd party API like Twitter, Instagram the gotten OAauth Access Token could be stored in the user DB table or so.

I think the part to store the JWT in Redis, DB, etc. makes less sense. This is needed on the client side right?


derrickmehaffy1y ago

Collaborator

No Redis is server side it would keep a cached state of the user and the token assigned to them/IP Address/ect.

Basically at the point of logout, the client would fire a request and delete that state.

(I’m not entirely familiar with httpOnly cookies, if it’s something that Strapi has to send then it could be an option to add)


luwes1y ago

Author

I don’t see any benefit to storing the JWT on the server in Redis/DB. The JWT is needed on the client to authenticate the user (to “log in”) (for every request). Either in local storage where you pass the JWT as a header Authorization: Bearer in the request from the client OR this is stored in the httpOnly cookie which doesn’t require passing that header all the time, it’s just gotten from that cookie which is available both on client and server.


derrickmehaffy1y ago

Collaborator

It acts as a means of revoking a JWT which isn’t currently possible without forcefully revoking all issued JWTs. When a JWT is created and sent to the client, until it expires it is valid, including if someone steals that JWT and uses it in a “repeater” attack


derrickmehaffy1y ago

Collaborator

Along with the above ^^^ it would also allow for easier support of refresh tokens to reissue a JWT without the user needing to enter in their account information again.


luwes1y ago

Author

@derrickmehaffy I think I get your point but to be sure this will still require a JWT on the client correct? either via local storage or httpOnly cookie.

It could be a good first step to inform users how to add this in Strapi because a httpOnly cookie can only be set on the server. Most resources strongly recommend not using local storage it seems.


derrickmehaffy1y ago

Collaborator

Generally yes both options could exist but in the cases I mentioned even if someone got their hands on the token they wouldn’t be able to do anything.

On the flip side to that there are cases where JWT can still be secure such as with mobile apps keeping it locked inside an app sandbox or similar applications such as desktop apps or server scripts ect.

Benefit of a headless CMS is not all content may come from the browser :slight_smile: So we don’t want to lock out people who can’t use cookies


derrickmehaffy1y ago

Collaborator

I do agree with your solution though it would be worth added for better security


keymandll1y ago

This was not mentioned yet as far as I see, it may be under one of the links posted, but:

Please note if you passed JWT as an HttpOnly cookie you would also have to implement CSRF protection.

What I ended up implementing in one of my projects is .e.g.:

  1. All authenticated sessions are issued a CSRF token (CSRF tokens are OK to be stored in local storage)
  2. API allows JWT to be passed in either as a cookie (httpOnly) or in Auth header
  3. Only if JWT is received via cookie the API requires a valid CSRF token as well
  4. (Consider) Attribute within JWT to specify if it was issued to a user or an app. If token was issued to user, expect JWT as cookie, otherwise expect JWT in header.

Also:

  1. Once you have an XSS the outcome of an attack can be a lot more than stealing a JWT token.
  2. Caching JWTs in Redis, etc. is generally a bad idea. The nice thing about a JWT is that it’s issued to the client and the server does not have to keep a copy to be able to authenticate a client. If you put user JWTs in another service on “server-side” you have to make sure that service is really really secure as if that service gets compromised, all cached JWTs will be exposed to the attacker.

yhrchan344d ago

Sorry I was also trying to figure out how to use httpCookie via Strapi as I don’t want to store the returned JWT to local storage on the client side. How would I do this? Is this a functionality which exist out of the box from Strapi? I couldn’t find such information from the documentations. Any help would be greatly appreciated!

Thanks!


curiousercreative261d ago

  1. Caching JWTs in Redis, etc. is generally a bad idea. The nice thing about a JWT is that it’s issued to the client and the server does not have to keep a copy to be able to authenticate a client. If you put user JWTs in another service on “server-side” you have to make sure that service is really really secure as if that service gets compromised, all cached JWTs will be exposed to the attacker.

@keymandll can you reference anything for the “generally a bad idea” claim? Your prescription to have the token store be secure is valid of course, but it’d seem that Redis is no harder to secure for most applications and if you want token revocation, you’ll need to store them. SO question " Should I store JWT tokens in Redis"