Moove It is now Qubika. For more information, visit our new website
Visit Qubika

What is it for?

Token based authentication is a new security technique for authenticating a user who attempts to log in to a secure system (e.g. server), using a signed token provided by the server.

The authentication is successful if the system can prove that the tokens belong to a valid user.

It is important to note that Json Web Token (JWT) provides signed tokens but not encrypted ones, so passwords or any critical information must not be included in the token unless you encrypt the data (e.g. using JWE).

Why use it?

Here are some advantages of choosing JWT:

  • Standard: JWT is becoming a standard, and there a multiple libraries for a lot of languages (Ruby, Java, Python, Node, Backbone). So the integration with your language or technology should be pretty easy.
  • Cross-domain / CORS: Since the information is transmitted using an HTTP header, you are able to make AJAX requests to any server or domain.
  • Protection from CSRF: The token must be included in every request made to the server, and will be validated by the server. The token is linked to the user’s current session.
  • Server side Scalability: The token is self-contained(i.e. contains all the user info), so there’s no need to keep a session store. The rest of the state lives in the client’s local storage.
    The token might be generated anywhere, so you are not tied to any specific authentication scheme, decoupling this process from your application.

Warning: since the information is transmitted in an HTTP header and its size is limited, the token size could be an issue.

How does it work?

Let’s see an example of how to use JWT to authenticate a user. In this example we will be using Ruby, Rails and AngularJS.

Server Side

Let’s suppose we have an authentication controller.

When a post to create a session comes to the server, we validate the user and create a new JWT.

class AuthController < ApplicationController

  # session creation
  def create
    user = User.authenticate!(params[:user])
    render json: { token: create_token(user) }
  end
 
  private
 
  def create_token(user)
    secret = ‘secret’ # must be an environment variable
    JWT.encode(user, secret)
  end
end

Then, for every request we have to validate the token before processing it.

class Api::ExampleController < ApplicationController
  before_action :validate_token
 
  def index
    render json: Example.all.to_json
  end
 
  private
 
  def validate_token
    secret = ‘secret’ # must be an environment variable 
    begin
      token = request.headers['Authorization'].split(' ').last
      JWT.decode(token, 'secret')
    rescue JWT::DecodeError
      head :unauthorized
    end
  end
end

Let’s take a look at the token. When we encode a new token, we get this string:

> user = {username: 'example_user', email: 'mail@example.com', id: 123}
 => {:username=>"example_user", :email=>"mail@example.com", :id=>123} 
> token = JWT.encode(user, "secret")
 => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImV4YW1wbGVfdXNlciIsImVtYWlsIjoibWFpbEBleGFtcGxlLmNvbSIsImlkIjoxMjN9.BEtGLs7sZwLztKsitaFTCysmluXMM6yU2-373JGHKWk"

Then, when we decode the token, we retrieve this:

> JWT.decode(token, "secret")
 => [{"username"=>"example_user", "email"=>"mail@example.com", "id"=>123}, {"typ"=>"JWT", "alg"=>"HS256"}]

[{"username"=>"example_user", "email"=>"mail@example.com", "id"=>123} # user information
{"typ"=>"JWT", "alg"=>"HS256"}] # token information, typ is the content type and alg is the encode algorithm used

If we want, we could add some claims to the token:

  • exp : identifies the expiration time on or after the token MUST NOT  be accepted for processing.
  • nbf : identifies the time before the token MUST NOT be accepted for processing.
  • iat : identifies the time when the  JWT was issued.

Client Side

An example of a sign in request to the server from the Angular app.

myApp.controller('UserCtrl', function ($scope, $http, $window) {
  $scope.user = {username: ''example_user'', password: 'pass'};
  $scope.submit = function () {
    $http
      .post('/sessions', $scope.user)
      .success(function (data, status, headers, config) {
        $window.sessionStorage.token = data.token;
      })
  };
});

Once we have the token, we can make any request to the server using the token.

angular.module('exampleApp')
    .service('Example', function Leagues( ENV, $http, Session ) {
      return {
             get: function( callback ){
                  $http.defaults.headers.common['Authorization'] = "Bearer " +   
                       $window.sessionStorage.token;
                  $http.get( ENV.apiEndPoint + '/example')
                        .success(function(data, status, headers, config) {
                            callback(data);
                        })
              }
       }
});

Reference Links

Get our stories delivered from us to your inbox weekly.