Token based Authentication system using JWT (JSON Web Token)
UltimateCoder (~ultimatecoder) |
3
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:
- Session Based Authentication Vs Token Based Authentication.
- Advantage of JWT as Authentication token.
- Example of JSON Web Token, Will explain various parts like Header, Payload and Signed MAC.
- Algorithms that can be used to sign JWT Payload.
- Explain various claims used for JWT.
- Demonstrate
- Creating JWT and sending to requested client
- How to validate given JWT with respect to time and payload values.
- Best practice to create JWT.
- 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
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 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
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
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
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
- It can be defined by fellows using JWT on condition that they have to register this claim at IANA "JSON Web Token Claims" registry
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
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:
- https://github.com/jpadilla/pyjwt
Slides over
Talks Conducted on JWT at below events
Prerequisites:
- Python 2 or 3 Interpreter
Content URLs:
- 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:
- Introduction to Django at PG GTU Gandhinagar
- My name is Python and I am not terrorist at K.S.K.V. Kachchh University
- Beginning with Python at Gujarat Polytechnic College, Gandhinagar
- Beginning with Python at Parul University, Waghodia, Vadodara
Conference attended:
- Pycon India 2015 at Bangalore
- Mini Pycon at New Delhi
Hackathons:
- Best design winner of Digital India Hackathon 2015, Infocity club resort, Gandhinagar:
- Hack Baroda 2015, Vadodara
Speaker Links:
- Github:
- http://github.com/ultimatecoder
- http://github.com/jsh-odoo
- Twitter: @jaysinhp
- Emai: jaysinhp@gmail.com
- IRC: thebigj
- Mobile: +919426789373