def inbound(request): """Authenticate from a cookie or an API key in basic auth. """ user = None if 'Authorization' in request.headers: header = request.headers['authorization'] if header.startswith('Basic '): creds = header[len('Basic '):].decode('base64') token, ignored = creds.split(':') user = User.from_api_key(token) # We don't require CSRF if they basically authenticated. csrf_token = csrf._get_new_csrf_key() request.headers.cookie['csrf_token'] = csrf_token request.headers['X-CSRF-TOKEN'] = csrf_token if 'Referer' not in request.headers: request.headers['Referer'] = \ 'https://%s/' % csrf._get_host(request) elif 'session' in request.headers.cookie: token = request.headers.cookie['session'].value user = User.from_session_token(token) if user is None: user = User() request.context['user'] = user
def outbound(response): if 'user' in response.request.context: user = response.request.context['user'] if not isinstance(user, User): raise Response(400, "If you define 'user' in a simplate it has to " "be a User instance.") else: user = User() if user.ANON: # user is anonymous if 'session' not in response.request.headers.cookie: # no cookie in the request, don't set one on response return else: # expired cookie in the request, instruct browser to delete it response.headers.cookie['session'] = '' expires = 0 else: # user is authenticated response.headers['Expires'] = BEGINNING_OF_EPOCH # don't cache response.headers.cookie['session'] = user.participant.session_token expires = time.time() + TIMEOUT user.keep_signed_in_until(expires) cookie = response.headers.cookie['session'] # I am not setting domain, because it is supposed to default to what we # want: the domain of the object requested. #cookie['domain'] cookie['path'] = '/' cookie['expires'] = rfc822.formatdate(expires) cookie['httponly'] = "Yes, please." if gittip.canonical_scheme == 'https': cookie['secure'] = "Yes, please."
def outbound(response): if 'user' in response.request.context: user = response.request.context['user'] if not isinstance(user, User): raise Response( 400, "If you define 'user' in a simplate it has to " "be a User instance.") else: user = User() if user.ANON: # user is anonymous if 'session' not in response.request.headers.cookie: # no cookie in the request, don't set one on response return else: # expired cookie in the request, instruct browser to delete it response.headers.cookie['session'] = '' expires = 0 else: # user is authenticated response.headers['Expires'] = BEGINNING_OF_EPOCH # don't cache response.headers.cookie['session'] = user.participant.session_token expires = time.time() + TIMEOUT user.keep_signed_in_until(expires) cookie = response.headers.cookie['session'] # I am not setting domain, because it is supposed to default to what we # want: the domain of the object requested. #cookie['domain'] cookie['path'] = '/' cookie['expires'] = rfc822.formatdate(expires) cookie['httponly'] = "Yes, please."
def test_user_can_be_loaded_from_session_token(self): self.make_participant('alice') user = User.from_username('alice') user.sign_in() token = user.participant.session_token actual = User.from_session_token(token).participant.username assert actual == 'alice'
def test_user_from_expired_session_is_anonymous(self): self.make_participant('alice') user = User.from_username('alice') user.sign_in(SimpleCookie()) token = user.participant.session_token user.participant.set_session_expires(utcnow()) user = User.from_session_token(token) assert user.ANON
def outbound(request, response): if request.line.uri.startswith('/assets/'): return response.headers['Expires'] = BEGINNING_OF_EPOCH # don't cache if SESSION in request.headers.cookie: user = request.context.get('user') or User() if not user.ANON: user.keep_signed_in(response.headers.cookie)
def serve_request(path, user=None): """Given an URL path, return response. """ request = StubRequest(path) request.website = test_website if user is not None: user = User.from_username(user) # Note that Cookie needs a bytestring. request.headers.cookie[str('session')] = user.session_token response = test_website.handle_safely(request) return response
def test_session_cookie_is_secure_if_it_should_be(self): canonical_scheme = gittip.canonical_scheme gittip.canonical_scheme = 'https' try: cookies = SimpleCookie() self.make_participant('alice') user = User.from_username('alice') user.sign_in(cookies) assert '; secure' in cookies[SESSION].output() finally: gittip.canonical_scheme = canonical_scheme
def test_session_is_regularly_refreshed(self): self.make_participant('alice') user = User.from_username('alice') user.sign_in(SimpleCookie()) cookies = SimpleCookie() user.keep_signed_in(cookies) assert SESSION not in cookies cookies = SimpleCookie() expires = user.participant.session_expires user.participant.set_session_expires(expires - SESSION_REFRESH) user.keep_signed_in(cookies) assert SESSION in cookies
def perform_request(self, request, user): request.website = test_website if user is not None: user = User.from_username(user) user.sign_in() # Note that Cookie needs a bytestring. request.headers.cookie[str('session')] = \ user.participant.session_token response = test_website.handle_safely(request) if response.headers.cookie: self.cookies.update(response.headers.cookie) return response
def inbound(request): """Authenticate from a cookie or an API key in basic auth. """ user = None if request.line.uri.startswith("/assets/"): pass elif "Authorization" in request.headers: header = request.headers["authorization"] if header.startswith("Basic "): creds = header[len("Basic ") :].decode("base64") token, ignored = creds.split(":") user = User.from_api_key(token) # We don't require CSRF if they basically authenticated. csrf_token = csrf._get_new_csrf_key() request.headers.cookie["csrf_token"] = csrf_token request.headers["X-CSRF-TOKEN"] = csrf_token if "Referer" not in request.headers: request.headers["Referer"] = "https://%s/" % csrf._get_host(request) elif "session" in request.headers.cookie: token = request.headers.cookie["session"].value user = User.from_session_token(token) request.context["user"] = user or User()
def opt_in(self, desired_username): """Given a desired username, return a User object. """ self.set_is_locked(False) user = User.from_username(self.participant) user.sign_in() assert not user.ANON, self.participant # sanity check if self.is_claimed: newly_claimed = False else: newly_claimed = True user.participant.set_as_claimed() try: user.participant.change_username(desired_username) except ProblemChangingUsername: pass return user, newly_claimed
def build_wsgi_environ(self, *a, **kw): """Extend base class to support authenticating as a certain user. """ # csrf - for both anon and authenticated self.cookie[b'csrf_token'] = b'sotokeny' kw[b'HTTP_X-CSRF-TOKEN'] = b'sotokeny' # user authentication auth_as = kw.pop('auth_as', None) if auth_as is None: if SESSION in self.cookie: del self.cookie[SESSION] else: user = User.from_username(auth_as) user.sign_in(self.cookie) return Client.build_wsgi_environ(self, *a, **kw)
def opt_in(self, desired_username): """Given a desired username, return a User object. """ from gittip.security.user import User self.set_is_locked(False) user = User.from_username(self.participant.username) assert not user.ANON, self.participant # sanity check if self.participant.is_claimed: newly_claimed = False else: newly_claimed = True user.participant.set_as_claimed() try: user.participant.change_username(desired_username) except ProblemChangingUsername: pass if user.participant.is_closed: user.participant.update_is_closed(False) return user, newly_claimed
def outbound(request, response): if request.line.uri.startswith('/assets/'): return response.headers['Expires'] = BEGINNING_OF_EPOCH # don't cache user = request.context.get('user') or User() if not isinstance(user, User): raise Response(500, "If you define 'user' in a simplate it has to " "be a User instance.") if not user.ANON: response.headers.cookie['session'] = user.participant.session_token expires = time.time() + TIMEOUT user.keep_signed_in_until(expires) cookie = response.headers.cookie['session'] cookie['path'] = '/' cookie['expires'] = rfc822.formatdate(expires) cookie['httponly'] = 'Yes, please.' if gittip.canonical_scheme == 'https': cookie['secure'] = 'Yes, please.'
def test_show_as_team_to_non_team_member(self): self.make_participant('alice') self.team.add_member(self.make_participant('bob')) user = User.from_username('alice') assert self.team.show_as_team(user)
def test_user_from_None_session_token_is_anonymous(self): self.make_participant('alice') self.make_participant('bob') user = User.from_session_token(None) assert user.ANON
def test_user_from_bad_session_token_is_anonymous(self): user = User.from_session_token('deadbeef') assert user.ANON
def test_show_plural_no_members_as_team_to_self(self): group = self.make_participant('Group', number='plural') assert group.show_as_team(User.from_username('Group'))
def test_user_from_bad_id_is_anonymous(self): user = User.from_username('deadbeef') assert user.ANON
def test_user_from_None_api_key_is_anonymous(self): self.make_participant('alice') self.make_participant('bob') user = User.from_api_key(None) assert user.ANON
def test_known_user_is_not_admin(self): self.make_participant('alice') alice = User.from_username('alice') assert not alice.ADMIN
def test_username_is_case_insensitive(self): self.make_participant('AlIcE') actual = User.from_username('aLiCe').participant.username_lower assert actual == 'alice'
def test_anonymous_user_is_not_admin(self): user = User() assert not user.ADMIN
def test_signed_out_user_is_anonymous(self): self.make_participant('alice') alice = User.from_username('alice') assert not alice.ANON alice.sign_out() assert alice.ANON
def test_dont_show_plural_no_members_as_team_to_anon(self): group = self.make_participant('Group', number='plural') assert not group.show_as_team(User())
def test_user_from_bad_api_key_is_anonymous(self): user = User.from_api_key('deadbeef') assert user.ANON
def test_admin_user_is_admin(self): self.make_participant('alice', is_admin=True) alice = User.from_username('alice') assert alice.ADMIN
def test_anonymous_user_is_anonymous(self): user = User() assert user.ANON
def test_unreviewed_user_is_not_ANON(self): self.make_participant('alice', is_suspicious=None) alice = User.from_username('alice') assert alice.ANON is False
def test_user_can_be_loaded_from_api_key(self): alice = self.make_participant('alice') api_key = alice.recreate_api_key() actual = User.from_api_key(api_key).participant.username assert actual == 'alice'
def test_whitelisted_user_is_not_ANON(self): self.make_participant('alice', is_suspicious=False) alice = User.from_username('alice') assert alice.ANON is False
def test_suspicious_user_from_username_is_anonymous(self): self.make_participant('alice', is_suspicious=True) user = User.from_username('alice') assert user.ANON
def test_blacklisted_user_is_ANON(self): self.make_participant('alice', is_suspicious=True) alice = User.from_username('alice') assert alice.ANON is True
def test_show_plural_no_members_as_team_to_admin(self): group = self.make_participant('Group', number='plural') self.make_participant('Admin', is_admin=True) assert group.show_as_team(User.from_username('Admin'))
def test_dont_show_plural_no_members_as_team_to_auth(self): group = self.make_participant('Group', number='plural') self.make_participant('alice') assert not group.show_as_team(User.from_username('alice'))