1 #!/usr/bin/env python 2 3 "Login redirection." 4 5 from WebStack.Helpers.Auth import get_token 6 7 class LoginRedirectResource: 8 9 "A resource redirecting to a login URL." 10 11 def __init__(self, login_url, app_url, resource, authenticator, anonymous_parameter_name=None): 12 13 """ 14 Initialise the resource with a 'login_url', an 'app_url' where the 'resource' for 15 the application being protected should be reachable, and an 'authenticator'. 16 17 If the optional 'anonymous_parameter_name' is set, clients providing a parameter 18 of that name in the URL will have that parameter sent specially to the login 19 application. 20 """ 21 22 self.login_url = login_url 23 self.app_url = app_url 24 self.resource = resource 25 self.authenticator = authenticator 26 self.anonymous_parameter_name = anonymous_parameter_name 27 28 def respond(self, trans): 29 30 # Check the authentication details with the specified authenticator. 31 32 if self.authenticator.authenticate(trans): 33 self.resource.respond(trans) 34 else: 35 # Define anonymous mode, if appropriate. 36 37 fields_path = trans.get_fields_from_path() 38 39 if self.anonymous_parameter_name is not None and fields_path.has_key(self.anonymous_parameter_name): 40 anonymous_parameter = "%s=%s&" % (self.anonymous_parameter_name, fields_path[self.anonymous_parameter_name][0]) 41 else: 42 anonymous_parameter = "" 43 44 # Redirect to the login URL. 45 46 trans.set_header_value("Location", "%s?%sredirect=%s%s" % ( 47 self.login_url, anonymous_parameter, self.app_url, self._encode(trans.get_path())) 48 ) 49 trans.set_response_code(307) 50 51 def _encode(self, url): 52 53 "Encode the given 'url' for redirection purposes." 54 55 return url.replace("?", "%3f").replace("&", "%26") 56 57 class LoginRedirectAuthenticator: 58 59 """ 60 An authenticator which verifies the credentials provided in a special login cookie. 61 """ 62 63 def __init__(self, secret_key, cookie_name=None): 64 65 "Initialise the authenticator with a 'secret_key' and an optional 'cookie_name'." 66 67 self.secret_key = secret_key 68 self.cookie_name = cookie_name or "LoginAuthenticator" 69 70 def authenticate(self, trans): 71 72 "Authenticate the originator of 'trans', updating the object if successful." 73 74 cookie = trans.get_cookie(self.cookie_name) 75 if cookie is None or cookie.value is None: 76 return 0 77 78 # Test the token from the cookie against a recreated token using the 79 # given information. 80 81 username, code = cookie.value.split(":") 82 if cookie.value == get_token(username, self.secret_key): 83 84 # Update the transaction with the user details. 85 86 trans.set_user(username) 87 return 1 88 else: 89 return 0 90 91 # vim: tabstop=4 expandtab shiftwidth=4