Import latest auth.py from pgeu as sample
authorMagnus Hagander <magnus@hagander.net>
Sat, 19 Jan 2019 19:00:35 +0000 (20:00 +0100)
committerMagnus Hagander <magnus@hagander.net>
Sat, 26 Jan 2019 15:19:26 +0000 (16:19 +0100)
tools/communityauth/sample/django/auth.py

index 90e293c1f890e8b3a5cf316bcf78aeaf59442f68..13e5b28e7fe052c29efd95c2b13f3054d3f69b4e 100644 (file)
@@ -28,8 +28,8 @@ from django.conf import settings
 import base64
 import json
 import socket
-import urlparse
-import urllib
+from urllib.parse import urlparse, urlencode, parse_qs
+import requests
 from Crypto.Cipher import AES
 from Crypto.Hash import SHA
 from Crypto import Random
@@ -49,26 +49,21 @@ class AuthBackend(ModelBackend):
 
 # Handle login requests by sending them off to the main site
 def login(request):
-    if not hasattr(settings, 'PGAUTH_REDIRECT'):
-        # No pgauth installed, so allow local installs.
-        from django.contrib.auth.views import login
-        return login(request, template_name='admin.html')
-
     if 'next' in request.GET:
         # Put together an url-encoded dict of parameters we're getting back,
         # including a small nonce at the beginning to make sure it doesn't
         # encrypt the same way every time.
-        s = "t=%s&%s" % (int(time.time()), urllib.urlencode({'r': request.GET['next']}))
+        s = "t=%s&%s" % (int(time.time()), urlencode({'r': request.GET['next']}))
         # Now encrypt it
         r = Random.new()
         iv = r.read(16)
-        encryptor = AES.new(SHA.new(settings.SECRET_KEY).digest()[:16], AES.MODE_CBC, iv)
+        encryptor = AES.new(SHA.new(settings.SECRET_KEY.encode('ascii')).digest()[:16], AES.MODE_CBC, iv)
         cipher = encryptor.encrypt(s + ' ' * (16 - (len(s) % 16)))  # pad to 16 bytes
 
         return HttpResponseRedirect("%s?d=%s$%s" % (
             settings.PGAUTH_REDIRECT,
-            base64.b64encode(iv, "-_"),
-            base64.b64encode(cipher, "-_"),
+            base64.b64encode(iv, b"-_").decode('utf8'),
+            base64.b64encode(cipher, b"-_").decode('utf8'),
         ))
     else:
         return HttpResponseRedirect(settings.PGAUTH_REDIRECT)
@@ -89,7 +84,7 @@ def auth_receive(request):
         # This was a logout request
         return HttpResponseRedirect('/')
 
-    if 'i' not in request:
+    if 'i' not in request.GET:
         return HttpResponse("Missing IV in url!", status=400)
     if 'd' not in request.GET:
         return HttpResponse("Missing data in url!", status=400)
@@ -98,11 +93,11 @@ def auth_receive(request):
     decryptor = AES.new(base64.b64decode(settings.PGAUTH_KEY),
                         AES.MODE_CBC,
                         base64.b64decode(str(request.GET['i']), "-_"))
-    s = decryptor.decrypt(base64.b64decode(str(request.GET['d']), "-_")).rstrip(')
+    s = decryptor.decrypt(base64.b64decode(str(request.GET['d']), "-_")).rstrip(b' ').decode('utf8')
 
     # Now un-urlencode it
     try:
-        data = urlparse.parse_qs(s, strict_parsing=True)
+        data = parse_qs(s, strict_parsing=True)
     except ValueError:
         return HttpResponse("Invalid encrypted data received.", status=400)
 
@@ -145,18 +140,6 @@ for you.
 We apologize for the inconvenience.
 """ % (data['e'][0], data['u'][0]), content_type='text/plain')
 
-        if hasattr(settings, 'PGAUTH_CREATEUSER_CALLBACK'):
-            res = getattr(settings, 'PGAUTH_CREATEUSER_CALLBACK')(
-                data['u'][0],
-                data['e'][0],
-                ['f'][0],
-                data['l'][0],
-            )
-            # If anything is returned, we'll return that as our result.
-            # If None is returned, it means go ahead and create the user.
-            if res:
-                return res
-
         user = User(username=data['u'][0],
                     first_name=data['f'][0],
                     last_name=data['l'][0],
@@ -175,12 +158,12 @@ We apologize for the inconvenience.
     # redirect the user.
     if 'd' in data:
         (ivs, datas) = data['d'][0].split('$')
-        decryptor = AES.new(SHA.new(settings.SECRET_KEY).digest()[:16],
+        decryptor = AES.new(SHA.new(settings.SECRET_KEY.encode('ascii')).digest()[:16],
                             AES.MODE_CBC,
-                            base64.b64decode(ivs, "-_"))
-        s = decryptor.decrypt(base64.b64decode(datas, "-_")).rstrip(')
+                            base64.b64decode(ivs, b"-_"))
+        s = decryptor.decrypt(base64.b64decode(datas, "-_")).rstrip(b' ').decode('utf8')
         try:
-            rdata = urlparse.parse_qs(s, strict_parsing=True)
+            rdata = parse_qs(s, strict_parsing=True)
         except ValueError:
             return HttpResponse("Invalid encrypted data received.", status=400)
         if 'r' in rdata:
@@ -200,7 +183,7 @@ We apologize for the inconvenience.
 # Unlike the authentication, searching does not involve the browser - we just make
 # a direct http call.
 def user_search(searchterm=None, userid=None):
-    # If upstream isn't responding quickly, it's not going to respond at all, and
+    # If upsteam isn't responding quickly, it's not going to respond at all, and
     # 10 seconds is already quite long.
     socket.setdefaulttimeout(10)
     if userid:
@@ -208,18 +191,20 @@ def user_search(searchterm=None, userid=None):
     else:
         q = {'s': searchterm}
 
-    u = urllib.urlopen('%ssearch/?%s' % (
-        settings.PGAUTH_REDIRECT,
-        urllib.urlencode(q),
-    ))
-    (ivs, datas) = u.read().split('&')
-    u.close()
+    r = requests.get(
+        '{0}search/'.format(settings.PGAUTH_REDIRECT),
+        params=q,
+    )
+    if r.status_code != 200:
+        return []
+
+    (ivs, datas) = r.text.encode('utf8').split(b'&')
 
     # Decryption time
     decryptor = AES.new(base64.b64decode(settings.PGAUTH_KEY),
                         AES.MODE_CBC,
                         base64.b64decode(ivs, "-_"))
-    s = decryptor.decrypt(base64.b64decode(datas, "-_")).rstrip(')
+    s = decryptor.decrypt(base64.b64decode(datas, "-_")).rstrip(b' ').decode('utf8')
     j = json.loads(s)
 
     return j