Include a timestamp in the authentication token
authorMagnus Hagander <magnus@hagander.net>
Tue, 20 Dec 2011 11:52:32 +0000 (12:52 +0100)
committerMagnus Hagander <magnus@hagander.net>
Thu, 22 Dec 2011 18:25:32 +0000 (19:25 +0100)
This way we can expire a token after e.g. 10 or 30 seconds, making
it impossible to do a replay attack later.

docs/authentication.rst
pgweb/account/views.py
tools/communityauth/test_auth.py

index 5e956565b951d6c45b8fd2a2e871c07b9bb40584..be59778d0c6c470b960c3a63a5b87b00f31ac363 100644 (file)
@@ -74,6 +74,10 @@ The flow of an authentication in the 2.0 system is fairly simple:
      The email address of the user logged in
    su
      The suburl to redirect to (optional)
+   t
+     The timestamp of the authentication, in seconds-since-epoch. This
+     should be validated against the current time, and authentication
+     tokens older than e.g. 10 seconds should be refused.
 
 #. This dictionary of information is then URL-encoded.
 #. The resulting URL-encoded string is padded with spaces to an even
index b20e7dbdbb97f15d5d61bddde5334ce444ec5bb0..d923c7a65056cdfe91e14b54018fdeab1b003d7e 100644 (file)
@@ -11,6 +11,7 @@ import base64
 import urllib
 from Crypto.Cipher import AES
 from Crypto import Random
+import time
 
 from pgweb.util.decorators import ssl_required
 from pgweb.util.contexts import NavContext
@@ -211,8 +212,9 @@ def communityauth(request, siteid):
        if su:
                info['su'] = request.GET['su']
 
-       # URL-encode the structure
-       s = urllib.urlencode(info)
+       # Turn this into an URL. Make sure the timestamp is always first, that makes
+       # the first block more random..
+       s = "t=%s&%s" % (int(time.time()), urllib.urlencode(info))
 
        # Encrypt it with the shared key (and IV!)
        r = Random.new()
index 792f053f8fb1d26cecc399d68c86a0042eb45293..cefc063598e011b9a53f360177db4a470109674a 100755 (executable)
@@ -10,6 +10,7 @@ from Crypto import Random
 from Crypto.Cipher import AES
 from urllib import quote_plus
 import base64
+import time
 import urllib
 from optparse import OptionParser
 
@@ -50,7 +51,11 @@ if __name__ == "__main__":
        if options.suburl:
                info['su'] = options.suburl
 
-       s = urllib.urlencode(info)
+       # Turn this into an URL. Make sure the timestamp is always first, that makes
+       # the first block more random..
+       # Since this is a fake authentication, put it 5 minutes into the future to
+       # give more time to copy/paste it.
+       s = "t=%s&%s" % (int(time.time()+300), urllib.urlencode(info))
 
        r = Random.new()
        iv = r.read(16)