Changeset - 9c2fc1390291
[Not reviewed]
default
0 2 0
Mads Kiilerich - 7 years ago 2019-01-04 03:42:17
mads@kiilerich.com
tests: prepare for adding CSRF protection on login forms

CSRF is about avoiding abuse of credentials by doing things in existing
sessions. The login form does not have any previous credentials, so there is
nothing to abuse and no real need for CSRF protection. But there is still an
unauth session, so we *can* have CSRF protection.

CSRF protection is currently in LoginRequired (which obviously isn't
applied to the login form), but let's prepare for changing that.
2 files changed with 52 insertions and 26 deletions:
0 comments (0 inline, 0 general)
kallithea/tests/base.py
Show inline comments
 
@@ -154,7 +154,8 @@ class TestController(object):
 
        self._logged_username = username
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': username,
 
                                  'password': password})
 
                                  'password': password,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        if 'Invalid username or password' in response.body:
 
            pytest.fail('could not login using %s %s' % (username, password))
kallithea/tests/functional/test_login.py
Show inline comments
 
@@ -31,7 +31,8 @@ class TestLoginController(TestController
 
    def test_login_admin_ok(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': TEST_USER_ADMIN_PASS})
 
                                  'password': TEST_USER_ADMIN_PASS,
 
                                  '_authentication_token': self.authentication_token()})
 
        assert response.status == '302 Found'
 
        self.assert_authenticated_user(response, TEST_USER_ADMIN_LOGIN)
 

	
 
@@ -41,7 +42,8 @@ class TestLoginController(TestController
 
    def test_login_regular_ok(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_REGULAR_LOGIN,
 
                                  'password': TEST_USER_REGULAR_PASS})
 
                                  'password': TEST_USER_REGULAR_PASS,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        assert response.status == '302 Found'
 
        self.assert_authenticated_user(response, TEST_USER_REGULAR_LOGIN)
 
@@ -52,7 +54,8 @@ class TestLoginController(TestController
 
    def test_login_regular_email_ok(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_REGULAR_EMAIL,
 
                                  'password': TEST_USER_REGULAR_PASS})
 
                                  'password': TEST_USER_REGULAR_PASS,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        assert response.status == '302 Found'
 
        self.assert_authenticated_user(response, TEST_USER_REGULAR_LOGIN)
 
@@ -65,7 +68,8 @@ class TestLoginController(TestController
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=test_came_from),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': TEST_USER_ADMIN_PASS})
 
                                  'password': TEST_USER_ADMIN_PASS,
 
                                  '_authentication_token': self.authentication_token()})
 
        assert response.status == '302 Found'
 
        response = response.follow()
 

	
 
@@ -76,7 +80,8 @@ class TestLoginController(TestController
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_REGULAR_LOGIN,
 
                                  'password': TEST_USER_REGULAR_PASS,
 
                                  'remember': False})
 
                                  'remember': False,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        assert 'Set-Cookie' in response.headers
 
        for cookie in response.headers.getall('Set-Cookie'):
 
@@ -86,7 +91,8 @@ class TestLoginController(TestController
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_REGULAR_LOGIN,
 
                                  'password': TEST_USER_REGULAR_PASS,
 
                                  'remember': True})
 
                                  'remember': True,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        assert 'Set-Cookie' in response.headers
 
        for cookie in response.headers.getall('Set-Cookie'):
 
@@ -95,7 +101,8 @@ class TestLoginController(TestController
 
    def test_logout(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_REGULAR_LOGIN,
 
                                  'password': TEST_USER_REGULAR_PASS})
 
                                  'password': TEST_USER_REGULAR_PASS,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        # Verify that a login session has been established.
 
        response = self.app.get(url(controller='login', action='index'))
 
@@ -123,13 +130,15 @@ class TestLoginController(TestController
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=url_came_from),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': TEST_USER_ADMIN_PASS},
 
                                  'password': TEST_USER_ADMIN_PASS,
 
                                  '_authentication_token': self.authentication_token()},
 
                                 status=400)
 

	
 
    def test_login_short_password(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': 'as'})
 
                                  'password': 'as',
 
                                  '_authentication_token': self.authentication_token()})
 
        assert response.status == '200 OK'
 

	
 
        response.mustcontain('Enter 3 characters or more')
 
@@ -137,14 +146,16 @@ class TestLoginController(TestController
 
    def test_login_wrong_username_password(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': 'error',
 
                                  'password': 'test12'})
 
                                  'password': 'test12',
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        response.mustcontain('Invalid username or password')
 

	
 
    def test_login_non_ascii(self):
 
        response = self.app.post(url(controller='login', action='index'),
 
                                 {'username': TEST_USER_REGULAR_LOGIN,
 
                                  'password': 'blåbærgrød'})
 
                                  'password': 'blåbærgrød',
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        response.mustcontain('>Invalid username or password<')
 

	
 
@@ -187,7 +198,8 @@ class TestLoginController(TestController
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=url('/_admin/users', **args)),
 
                                 {'username': TEST_USER_ADMIN_LOGIN,
 
                                  'password': TEST_USER_ADMIN_PASS})
 
                                  'password': TEST_USER_ADMIN_PASS,
 
                                  '_authentication_token': self.authentication_token()})
 
        assert response.status == '302 Found'
 
        for encoded in args_encoded:
 
            assert encoded in response.location
 
@@ -201,7 +213,8 @@ class TestLoginController(TestController
 
        response = self.app.post(url(controller='login', action='index',
 
                                     came_from=url('/_admin/users', **args)),
 
                                 {'username': 'error',
 
                                  'password': 'test12'})
 
                                  'password': 'test12',
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        response.mustcontain('Invalid username or password')
 
        came_from = urlparse.parse_qs(urlparse.urlparse(response.form.action).query)['came_from'][0]
 
@@ -223,7 +236,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'test12',
 
                                             'email': 'goodmail@example.com',
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 

	
 
        with test_context(self.app):
 
            msg = validators.ValidUsername()._messages['username_exists']
 
@@ -237,7 +251,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'test12',
 
                                             'email': TEST_USER_ADMIN_EMAIL,
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 

	
 
        with test_context(self.app):
 
            msg = validators.UniqSystemEmail()()._messages['email_taken']
 
@@ -250,7 +265,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'test12',
 
                                             'email': TEST_USER_ADMIN_EMAIL.title(),
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 
        with test_context(self.app):
 
            msg = validators.UniqSystemEmail()()._messages['email_taken']
 
        response.mustcontain(msg)
 
@@ -262,7 +278,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'test',
 
                                             'email': 'goodmailm',
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 
        assert response.status == '200 OK'
 
        response.mustcontain('An email address must contain a single @')
 
        response.mustcontain('Enter a value 6 characters long or more')
 
@@ -274,7 +291,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'test12',
 
                                             'email': 'goodmailm',
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 

	
 
        response.mustcontain('An email address must contain a single @')
 
        response.mustcontain('Username may only contain '
 
@@ -290,7 +308,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'test12',
 
                                             'email': 'goodmailm',
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 

	
 
        response.mustcontain('An email address must contain a single @')
 
        with test_context(self.app):
 
@@ -305,7 +324,8 @@ class TestLoginController(TestController
 
                                         'password_confirmation': 'ąćźżąśśśś',
 
                                         'email': 'goodmailm@test.plx',
 
                                         'firstname': 'test',
 
                                         'lastname': 'test'})
 
                                         'lastname': 'test',
 
                                         '_authentication_token': self.authentication_token()})
 

	
 
        with test_context(self.app):
 
            msg = validators.ValidPassword()._messages['invalid_password']
 
@@ -318,7 +338,8 @@ class TestLoginController(TestController
 
                                             'password_confirmation': 'qwe123',
 
                                             'email': 'goodmailm@test.plxa',
 
                                             'firstname': 'test',
 
                                             'lastname': 'test'})
 
                                             'lastname': 'test',
 
                                             '_authentication_token': self.authentication_token()})
 
        with test_context(self.app):
 
            msg = validators.ValidPasswordsMatch('password', 'password_confirmation')._messages['password_mismatch']
 
        response.mustcontain(msg)
 
@@ -337,7 +358,8 @@ class TestLoginController(TestController
 
                                             'email': email,
 
                                             'firstname': name,
 
                                             'lastname': lastname,
 
                                             'admin': True})  # This should be overridden
 
                                             'admin': True,
 
                                             '_authentication_token': self.authentication_token()})  # This should be overridden
 
        assert response.status == '302 Found'
 
        self.checkSessionFlash(response, 'You have successfully registered with Kallithea')
 

	
 
@@ -358,8 +380,8 @@ class TestLoginController(TestController
 
        bad_email = 'username%wrongmail.org'
 
        response = self.app.post(
 
                        url(controller='login', action='password_reset'),
 
                            {'email': bad_email, }
 
        )
 
                            {'email': bad_email,
 
                             '_authentication_token': self.authentication_token()})
 

	
 
        response.mustcontain('An email address must contain a single @')
 

	
 
@@ -387,7 +409,8 @@ class TestLoginController(TestController
 

	
 
        response = self.app.post(url(controller='login',
 
                                     action='password_reset'),
 
                                 {'email': email, })
 
                                 {'email': email,
 
                                  '_authentication_token': self.authentication_token()})
 

	
 
        self.checkSessionFlash(response, 'A password reset confirmation code has been sent')
 

	
 
@@ -404,6 +427,7 @@ class TestLoginController(TestController
 
                                  'password': "p@ssw0rd",
 
                                  'password_confirm': "p@ssw0rd",
 
                                  'token': token,
 
                                  '_authentication_token': self.authentication_token(),
 
                                 })
 
        assert response.status == '200 OK'
 
        response.mustcontain('Invalid password reset token')
 
@@ -431,6 +455,7 @@ class TestLoginController(TestController
 
                                  'password': "p@ssw0rd",
 
                                  'password_confirm': "p@ssw0rd",
 
                                  'token': token,
 
                                  '_authentication_token': self.authentication_token(),
 
                                 })
 
        assert response.status == '302 Found'
 
        self.checkSessionFlash(response, 'Successfully updated password')
0 comments (0 inline, 0 general)