I am using JWT for my Node+Express API's route protection; I normally store the user's profile information in the jwt token, unless is granular PII. But I want to know what the best practice is for this.
I have the following user schema (mongoose):
USER {
_id: ObjectID,
userName: string,
img: string,
email: string,
role: string
}
I probably don't want to throw the img in the JWT payload to avoid unwanted hashing costs, but what other information/properties can I throw in the JWT payload?
-- Is there a performance limiting factor to larger JWT's?
I have seen some people only using the _id and username properties, but I would like to have a standard that I stick to to keep everything nice and uniform.
Thanks! :)
Anatomy of a JWT Figure 1 shows that a JWT consists of three parts: a header, payload, and signature. The header typically consists of two parts: the type of the token, which is JWT, and the algorithm that is used, such as HMAC SHA256 or RSA SHA256. It is Base64Url encoded to form the first part of the JWT.
In these scenarios, the storage dictates the maximum JWT length. For example, the typical storage limit for cookies in a browser is typically 4096 bytes, including the name. The limit on HTTP headers varies widely based on software components, but 8192 bytes seems to be a common value.
The JWK RFC does specify minimum lengths for the various algorithms. The minimum secret length for HMAC: A key of the same size as the hash output (for instance, 256 bits for “HS256”) or larger MUST be used with this algorithm.
You should put just enough information in your JWT token to authenticate your user without needing to make additional database requests. That's the whole point of the payload - so that authentication can be distributed. If you need to make database requests to authenticate every API call then you have not achieved distribution because you will still be centralizing your authentication process at the database.
However, do note that everything you put into your JWT tokens are public. Anyone can do a base64 decode on the token to extract the payload. Therefore I would suggest not including your user's email address in the payload if you don't use it often (for every API call). Malicious scripts may somehow get access to the token and harvest the email addresses (which does have value and can be sold to "email marketers"). The user's ID should be enough to identify the user.
If your UI needs to display the user's name then you can also include the name but personally I'd delegate that to a profile API call (I normally implement a /myself
endpoint for this).
I'd also include the user's role in the payload to avoid needing to query the database to check if the user has permission to make an API call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With