- JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).
- In this article we will see how we can create and sign a JWT token with the RS256 algorithm. This function is complementary to the validate function I posted some time ago. Here is the Sign(.) function that can create a RS256 signed JWT token. It makes use of the BouncyCastle library. It is available as a NuGet package with version 1.8.1.
We create a TokenHandler which is a.NET Core inbuilt class for handling JWT Tokens, we pass it our token as well as our “expected” issuer, audience and our security key and call validate. This validates that the issuer and audience are what we expect, and that the token is signed with the correct key.
I challenged myself during last weeks to implement an authentication on a freshly created API. After digging around, I found that one of the best solution would be JSON Web Tokens. As understanding a concept passes by experimenting it, here is a post describing how to forge such a token in JavaScript.
What is JSON Web Token (JWT)?
JSON Web Token (JWT) is an easy way to secure an API. When a user authenticates first on a server, using for instance a standard login form, the server creates a token. This token includes some personal data, such as username or email address. Then, this token is signed server-side (to prevent token integrity), and sent back to the user. Within each next request, user sends the token to establish emitter identity.
JSON Web Token is composed of three main parts:
- Header: normalized structure specifying how token is signed (generally using HMAC SHA-256 algorithm)
- Free set of claims embedding whatever you want: username, email, roles, expiration date, etc.
- Signature ensuring data integrity
Creating a JSON Web Token in JavaScript
JSON Web Tokens may be resumed by the following equations:
Base64 URL encoding
Note I wrote base64url
, not base64
. There is indeed two small differences between these two encodings:
- There is no
=
padding at the end, +
and/
characters are replaced by-
and_
respectively.
Implementing such a function can be achieved in JavaScript:
I use CryptoJS library to achieve the standard base64
encoding. This is a useful library whenever you want to assume some cryptographic, hashing or encoding tasks. This is perfectly the case, with the incoming HMAC signature.
To make this function work, you have to specify source as an array of UTF-8 bytes. It can easily be achieved using another utility function of CryptoJS: Utf8.parse
.
This extra call is not included into the base64url
function for signature commodity. But you are going to notice it later.
Creating our unsigned token
We can now encode our header and claims. Header is normalized, and contains two alg
and typ
fields indicating the used signature algorithm.
After executing this first snippet, we got our unsigned token:
Signing our token
Finally, to ensure our token integrity, we should sign it with a secret. Signature is the HMAC SHA-256 (as specified in header) of our current token. And as usual, we should base64url
encode it.
No need of Utf8.parse
the output of HmacSHA256
. It is indeed already an array of UTF-8 characters. That’s why I didn’t include this method in our base64url
function.
Of course, you shouldn’t share your secret client-side. Tokens should be forged server-side. Otherwise, everyone would be able to modify your tokens and pass them as genuine.
If you execute this code, your signed token should look like:
There is plenty of libraries dealing with JWT. Creating tokens by hand is only a good idea to learn how they work. On a real project, don’t reinvent the wheel and use existing third-part tools, such as LexikJWTAuthenticationBundle for Symfony2 users or node-jsonwebtoken for Node.js developers.
The full code of this post is available as a CodePen.
Another interesting resource: JWT.io
1. JWT Token Overview
JSON Web Token (JWT) is an open standard defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens signs using public/private key pairs, the signature also certifies that only the party holding the private key is the one signed it.
1.1 What is JSON Web Token (JWT) Structure?
JWT tokens consist of 3 parts separated by a period ( . ).
These parts are:
- Header
- Payload
- Signature
The JWT typically looks like:
2. Setting up JJWT library
To start using JJWT library for JWT generation, add following dependencies in your build.gradle file.
Alternatively if using Maven, add following dependencies in pom.xml
3. Create JWT Token
Jwts.builder()
is used to create a JWT token. We can specify claims, subject and other JWT attribute.
Generated JWT Token:
The above code to generate JWT is pretty self-explanatory however let’s check step by step how are we generating JWT token:
- Add claims
name
andemail
with valueJane Doe
and[email protected]
respectively - Add subject in JWT token with value
jane
- Set Id for the JWT token using randomly generate GUID
- Set issued at to current time
- Set expiration to current time plus 5 minutes. So the JWT is valid for only 5 minutes
The JWT generated above is not signed (Check algorithm alg
attribute in the header). We have just encoded the claims in JSON format. If using JWT for authentication or authorization it is advisable to Sign the JWT, so it can be verified.
4. Validate/Parse JWT Token
To validate or parse the JWT token, Jwts.parserBuilder()
method is used.
While parsing the JWT token we need to pass Signing key to verify the JWT signature. Let us see how to sign the JWT token using different algorithms.
5. Create and Validate JWT Token Signed using HMAC Secret
The simplest way of creating a signed JWT token is by using HMAC secret. HMAC stands for hash-based message authentication code and is cryptographic hash function. It is used to simultaneously verify both the data integrity and the authenticity of a token.
5.1 Create JWT Token signed with HMAC
To create JWT token signed with HMAC shared secret, we need to specify signature using .signWith() method.
Generated JWT Token:
5.2 Validate/Parse JWT Token signed with HMAC
To validate/parse the JWT token generated using HMAC shared secret, the same steps can be applied. We need to use setSigningKey()
method to set the key before we parse the JWT token.
Output:
If the JWT token expires (exp
claim value is less than current system time), the parseClaimsJws() method will throw SignatureException
.
6. Create and Validate JWT Token Signed using RSA Private Key
When using JWT token for microservice authentication/authorization it is advisable to sign with RSA Private/Public Keys instead of using Shared HMAC Secret. The token is generated and signed by a central authority (usually an Authorization Server) and each microservice can validate the JWT token using the Public Key exposed from Authorization Server.
Generate Jwt Token With Public Key
Before we see how to generate JWT token with Private/Public key, let us see how to generate a Private and Public RSA Key pairs.
Generate Jwt Token With Keypad
6.1 Generate Private and Public RSA Key
Generate an RSA private key, of size 2048, and output it to a file named key.pem:
Extract the public key from the key pair, which can be used in a certificate:
Generate Jwt Token With Keys
The key.pem
file contains the private key generated using RSA and public.pem
file contains public key.
6.2 Create JWT Token signed with RSA
Following code snippets shows how to generate JWT Token Signed using RSA.
Generated JWT Token:
For simplicity the Private Key is hard coded in above example. However, in real production system it will be loaded from environment variable, or a secret vault (Hashicorp Vault or AWS Parameter Store).
In above example the method getPrivateKey()
gets the java.security.PrivateKey
which is then used in Jwts.builder
to sign the JWT token using Private key.
6.3 Validate/Parse JWT Token signed with RSA Private/Public Keys
Next, let us validate and parse the JWT signed using RSA. For that we will need Public Key instance in java.security.PublicKey
format which Jwts.parserBuilder
will use to validate the JWT.
Generate Jwt Token With Private Key
Output:
In above example, we have hardcoded the Public Key. In a production system, it is usually configured through environment variable or service configuration.
7. Source Code – Generate and Validate JWT Tokens using Java & JJWT
Generate Jwt Token With Private Key Python
Source code for the Creating and Validating JWT token in Java.
Github – source code