Token based Authentication system using JWT (JSON Web Token)

UltimateCoder (~ultimatecoder)


3

Votes

Description:

JSON Web Token

Definition

JWT is standard for making authentication token. 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 encrypted.

JSON Web Token as Token Based Authentication system

Unlike session based authentication, Token based authentication system takes very less load of server. In session based authentication system, maintaining of session storage is requires processing and storage. While as Token based authentication system, it is not required to maintain session storage at server side. Tone of processing and storage will be saved. Beauty of using JWT as authentication token is it's simplicity. Once token is created, it is possible to authenticate user without touching the database again. Token can be discarded when it is expired by time from the expire time mentioned in token itself. The JWT is self contained token which has authentication, expire time information and any other user defined claims digitally signed.

Usage

JWT can be used to provide Token Based Authentication system at your ReST API. Because JWT is self contained with required claims it is possible to scale API without depending on Authentication server.

Talk Outline:

  1. Session Based Authentication Vs Token Based Authentication.
  2. Advantage of JWT as Authentication token.
  3. Example of JSON Web Token, Will explain various parts like Header, Payload and Signed MAC.
  4. Algorithms that can be used to sign JWT Payload.
  5. Explain various claims used for JWT.
  6. Demonstrate
    1. Creating JWT and sending to requested client
    2. How to validate given JWT with respect to time and payload values.
  7. Best practice to create JWT.
  8. Practical example of JWT as Django Authentication module.

Some notes on Oauth 2.0

Oauth 2.0 uses JWT as token exchange standard. Using JWT is simple and more efficient when we have to design authentication system for our internal client who are not user of any Oauth provider like Gmail, Facebook etc. OAuth 2.0 contains many payload values which increase token size and it requires time to transfer where as using JWT, it is possible to get small size token with best security as Oauth 2.0

Slide Outline

Token Based Authentication system using JWT

By Jaysinh Shukla


Speaker Description

Speaker Image

  • Role: Full stack developer

  • Github:

    1 http://github.com/ultimatecoder

    2 http://github.com/jsh-odoo

  • Twitter: @jaysinhp

  • Email: jaysinhp@gmail.com

  • IRC: thebigj


Types of Authentication

  • Session / Cookie Authentication
  • Token Authentication

Session Authentication for Multiple User

Session Authentication Multiple User


Session or Cookie Authentication

  • Client sends authentication credentials (username and password) to Server.

  • Server verifies authentication credentials

    • if valid, assigns session storage, creates session id and returns session id to requested client.
  • Client stores session id probably at Cookie storage. This id is sent by client with every request. And from that session id user is identified further.

  • This allows to identified the same user from upcoming request without re asking user credentials.


Disadvantages of Session Authentication

  • Difficult to handle with Load balancer

  • Required high amount of resource(RAM without mass-storage) for maintaining huge amount of user session parallel.

  • CORS doesn't work well with cookies


Birth of Token Authentication

  • Token based authentication are most popular authentication system for APIs.

  • Comparatively puts less load than Session authentication.

  • Best for

    • Scaling

    • Load balancer

  • No cookie, No CSRF protection.

  • Same API, Authentication will be used for Mobile and Front end app.


Algorithm of Token Authentication

  • Client sends authentication credentials.

  • Authentication credentials are verified by server. If valid Token is crated.

  • Token is logged to database and the token is sent back as authentication token

  • The client sends Token with every request to get verified.

  • Normally token is generated with random value and hashed with popular hashing algorithm.

  • Revoking access of specific Token by deactivating record at token table.


How Token Authentication works normally

Normal Token Authentication


Example of authentication at Djnago Rest Framework

from rest_framework.authtoken.models import Token

token = Token.objects.create(user=...)
print token.key

Above code is used at authentication view where that token.key is returned if credentials are right.

Assuming random output 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b

Example of Client request using curl

curl -X GET http://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'

Example of Token Authentication at Django Rest Framework

@python_2_unicode_compatible
class Token(models.Model):
    """
    The default authorization token model.
    """
    key = models.CharField(_("Key"), max_length=40, primary_key=True)
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL, related_name='auth_token',
        on_delete=models.CASCADE, verbose_name=_("User")
    )
    created = models.DateTimeField(_("Created"), auto_now_add=True)

    class Meta:
        verbose_name = _("Token")
        verbose_name_plural = _("Tokens")

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = self.generate_key()
        return super(Token, self).save(*args, **kwargs)

    def generate_key(self):
        return binascii.hexlify(os.urandom(20)).decode()

Problems, Problems every where

  • Impossible to

    • identify user from which client (like Angular App, Android App, etc) is authenticated with.

    • provide way of access control with respect to client.

    • judge that the token is valid by time or not.

    • predict for how much time token is valid for.

  • Difficult to

    • Scale because of having dependency on database to authenticate client with each request

    • run authentication logic separate from API server.

  • Quite difficult to

    • scale

    • identify when client is identified from multiple sources semantically.


Solution is awesome JWT!

  • Suggested pronunciation is "jot".

  • JSON Web Token is JSON based Web Authentication Token.

  • The token is a combination of three parts. Header, Claim set and Signature.

  • Each part of authentication token is encoded with base64url encoding and separated with "."


How Token Authentication works with JWT

JWT Token Authentication


Structure Of JSON Web Token

  eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4
  MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K2
  7uhbUJU1p1r_wW1gFWFOEjXk
  • The token is containing three different part separated with "."

  • Each part is encoded with base64url encoding.

  • The first part the .red[Red Part] is JOSE Header

  • The second part the .blue[Blue Part] is JWT Claim set

  • The third part the .green[Green Part] is JWT Signature

  • Base64URL(JOSE Header).Base64URL(JWT Claims).Base64URL(JWT Signature)


JOSE Header

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
  • Decoded with Base64 encoding:

    { "typ":"JWT", "alg":"HS256" }

  • Here,

    • typ defines type of the JSON Web Token. It is not optional.

    • alg represents type of algorithm used for signing the claim set.


JWT Claim-set

  eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ
  • Decoding with Base64 encoding:

    { "iss":"joe", "exp":1300819380, "is_root":true }

  • Here,

    • iss is registered claim. It represents the name of Issuer of the token

    • exp is registered claim. It represents expiration time in format of Unix time

    • is_root is unregistered claim. User defined claim which can be presumed that it is considering user as root user.


JWT Signature

dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
  • Signature is MAC of encoded JOSE Header and encoded JWS Payload with the HMAC SHA-256 algorithm.

  • And then base64url encoding of that HMAC value.

  • This signature helps to verify the authenticity of the Token.


Generate JWT Token

  • Define secret key

  • Example using pyjwt

<pre> >>> import jwt >>> token = jwt.encode({'user_id': 1}, '12345', algorithm='HS256') >>> token b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.0X_1nSfbSETzHhcoeywtv6zXXlQd13M3d0-su89rfvM' </pre>

  • Here, 12345 is considered as secret key and HS256 is the algorithm we are using.

Example of Verifying Token

# Assume token is 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.0X_1nSfbSETzHhcoeywtv6zXXlQd13M3d0-su89rfvM'
  >>> jwt.decode(token, '12345', algorithms=['HS256'])
  {'user_id': 1}
  • Here, 12345 is secret key.

JWT Authentication at Django

from django.contrib.auth import authenticate


class Login(View):

    def post(self, request, *args, **kwargs):
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(username=username, password=password)

        if user:
            payload = {
                'id': user.pk,
                'username': user.username,
                'staff': user.is_staff,
                'exp': datetime.utcnow() + EXPIRY_TIME
            }
            token = {'token': jwt.encode(payload, SECRET)}
            return HttpResponse(
              json.dumps(token),
              content_type="application/json"
            )
        else:
            return HttpResponse(
              json.dumps({'Error': "Invalid credentials"}),
              status=400,
              content_type="application/json"
            )

JWT Token Verification at Django

class JWT_AuthMiddleware(object):

    def _get_token(request=None):
        return request.META.get('HTTP_AUTHORIZATION') or request.GET.get('token')

    def process_request(self, request):
        token = self._get_token(request)
        try:
            payload = jwt.decode(token, SECRET)
            request.user = User.objects.get(
                username=payload.get('username'),
                pk=payload.get('id'),
                is_active=True
            )
        except jwt.ExpiredSignature, jwt.DecodeError, jwt.InvalidTokenError:
            return HttpResponse({'Error': "Token is invalid"}, status="403")
        except User.DoesNotExist:
            return HttpResponse({'Error': "Internal server error"}, status="500")

Still it is not over!

  • If user is logged out, then also the token will be accepted until it is expired by time.

  • For Example, We assigned the token to "X" user and assigned the expire time to next 3 days and user is logged out after 1 day, that token can be used by attacker for that unused 2 days and API will consider Token as valid.

  • As a best practice, set expiry time not longer than 10 minutes!

  • As a good practice keep less values in claim. Adding many claims may increase size of token which takes time to transfer the token.

  • Change your Secret key periodically and Black list tokens if possible.


What we are doing with JWT

  • Creating JWT token

  • Validating Token at every request.

  • Allowing user to refresh token if given Token is valid.

  • If user is logging out then creating entry of token to Black list table

  • Advantage:

    • Token will not be used further if it is Black listed even in the valid time frame.

How we are using JWT

Our Token Authentication


JWT Claims

  • Types of Claims

    1 Registered Claim Names

    2 Public Claim Names

    3 Private Claim Names


JWT Registered Claim names

  • iss: Depicting Issuer of the token

  • sub: Subject of the Token

  • aud: Audience for which token is given for

  • exp: Expiration time in Unix time.

  • nbf: Token should not be accepted before this value. In Unix time format

  • iat: Representing age of the token

  • jti: Depicting ID of the token


JWT Public Claim names


JWT Private Claim names

  • Custom claims which are not publicly used but represented as claims in JWT.

  • This custom claims should be considered as private claims.


Similar Technologies

1 Simple Web Token

2 JSON Simple Singn


Why not to go with Oauth 2.0?

  • Oauth 2.0 uses JWT as token exchange standard.

  • But Oauth 2.0 is more focused for three parties. Resource owner, Authorization Server, Resource Server

  • Using JWT is simple and more efficient when focus is only authentication.

  • OAuth 2.0 contains many payload values which will increase the size of token.


References

  • https://en.wikipedia.org/wiki/Session_(computer_science)

  • https://tools.ietf.org/html/rfc7519

  • https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/


Libraries:

  1. https://github.com/jpadilla/pyjwt

Slides over

Talks Conducted on JWT at below events

  1. Ahmedabad-Web-and-Mobile-Developers-Meetup

  2. Community event organized at Startup Gujarat

  3. Hangout On Air

Prerequisites:

  • Python 2 or 3 Interpreter

Content URLs:

  1. https://drive.google.com/open?id=1ajrIkszLNe0qkLbAoVOrBE3esuyLiVAq4XKVrbZI0ho

Speaker Info:

Information:

  • Name: Jaysinh Shukla
  • Employment: Self Employed
  • Role: Fullstack developer
  • City: Gandhinagar
  • Technologies: , Python, Django, AngularJS, Odoo(Open Source ERP)
  • Contributions: Python Express, Oppia
  • Organizer: PyKutch 2016 (http://cs.kutchuni.edu.in/PyKutch-2016/)
  • Talks:

    1. Introduction to Django at PG GTU Gandhinagar
    2. My name is Python and I am not terrorist at K.S.K.V. Kachchh University
    3. Beginning with Python at Gujarat Polytechnic College, Gandhinagar
    4. Beginning with Python at Parul University, Waghodia, Vadodara
  • Conference attended:

    1. Pycon India 2015 at Bangalore
    2. Mini Pycon at New Delhi
  • Hackathons:

    1. Best design winner of Digital India Hackathon 2015, Infocity club resort, Gandhinagar:
    2. Hack Baroda 2015, Vadodara

Speaker Links:

  • Github:
  1. http://github.com/ultimatecoder
  2. http://github.com/jsh-odoo
  • Twitter: @jaysinhp
  • Emai: jaysinhp@gmail.com
  • IRC: thebigj
  • Mobile: +919426789373

Section: Web Development
Type: Talks
Target Audience: Intermediate
Last Updated: