Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DjangoCon US 2018 - Finally Understand User Aut...

William S. Vincent
November 01, 2018
3

DjangoCon US 2018 - Finally Understand User Authentication in Django REST Framework

Traditional Django handles user authentication for us. REST Framework? Not so much. The abundance of choice is overwhelming and typically THE biggest obstacle for newcomers. This talk is a deep dive on authentication in Django REST Framework. We’ll start with an overview of HTTP and REST APIs before demonstrating how to implement the 4 built-in auth modes and their respective pros/cons. Special attention will be paid to common gotchas such as, Why do I need “both” TokenAuth and SessionAuth? What are JWTs? Next we’ll implement a real-world REST auth setup that includes user registration, password reset/confirm, social auth, and endpoints for sign up, log in, and log out. The third-party packages django-rest-auth and django-allauth will be used . By the end of the talk attendees will understand the basics of REST authentication, the tradeoffs involved, and walk away with a working implementation to jumpstart their future projects.

William S. Vincent

November 01, 2018
Tweet

Transcript

  1. +

  2. HTTP Verbs Functionality Create Read Update Delete HTTP Method/Verb POST

    GET PUT/PATCH DELETE Rough equivalence between CRUD & HTTP verbs
  3. HTTP Status Codes Code 2xx 3xx 4xx 5xx Meaning Success

    (200, 201) Redirection (301) Client error (404, 401) Server error (500)
  4. HTTP Response Message HTTP/1.1 200 OK Date: Wed, 03 Oct

    2018 17:50:58 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 1270 Start Line Header(s)
  5. HTTP Response Message HTTP/1.1 200 OK Date: Wed, 03 Oct

    2018 17:50:58 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 1270 <!doctype html> <html> <head> <title>Example Domain</title> ...
  6. Takeaway CLIENT SERVER GET http://www.example.com HTTP/1.1 HTTP/1.1 200 OK Host:

    www.example.com Date: Tue, 16 Oct 2018 22:38:34 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 1270 <!doctype html> <html> <head> <title>Example Domain</title> ...
  7. $ curl http://127.0.0.1:8000/users/ -v > GET /users/ HTTP/1.1 > Host:

    127.0.0.1:8000 > < HTTP/1.1 200 OK < Date: Wed, 03 Oct 2018 16:37:28 GMT < Server: WSGIServer/0.2 CPython/3.7.0 < Vary: Accept, Cookie < Allow: GET, HEAD, OPTIONS < X-Frame-Options: SAMEORIGIN < [{“id”:1,”username”:”wsv”}]
  8. HTTP Authentication CLIENT SERVER GET / HTTP/1.1 HTTP/1.1 401 Unauthorized

    WWW-Authenticate: Basic GET / HTTP/1.1 Authorization: Basic d3N2OnBhc3N3b3JkMTIz HTTP/1.1 200 OK
  9. #1 BasicAuthentication CLIENT SERVER 1) Send me web resource please?

    2) Who are you? Identify yourself! 3) Hereʼs my username/password in Authorization HTTP Header. 4) Checks credentials. Looks good. Letʼs chat!
  10. #1 BasicAuthentication CLIENT SERVER GET / HTTP/1.1 HTTP/1.1 401 Unauthorized

    WWW-Authenticate: Basic GET / HTTP/1.1 Authorization: Basic d3N2OnBhc3N3b3JkMTIz HTTP/1.1 200 OK
  11. #1 BasicAuthentication Pros Cons Simple Every request look up Session

    Object Credentials passed in clear text Only suitable for testing Must use HTTPS
  12. #2 SessionAuthentication CLIENT SERVER 1) Send me web resource please?

    2) Who are you? Identify yourself! 3) Ok, Iʼll log in with credentials. 4) Looks good. Iʼve created a Session Object and ID. 5) Cool, Iʼll store the ID locally and include in HTTP Header. 6) Iʼll compare Session ID to Session Object on every request.
  13. #2 SessionAuthentication Pros Cons Secure Not good for multiple front-ends

    Only validate user once Hard to keep up-to-date
  14. #3 TokenAuthentication CLIENT SERVER 1) Send me web resource please?

    2) Who are you? Identify yourself! 3) Ok, Iʼll log in with credentials. 4) Looks good. Iʼve created a signed Token. 5) Cool, Iʼll store the signed token and include in HTTP Header. 6) Iʼll check the signed token on every request.
  15. #3 TokenAuthentication CLIENT SERVER GET / HTTP/1.1 HTTP/1.1 401 Unauthorized

    WWW-Authenticate: Token GET / HTTP/1.1 Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a HTTP/1.1 200 OK
  16. #3 TokenAuthentication (code) # settings.py INSTALLED_APPS = [ 'rest_framework.authtoken', ]

    REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ] }
  17. #3 TokenAuthentication Pros Cons Easy to scale Large tokens hurt

    performance Only validate user once Tokens never expire
  18. BasicAuthentication - insecure, for testing only SessionAuthentication - same session

    context as website, powers DRF visualizer TokenAuthentication - secure, recommended default! RemoteUserAuthentication - intranet sites, rarely used
  19. JWTs Pros Cons Store more data Large size Can be

    signed Complicated setup Can be encrypted Can set to expire
  20. Getting Started $ pipenv install django $ pipenv shell (env)

    $ django-admin startproject example_project . (env) $ python manage.py startapp users
  21. Custom User Model (part 1) # example_project/settings.py INSTALLED_APPS = [

    ... # Local 'users.apps.UsersConfig', # new ] AUTH_USER_MODEL = 'users.CustomUser' # new
  22. Custom User Model (part 2) # users/models.py from django.contrib.auth.models import

    AbstractUser from django.db import models class CustomUser(AbstractUser): pass
  23. Custom User Model (part 3) # users/admin.py from django.contrib import

    admin from django.contrib.auth.admin import UserAdmin from .models import CustomUser class CustomUserAdmin(UserAdmin): model = CustomUser admin.site.register(CustomUser, CustomUserAdmin)
  24. Custom User Model (part 4) (env) $ python manage.py makemigrations

    users (env) $ python manage.py migrate (env) $ python manage.py createsuperuser (env) $ python manage.py runserver
  25. Install Django REST Framework # example_project/settings.py INSTALLED_APPS = [ ...

    # Local 'users.apps.UsersConfig', # 3rd party 'rest_framework', # new 'rest_framework.authtoken', # new ]
  26. Install django-rest-auth (part 2) # example_project/settings.py INSTALLED_APPS = [ ...

    # Local 'users.apps.UsersConfig', # 3rd party 'rest_framework', 'rest_framework.authtoken', 'rest_auth', # new ]
  27. Install django-rest-auth (part 3) # example_project/urls.py from django.contrib import admin

    from django.urls import path, include # new urlpatterns = [ path('admin/', admin.site.urls), path('rest-auth/', include('rest_auth.urls')), # new ]
  28. Install django-allauth (part 2) # example_project/settings.py INSTALLED_APPS = [ ...

    # Local 'users.apps.UsersConfig', # 3rd party 'rest_framework', 'rest_auth', 'django.contrib.sites', # new 'allauth', # new 'allauth.account', # new 'rest_auth.registration', # new ]
  29. Install django-allauth (part 4) # example_project/urls.py from django.contrib import admin

    from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('users/', include('users.urls')), path('rest-auth/', include('rest_auth.urls')), path('rest-auth/registration/', include('rest_auth.registration.urls')), # new ]
  30. Install django-allauth (part 5) (env) $ python manage.py migrate (env)

    $ python manage.py runserver http://127.0.0.1:8000/rest-auth/registration/