def __call__(self, environ, start_response): ''' This method is called for each request. It looks for a user-supplied CSRF token in the GET/POST parameters, and compares it to the token attached to ``environ['repoze.who.identity']['_csrf_token']``. If it does not match, or if a token is not provided, it will remove the user from the ``environ``, based on the ``clear_env`` setting. ''' request = Request(environ) log.debug( b_('CSRFProtectionMiddleware(%(r_path)s)') % {'r_path': to_bytes(request.path)}) token = environ.get('repoze.who.identity', {}).get(self.csrf_token_id) csrf_token = environ.get(self.token_env) if token and csrf_token and token == csrf_token: log.debug(b_('User supplied CSRF token matches environ!')) else: if not environ.get(self.auth_state): log.debug(b_('Clearing identity')) self._clean_environ(environ) if 'repoze.who.identity' not in environ: environ['repoze.who.identity'] = Bunch() if 'repoze.who.logins' not in environ: # For compatibility with friendlyform environ['repoze.who.logins'] = 0 if csrf_token: log.warning( b_('Invalid CSRF token. User supplied' ' (%(u_token)s) does not match what\'s in our' ' environ (%(e_token)s)') % { 'u_token': to_bytes(csrf_token), 'e_token': to_bytes(token) }) response = request.get_response(self.application) if environ.get(self.auth_state): log.debug(b_('CSRF_AUTH_STATE; rewriting headers')) token = environ.get('repoze.who.identity', {})\ .get(self.csrf_token_id) loc = update_qs(response.location, {self.csrf_token_id: str(token)}) response.location = loc log.debug( b_('response.location = %(r_loc)s') % {'r_loc': to_bytes(response.location)}) environ[self.auth_state] = None return response(environ, start_response)
def __call__(self, environ, start_response): ''' This method is called for each request. It looks for a user-supplied CSRF token in the GET/POST parameters, and compares it to the token attached to ``environ['repoze.who.identity']['_csrf_token']``. If it does not match, or if a token is not provided, it will remove the user from the ``environ``, based on the ``clear_env`` setting. ''' request = Request(environ) log.debug('CSRFProtectionMiddleware(%(r_path)s)' % {'r_path': to_bytes(request.path)}) token = environ.get('repoze.who.identity', {}).get(self.csrf_token_id) csrf_token = environ.get(self.token_env) if token and csrf_token and token == csrf_token: log.debug('User supplied CSRF token matches environ!') else: if not environ.get(self.auth_state): log.debug('Clearing identity') self._clean_environ(environ) if 'repoze.who.identity' not in environ: environ['repoze.who.identity'] = Bunch() if 'repoze.who.logins' not in environ: # For compatibility with friendlyform environ['repoze.who.logins'] = 0 if csrf_token: log.warning('Invalid CSRF token. User supplied' ' (%(u_token)s) does not match what\'s in our' ' environ (%(e_token)s)' % {'u_token': to_bytes(csrf_token), 'e_token': to_bytes(token)}) response = request.get_response(self.application) if environ.get(self.auth_state): log.debug('CSRF_AUTH_STATE; rewriting headers') token = environ.get('repoze.who.identity', {})\ .get(self.csrf_token_id) loc = update_qs( response.location, {self.csrf_token_id: str(token)}) response.location = loc log.debug('response.location = %(r_loc)s' % {'r_loc': to_bytes(response.location)}) environ[self.auth_state] = None return response(environ, start_response)
def add_metadata(self, environ, identity): request = Request(environ) log.debug( b_('CSRFMetadataProvider.add_metadata(%(r_path)s)') % {'r_path': to_bytes(request.path)}) session_id = environ.get(self.auth_session_id) if not session_id: session_id = request.cookies.get(self.session_cookie) log.debug(b_('session_id = %(s_id)r') % {'s_id': to_bytes(session_id)}) if session_id and session_id != 'Set-Cookie:': environ[self.auth_session_id] = session_id token = sha1(session_id).hexdigest() identity.update({self.csrf_token_id: token}) log.debug(b_('Identity updated with CSRF token')) path = self.strip_script(environ, request.path) if path == self.login_handler: log.debug(b_('Setting CSRF_AUTH_STATE')) environ[self.auth_state] = True environ[self.token_env] = token else: environ[self.token_env] = self.extract_csrf_token(request) app = environ.get('repoze.who.application') if app: # This occurs during login in some application configurations if isinstance(app, HTTPFound) and environ.get(self.auth_state): log.debug( b_('Got HTTPFound(302) from' ' repoze.who.application')) # What possessed people to make this a string or # a function? location = app.location if hasattr(location, '__call__'): location = location() loc = update_qs(location, {self.csrf_token_id: str(token)}) headers = app.headers.items() replace_header(headers, 'location', loc) app.headers = ResponseHeaders(headers) log.debug( b_('Altered headers: %(headers)s') % {'headers': to_bytes(app.headers)}) else: log.warning( b_('Invalid session cookie %(s_id)r, not setting CSRF' ' token!') % {'s_id': to_bytes(session_id)})
def add_metadata(self, environ, identity): request = Request(environ) log.debug('CSRFMetadataProvider.add_metadata(%(r_path)s)' % {'r_path': to_bytes(request.path)}) session_id = environ.get(self.auth_session_id) if not session_id: session_id = request.cookies.get(self.session_cookie) log.debug('session_id = %(s_id)r' % {'s_id': to_bytes(session_id)}) if session_id and session_id != 'Set-Cookie:': environ[self.auth_session_id] = session_id token = sha1(session_id).hexdigest() identity.update({self.csrf_token_id: token}) log.debug('Identity updated with CSRF token') path = self.strip_script(environ, request.path) if path == self.login_handler: log.debug('Setting CSRF_AUTH_STATE') environ[self.auth_state] = True environ[self.token_env] = token else: environ[self.token_env] = self.extract_csrf_token(request) app = environ.get('repoze.who.application') if app: # This occurs during login in some application configurations if isinstance(app, HTTPFound) and environ.get(self.auth_state): log.debug('Got HTTPFound(302) from' ' repoze.who.application') # What possessed people to make this a string or # a function? location = app.location if hasattr(location, '__call__'): location = location() loc = update_qs(location, {self.csrf_token_id: str(token)}) headers = app.headers.items() replace_header(headers, 'location', loc) app.headers = ResponseHeaders(headers) log.debug('Altered headers: %(headers)s' % { 'headers': to_bytes(app.headers)}) else: log.warning('Invalid session cookie %(s_id)r, not setting CSRF' ' token!' % {'s_id': to_bytes(session_id)})
def add_metadata(self, environ, identity): request = Request(environ) log.debug(_('CSRFMetadataProvider.add_metadata(%(r_path)s)') % {'r_path': request.path}) session_id = environ.get(self.auth_session_id) if not session_id: session_id = request.cookies.get(self.session_cookie) log.debug(_('session_id = %(s_id)r') % {'s_id': session_id}) if session_id and session_id != 'Set-Cookie:': token = sha1(session_id).hexdigest() identity.update({self.csrf_token_id: token}) log.debug(_('Identity updated with CSRF token')) path = self.strip_script(environ, request.path) if path == self.login_handler: log.debug(_('Setting CSRF_AUTH_STATE')) environ[self.auth_state] = True environ[self.token_env] = token else: environ[self.token_env] = self.extract_csrf_token(request) app = environ.get('repoze.who.application') if app: # This occurs during login in some application configurations if isinstance(app, HTTPFound) and environ.get(self.auth_state): log.debug(_('Got HTTPFound(302) from' ' repoze.who.application')) loc = update_qs(app.location(), {self.csrf_token_id: str(token)}) replace_header(app.headers, 'location', loc) log.debug(_('Altered headers: %(headers)s') % {'headers': str(app.headers)}) else: log.warning(_('Invalid session cookie %(s_id)r, not setting CSRF' ' token!') % {'s_id': session_id})
def test_simple_without_overwrite_and_same(self): original = base + "?foo=yes" expected = base + "?foo=yes&foo=yes" params = dict(foo="yes") actual = update_qs(original, params, overwrite=False) self.assertEquals(actual, expected)
def test_simple_with_tuples(self): original = base expected = base + "?foo=yes" params = [('foo', 'yes')] actual = update_qs(original, params) self.assertEquals(actual, expected)
def test_simple_idempotence(self): original = base + "?foo=yes" expected = base + "?foo=yes" params = dict(foo="yes") actual = update_qs(original, params) self.assertEquals(actual, expected)
def test_simple_with_overwrite(self): original = base + "?foo=yes" expected = base + "?foo=no" params = dict(foo="no") actual = update_qs(original, params) self.assertEquals(actual, expected)
def test_simple_add(self): original = base expected = base + "?foo=yes" params = dict(foo="yes") actual = update_qs(original, params) self.assertEqual(actual, expected)