DjangoCon US 2014 talk on JSON Web Tokens
JWT
View Slide
“jot”
JSON Web Tokens
José Padilla
Flickr: Bryan Vincent
Co-founder atblimp.io
/jpadilla
jpadilla.com
Why?
Single Sign-on
Action Links
Webhooks
Token-based Auth
What?
“Compact URL-safe means of representingclaims to be transferred between two parties. Theclaims in a JWT are encoded as a JSON objectthat is digitally signed using JSON WebSignature (JWS).” - IETF.
JOSE
JavaScriptObjectSigning andEncryption
JWA
JSONWebAlgorithms
JWK
JSONWebKey
JSONWebToken
JWS
JSONWebSignature
JWE
JSONWebEncryption
Today it’sall aboutJWT
How?
Internet-Draft
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.xpCS8TTq1a53OIps1ByTdm6Sh-A1ZoCId3e2YYWjapU
{"typ": "JWT","alg": "HS256"}eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.xpCS8TTq1a53OIps1ByTdm6Sh-A1ZoCId3e2YYWjapU
import jsonimport hmacfrom hashlib import sha256from base64 import urlsafe_b64encode!segments = []!header_dict = {'typ':'JWT','alg': 'HS256'}!json_header = json.dumps(header_dict)!header = urlsafe_b64encode(json_header).rstrip('=')segments.append(header)eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.xpCS8TTq1a53OIps1ByTdm6Sh-A1ZoCId3e2YYWjapU
{!"user_id": 1!}eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.xpCS8TTq1a53OIps1ByTdm6Sh-A1ZoCId3e2YYWjapU
payload_dict = {'user_id': 1}!json_payload = json.dumps(payload)!payload = urlsafe_b64encode(json_payload).rstrip('=')segments.append(payload)eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.xpCS8TTq1a53OIps1ByTdm6Sh-A1ZoCId3e2YYWjapU
SECRET = 'abc123'!signing_input = '.'.join(segments)!sig = hmac.new(SECRET, signing_input, sha256)signature = urlsafe_b64encode(sig.digest()).rstrip('=')segments.append(signature)!token = '.'.join(segments)eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.xpCS8TTq1a53OIps1ByTdm6Sh-A1ZoCId3e2YYWjapU
PyJWT
$ pip install PyJWT
import jwt!SECRET_KEY = "abc123"payload = {"user_id": 1}!jwt_token = jwt.encode(payload, SECRET_KEY)!payload = jwt.decode(jwt_token, SECRET_KEY)
/progrium/pyjwt
Django JWT Auth
username/passwordJWTError/login
Authorization: Bearer JWTError/restricted
$ pip install django-jwt
import json!from django.views.generic import Viewfrom django.http import HttpResponse!from jwt_auth.mixins import JSONWebTokenAuthMixin!!class RestrictedView(JSONWebTokenAuthMixin, View):def get(self, request):data = json.dumps({'foo': 'bar'})return HttpResponse(data, content_type='application/json')
from django.conf.urls import patternsfrom .views import RestrictedViewurlpatterns = patterns('',!(r'^login/$', 'jwt_auth.views.obtain_jwt_token'),(r'^restricted/$', RestrictedView.as_view()),)
/jpadilla/django-jwt-auth
DRF JWT Auth
$ pip install djangorestframework-jwt
from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom rest_framework.permissions import IsAuthenticatedfrom rest_framework_jwt.authentication import JSONWebTokenAuthenticationclass RestrictedView(APIView):permission_classes = (IsAuthenticated, )authentication_classes = (JSONWebTokenAuthentication, )def get(self, request):data = {'foo': 'bar'}!return Response(data)
from django.conf.urls import patternsfrom .views import RestrictedViewurlpatterns = patterns('',!(r'^login/', 'rest_framework_jwt.views.obtain_jwt_token'),(r'^restricted/$', RestrictedView.as_view()),)
var url = 'http://localhost:8000/login/',creds = {username: 'admin',password: 'abc123'};$.post(url, creds, function(auth) {$.ajax({type: 'GET',url: 'http://localhost:8000/restricted/',beforeSend: function(xhr) {xhr.setRequestHeader("Authorization", "Bearer " + auth.token);},success: function(data){console.log(data);// {// foo: "bar"// }}});});
/GetBlimp/django-rest-framework-jwt
Recap• It’s a standard• It’s simple• Third party libraries• Single Sign-on• Action links• Authentication• CORS• Stateless• No CSRF• CDN• Mobile/WebSockets
DjangoREST FrameworkSprint
ThanksQuestions?http://bit.ly/djangocon-jwt