Secure API with JWT (JSON Web Token)

2 min read

I have recently come across JSON Web Token (JWT) which is pronounced as ‘jot’. So what is JWT?
Here is the definition that I read from https://self-issued.info/docs/draft-ietf-oauth-json-web-token.html

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 used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

We build API’s for different projects and to we use tokens to secure API across . Token help us to validate each request.
This is how we secure the API with token. JWT is about generating/encoding/decoding.. token. JWT token will consists of three parts.
jwt-structure
JWT token will look like following.
[source=’ruby’]
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
[/source]
Header, payload and signature are separated by dot(.)
Header will contain type of token and algorithm used for encrypting the token. Payload will contain the basic information, e.g userid
Without using JWT token, when a user requests a token with proper credentials, API server will return the JSON with token information to that user. Response JSON will contain userid, token and other info if required. When we use JWT token, simple token will be sent. By decoding the token, the claims can be extracted.
api_token_save
JWT client libraries are available for different languages. See the list of available client libraries http://jwt.io/
I am going to create new JWT token with Ruby client library (gem json_web_token). Add gem ‘jwt’ to your Gemfile and bundle install
[source=’ruby’]
$> rails c
payload = {:user_id => 1, :name => “Sivakumar”}
token = JWT.encode payload, nil, ‘none’
[/source]
Output will be a JWT token.
[source=”ruby”]
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoxLCJuYW1lIjoiU2l2YWt1bWFyIn0.
[/source]
If you see the second parameter in above code, its ‘non’ which means, no encoding. It uses simple base64 encoding but we can also use different algorithm for encoding. See the list of supported algorithms here <a href=”https://github.com/jwt/ruby-jwt” target=”_blank”>https://github.com/jwt/ruby-jwt</a>
Next lets encrypt the payload using HS256
[source=’ruby’]
payload = {:user_id => 1, :name => “Sivakumar”}
secret = “misecretee”
token = JWT.encode payload,secret, ‘HS256′
[/source]
Output will be a JWT token encrypted with HS256
[source=’ruby’]
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJuYW1lIjoiU2l2YWt1bWFyIn0.mCV3zdFX-FWg7jqrthTTSrWbHgQpdjzgSxVteARUZA0
[/source]
Reserved claim names
A piece of information asserted about a subject. A claim is represented as a name/value pair consisting of a Claim Name and a Claim Value.

  • ‘exp’ (Expiration Time) Claim
  • ‘nbf’ (Not Before Time) Claim
  • ‘iss’ (Issuer) Claim
  • aud’ (Audience) Claim
  • ‘jti’ (JWT ID) Claim
  • ‘iat’ (Issued At) Claim
  • ‘sub’ (Subject) Claim

Lets create expiration claim. To check ‘exp’ claim, I am going to set ‘exp’ with past date time.
[source=’ruby’]
secret = “misecretee”
exp_date = (Time.now – 1.day).to_i
payload = {:user_id => 1, :name => “Sivakumar”, :exp => exp_date}
token = JWT.encode payload,secret, ‘HS256′
[/source]
Output will look like
[source=’ruby’]
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJuYW1lIjoiU2l2YWt1bWFyIiwiZXhwIjoxNDQyNzQzMzA3fQ._Pjb5vQVZ4y8wtNbo8YUqBCOw2q6gfD-Yy5nIdkgQ8k
[/source]
Next lets decode this token,
[source=’ruby’]
decoded_token = JWT.decode token, secret, true
[/source]
This produce error, because token expired
[source=’ruby’]
JWT::ExpiredSignature: Signature has expired
[/source]
Its very easy to expire token. Also ‘nbf’ (Not Before Time) is very useful. Token will be valid only after some time mentioned in this claim.
I am going to create claim ‘nbf’
[source=’ruby’]
secret = “misecretee”
activate_time = (Time.now + 1.day).to_i
payload = {:user_id => 1, :name => “Sivakumar”, :nbf =>activate_time}
token = JWT.encode payload,secret, ‘HS256′
[/source]
Output will look like
[source=’ruby’]
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJuYW1lIjoiU2l2YWt1bWFyIiwibmJmIjoxNDQyOTE2NjY1fQ.5jKxpZAN6Ot3r_pAaTVlpkReIvgd9mIXdZh-kC9QXto
[/source]
Next lets decode this token
[source=’ruby’]
secret = “misecretee”
decoded_token = JWT.decode token, secret, true
[/source]
 
This will may give error
[source=’ruby’]
JWT::ImmatureSignature: Signature nbf has not been reached
[/source]
If you are interested, you can read about other claims at https://github.com/jwt/ruby-jwt. Using JWT token will be very easy and make your API more secure.
JWT tokens are industrial standard methods for representing claims and they are secure. Client libraries are available for different programming languages. Its very easy to implement.

Related posts:

One Reply to “Secure API with JWT (JSON Web Token)”

Leave a Reply

Your email address will not be published. Required fields are marked *