1. Introduction to JWT
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way to securely transmit information as JSON objects between parties. This information can be verified and trusted through digital signatures. The JWT can be signed with a secret (using the HMAC algorithm) or with a public/private key pair using RSA.
While JWTs can be encrypted to provide confidentiality between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within them, while encrypted tokens hide claims from other parties. When a token is signed with a public/private key pair, the signature also proves that only the party holding the private key is the signing party.
Let's explain some concepts further:
- Compact :
Due to their small size, JWTs can be sent via URLs, POST parameters or within HTTP headers. Plus, smaller size means faster transfer speeds. - Self-contained :
The payload (Playload) contains all required information about the user, avoiding multiple queries to the database.
2. JWT applicable scenarios
- Authentication :
This is the most common case of using JWT. Once the user is logged in, each subsequent request will contain the JWT, allowing the user to access the routes, services and resources allowed by that token. Single sign-on is a feature that is widely used today with JWT because it has little overhead and can easily be used across different domains. - Information Exchange :
JSON Web Tokens are a great way to securely transfer information between parties. Because JWTs can be signed: e.g. using a public/private key pair, it is certain that the sender is who they claim to be. Additionally, since the signature is calculated using the header and payload, you can also verify that the content has not been tampered with.
3. JWT structure
In compact form, a JWT consists of three parts separated by dots (.), which are:
- Header
- Payload
- Signature
The JWT structure usually looks like this:
xxxxx.yyyyy.zzzzz
Let's introduce these three parts separately:
Header
Header usually consists of two parts: the type of token, that is JWT. and commonly used hashing algorithms like HMAC SHA256 or RSA.
E.g:
{
"alg": "HS256",
"typ": "JWT"
}
The JSON of the Header part is Base64Url encoded to form the first part of the JWT.
Payload
The content of the statement is placed here. It can be said that it is the place to store the communication information. There are 3 kinds of declarations (Claims) in the definition:
Registered claims :
These are a set of pre-defined claims that are not mandatory but recommended to provide a useful, interoperable set of claims. Some of them are:iss
(issuer),exp
(expiration time),sub
(subject),aud
(audience), etc. #Registered Claim Names#- Public claims :
These can be freely defined by the person using the JWT. But to avoid conflicts, they should be defined in the IANA JSON Web Token Registry, or as a URI containing a collision-proof namespace. Private claims :
These are custom claims created in order to share information between parties who agree to use them but have neither registered nor public claims.
An example of Playload is as follows:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
The JSON of the Playload part is Base64Url encoded to form the second part of the JWT.
Notice:
Note that for signed tokens, this information, albeit tamper-protected, is readable by anyone. Do not put secret information in the payload or header elements of the JWT unless encrypted. This is also the reason why many articles argue about the security of jwt, do not replace the server-side session state mechanism with JWT. Read this article for details: Stop Using Jwt For Sessions .
Signature
The third part of signature is used to verify the identity of the sender and is formed by the encryption of the first two parts.
To create the signed part, you must take the encoded header, encode the payload, the secret key, the algorithm specified in the header and sign it.
For example, if you wanted to use the HMAC SHA256 algorithm, the signature would be created as follows:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
3. JWT practice
The output of JWT is three dot-separated Base64-URL strings that can be passed easily in HTML and HTTP environments, while being more compact compared to XML-based standards such as SAML.
The following JWT example has the previous header and payload encoding and is signed with a secret key.
We can use the jwt.io debugger to decode, validate and generate JWTs:
4. How JWT works
In authentication, when the user successfully logs in with their credentials, a JSON Web Token will be returned and must be saved locally (usually in local storage, but cookies can also be used), instead of creating a session server and Return a cookie.
Regarding the way of storing the token (Token), security factors must be considered.
Reference: #Where to Store Tokens#
Whenever a user wants to access a protected route or resource, the user agent should send the JWT using the bearer scheme, usually a Authorization
field in the request header, using the Bearer
schema:
Authorization: Bearer <token>
This is a stateless authentication mechanism because user state is never kept in server memory. The server-protected route will check for a valid JWT in the Authorization header and, if present, allow the user to access the protected resource. Since the JWT is self-contained, all the necessary information is there, reducing the need to query the database multiple times.
This allows us to fully rely on stateless data APIs and even make requests to downstream services. It doesn't matter which domains are serving the API, so there won't be an issue with Cross-Origin Resource Sharing (CORS) since it doesn't use cookies.
Notice:
Note that with a signed token, all the information contained in the token is exposed to the user or other parties, even if they cannot change it. In JWT, no sensitive data, such as passwords, should be added to the Playload. If you put the user's password in the JWT, then a malicious third party can quickly know your password through Base64 decoding.
5. Frequently Asked Questions
① Is JWT safe?
The Base64 encoding method is reversible, that is, the content of the Token issued after encoding can be parsed. In general, we don't recommend putting sensitive information, such as a user's password, in the payload.
② Can the content of JWT Payload be forged?
One of the components of the JWT is the Signature, which prevents the content of the payload from being pushed back and modified by the Base64 reversible method. Because Signature is composed of Base64 through Header and Payload.
③ If my cookie is stolen, doesn't it mean that a third party can do CSRF attack?
Yes, the loss of the cookie means that the identity can be forged. Therefore, the official recommended way to use it is to store it in LocalStorage and send it in the request header.
④ Space and length issues?
JWT Tokens are usually not too short in length, especially Stateless JWT Tokens. All data is compiled in the Token, which will soon exceed the size of the cookie (4K) or the URL length limit.
⑤ Token invalidation problem?
-
- After the Stateless JWT Token is issued, the token cannot be invalidated through the server side, and it must wait until the expiration time expires before it becomes invalid.
-
- Assuming that the Token is intercepted during this period, or the authorization scope is modified due to the difference in the authority management identity, it cannot prevent the issued Token from invalidating and require the user to request a new Token again.
6. JWT usage advice
- Do not store sensitive information in Token.
- Do not set the time limit in Payload to
exp
be too long. - Enable
Only Http
XSS attack prevention. - If worried about replay attacks (replay attacks) can increase
jti
(JWT ID),exp
(valid time) Claim. - Add a blacklist mechanism to the application layer of your application, and block it when necessary (this is a manual defense against the token being stolen by a third party).
[1] Stop using JWT for sessions:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
[3] Use JWT The Right Way!:
https://stormpath.com/blog/jwt-the-right-way
[2] JSON Web Token 维基百科:
https://en.wikipedia.org/wiki/JSON_Web_Token