diff --git a/requirements/dev.txt b/requirements/dev.txt index 025172814..9fe7cb7b1 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -50,4 +50,12 @@ pytest-xdist==1.31.0 cssselect==1.1.0 # PostgreSQL database adapter for the Python -psycopg2-binary==2.8.5 \ No newline at end of file +psycopg2-binary==2.8.5 + +# JSON Web Token implementation in Python +# https://pyjwt.readthedocs.io/en/stable/ +PyJWT==1.7.1 + +# A JSON Web Token authentication plugin for the Django REST Framework. +# https://django-rest-framework-simplejwt.readthedocs.io/en/stable/ +djangorestframework-simplejwt==4.4.0 \ No newline at end of file diff --git a/src/attendee/api/views.py b/src/attendee/api/views.py index b7a9fc338..12c56c9f1 100644 --- a/src/attendee/api/views.py +++ b/src/attendee/api/views.py @@ -3,13 +3,13 @@ from rest_framework.response import Response from registry.helper import reg from rest_framework.permissions import IsAuthenticated +from rest_framework_simplejwt.authentication import JWTAuthentication -from core.authentication import TokenAuthentication from attendee.models import Attendee class AttendeeAPIView(views.APIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] model = Attendee diff --git a/src/events/api/views.py b/src/events/api/views.py index 7e8906481..e7eb53b60 100644 --- a/src/events/api/views.py +++ b/src/events/api/views.py @@ -4,12 +4,12 @@ from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework_simplejwt.authentication import JWTAuthentication from django.conf import settings from django.db.models import Count from django.http import Http404 -from core.authentication import TokenAuthentication from events.models import ( CustomEvent, Location, ProposedTalkEvent, ProposedTutorialEvent, SponsoredEvent, Time, KeynoteEvent @@ -34,7 +34,7 @@ class TutorialListAPIView(ListAPIView): class SpeechListAPIView(APIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): @@ -76,7 +76,7 @@ class TutorialDetailAPIView(RetrieveAPIView): class SpeechDetailAPIView(APIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): @@ -213,7 +213,7 @@ def display(self): class ScheduleAPIView(APIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] event_querysets = [ @@ -294,7 +294,7 @@ def get(self, request): class KeynoteEventListAPIView(ListAPIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] queryset = KeynoteEvent.objects.all() diff --git a/src/pycontw2016/settings/local.py b/src/pycontw2016/settings/local.py index 929560a70..e174b9517 100644 --- a/src/pycontw2016/settings/local.py +++ b/src/pycontw2016/settings/local.py @@ -3,6 +3,7 @@ env, ) from .base import * # NOQA +from datetime import timedelta import logging.config import os @@ -99,3 +100,8 @@ DJANGO_Q_DEBUG = True + +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=10), + 'AUTH_HEADER_TYPES': ('Token',), +} diff --git a/src/pycontw2016/urls.py b/src/pycontw2016/urls.py index a10087a07..1d667b3e9 100644 --- a/src/pycontw2016/urls.py +++ b/src/pycontw2016/urls.py @@ -36,7 +36,8 @@ url(r'^api/events/', include('events.api.urls', namespace="events")), url(r'^set-language/$', set_language, name='set_language'), url(r'^admin/', admin.site.urls), - url(r'^api/attendee/', include('attendee.api.urls')) + url(r'^api/attendee/', include('attendee.api.urls')), + url(r'api/token/', include('security.urls')) ] # User-uploaded files like profile pics need to be served in development. diff --git a/src/security/__init__.py b/src/security/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/security/urls.py b/src/security/urls.py new file mode 100644 index 000000000..074d7759f --- /dev/null +++ b/src/security/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from rest_framework_simplejwt.views import ( + TokenObtainPairView, + TokenRefreshView, +) + + +urlpatterns = [ + path('', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('refresh/', TokenRefreshView.as_view(), name='token_refresh') +] diff --git a/src/sponsors/api/views.py b/src/sponsors/api/views.py index 41636a81a..d3682fcd9 100644 --- a/src/sponsors/api/views.py +++ b/src/sponsors/api/views.py @@ -3,13 +3,13 @@ from rest_framework import views from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework_simplejwt.authentication import JWTAuthentication -from core.authentication import TokenAuthentication from sponsors.models import Sponsor, OpenRole class SponsorAPIView(views.APIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request): @@ -42,7 +42,7 @@ def get(self, request): class JobAPIView(views.APIView): - authentication_classes = [TokenAuthentication] + authentication_classes = [JWTAuthentication] permission_classes = [IsAuthenticated] def get(self, request):