diff --git a/docs/authentication.rst b/docs/authentication.rst index 5e956565..be59778d 100644 --- a/docs/authentication.rst +++ b/docs/authentication.rst @@ -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 diff --git a/pgweb/account/views.py b/pgweb/account/views.py index b20e7dbd..d923c7a6 100644 --- a/pgweb/account/views.py +++ b/pgweb/account/views.py @@ -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() diff --git a/tools/communityauth/test_auth.py b/tools/communityauth/test_auth.py index 792f053f..cefc0635 100755 --- a/tools/communityauth/test_auth.py +++ b/tools/communityauth/test_auth.py @@ -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)