I am currently working on a public API that uses JSON Web Tokens (JWTs) for authentication and access control. I am hoping to secure this API against cheats and exploits and hope you guys can help clarify a few points for me.
Q1: Do I understand correctly that anyone in possession of a valid JWT has access to all the permissions expressed in the JWT?
I understand that a JWT is just a base64-encoded header, payload, and signature and it’s up to one’s server to decide how to grant access or not, but are there any best practices or standard approaches to limiting the circumstances under which a JWT might be used? I see that exp (i.e., Expiration) and nbf (not before) are standard fields which limit the time span in which a JWT is valid. I’ve so far seen little information about how these typically get used.
Given that a JWT seems to grant access permission without any further authentication, it seems very sensitive.
Q2: What are best practices for making sure it stays secret?
Clearly, the JWT should only be delivered over a secure (i.e., HTTPS) connection to prevent some packet sniffer from snooping it while it’s in transit. If the JWT is being sent to some server for API requests via curl, we’d clearly want to avoid storing it in some file in the web root, or exposing it through sloppy coding. What about if we are using the JWT in some single-page app? Should we be concerned about Cross-site scripting (XSS) or cross-frame scripting (XFS) or CORS considerations? Seems like one should probably set x-frame-options headers. Should we also be concerned about setting content-type headers to prevent circumvention of same-origin policies?
Q3: Should we be concerned about CSRF attacks?
I’m aware how easy it is for a hacker to construct a form that sends a POST request to some other website in order to do bad things, and I understand that one can protect against this sort of thing with a CSRF token. Do we have CSRF considerations with JWTs? I expect we’ll configure our API such that it looks for the JWT in a request header:
Authorization: Bearer <JWT-goes-here>
That being the case, it seems like an attacker simply constructing a POST form would not work. I’m having difficulty imagining how an attacker might sniff out a JWT that’s in some JS var in my page, or perhaps stored in localStorage, but I suppose it could happen. Must one be on guard against CSRF attacks when using JWTs? This page, which appears to be the authoritative JWT site, says:
If the token is sent in the Authorization header, Cross-Origin Resource Sharing (CORS) won't be an issue as it doesn't use cookies.
I’m not sure I buy that entirely. If anyone has insights, I’d love to hear them.
I’ve been reading the OWASP site for tips on preventing XSS and XFS, but I’m still wondering if we might need to take extra steps to secure this API against JWT abuse. Any input would be much appreciated.