Django session authentication for project post api.
authorcavaliet
Fri, 09 Nov 2012 15:58:04 +0100
changeset 920 510e079e4b15
parent 919 11650ed8126e
child 921 4e24ad4db185
Django session authentication for project post api.
src/ldt/ldt/api/ldt/authentication.py
src/ldt/ldt/api/ldt/resources/project.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/api/ldt/authentication.py	Fri Nov 09 15:58:04 2012 +0100
@@ -0,0 +1,58 @@
+from django.conf import settings
+from django.middleware.csrf import _sanitize_token, constant_time_compare
+from django.utils.http import same_origin
+from tastypie.authentication import Authentication
+
+# imported from tastypie's next version 0.9.12
+class SessionAuthentication(Authentication):
+    """
+    An authentication mechanism that piggy-backs on Django sessions.
+    
+    This is useful when the API is talking to Javascript on the same site.
+    Relies on the user being logged in through the standard Django login
+    setup.
+    
+    Requires a valid CSRF token.
+    """
+    def is_authenticated(self, request, **kwargs):
+        """
+        Checks to make sure the user is logged in & has a Django session.
+        """
+        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
+        # We can't just use what's there, since the return values will be
+        # wrong.
+        # We also can't risk accessing ``request.POST``, which will break with
+        # the serialized bodies.
+        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
+            return request.user.is_authenticated()
+
+        if getattr(request, '_dont_enforce_csrf_checks', False):
+            return request.user.is_authenticated()
+
+        csrf_token = _sanitize_token(request.COOKIES.get(settings.CSRF_COOKIE_NAME, ''))
+
+        if request.is_secure():
+            referer = request.META.get('HTTP_REFERER')
+
+            if referer is None:
+                return False
+
+            good_referer = 'https://%s/' % request.get_host()
+
+            if not same_origin(referer, good_referer):
+                return False
+
+        request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
+
+        if not constant_time_compare(request_csrf_token, csrf_token):
+            return False
+
+        return request.user.is_authenticated()
+
+    def get_identifier(self, request):
+        """
+        Provides a unique string identifier for the requestor.
+        
+        This implementation returns the user's username.
+        """
+        return request.user.username
\ No newline at end of file
--- a/src/ldt/ldt/api/ldt/resources/project.py	Fri Nov 09 15:12:10 2012 +0100
+++ b/src/ldt/ldt/api/ldt/resources/project.py	Fri Nov 09 15:58:04 2012 +0100
@@ -1,5 +1,6 @@
 from django.conf.urls.defaults import url
 from ldt.ldt_utils.models import Project
+from ldt.api.ldt.authentication import SessionAuthentication
 from ldt.api.ldt.serializers.cinelabserializer import CinelabSerializer
 from ldt.api.ldt.resources import ContentResource
 from ldt.api.ldt.resources.user import UserResource
@@ -14,6 +15,7 @@
     class Meta:
         allowed_methods = ['get', 'post']
         authorization = Authorization() # BE CAREFUL WITH THAT, it's unsecure
+        authentication = SessionAuthentication()
         resource_name = 'projects'
         queryset = Project.objects.all()
         serializer = CinelabSerializer()