Testing

class keg_auth.testing.AuthAttemptTests

Tests to verify that automated attempt logging/blocking works as intended. These tests are included in the AuthTests class and are intended to be used in target applications to verify customization hasn’t broken basic KegAuth functionality.

test_forgot_attempts_blocked(limit, timespan, lockout)

Test that forgot attempts get blocked after reaching the failed forgot attempt limit. forgot attempts after the lockout period has passed (since the failed attempt that caused the lockout) should not be blocked.

test_forgot_attempts_not_blocked()

Test that we do not block any attempts with missing attempt entity.

test_login_attempts_blocked(limit, timespan, lockout, create_user, view_config)

Test that login attempts get blocked after reaching the failed login attempt limit. Login attempts after the lockout period has passed (since the failed attempt that caused the lockout) should not be blocked.

test_login_attempts_blocked_but_not_configured(_)

Test that we check for the registered attempt entity when limiting is enabled.

test_login_attempts_blocked_by_ip(limit, timespan, lockout)

Test that login attempts get blocked for an IP address

test_login_attempts_not_blocked()

Test that we do not block any attempts with missing attempt entity.

test_reset_pw_attempts_blocked(limit, timespan, lockout)

Test that login attempts get blocked after reaching the failed login attempt limit. Login attempts after the lockout period has passed (since the failed attempt that caused the lockout) should not be blocked.

test_successful_forgot_resets_attempt_counter(limit, timespan, lockout)

Test that several failed forgots before a successful forgot do not count towards the attempt lockout counter.

test_successful_login_resets_attempt_counter(limit, timespan, lockout)

Test that several failed logins before a successful login do not count towards the attempt lockout counter.

class keg_auth.testing.AuthTestApp(app, **kwargs)

Wrapper of flask_webtest.TestApp that will inject a user into the session.

Pass in a user instance to “log in” the session:

user = User.fake(permissions=[‘auth-manage’, ‘do-something’]) test_app = AuthTestApp(flask.current_app, user=user)

When running integration tests, following the view sequence to log a user in can be quite time-consuming and unnecessary. Login tests can be elsewhere. Once a user is logged in, they are identified by their session_key. So, we simply inject that key in the environment, and then follow the request out to webtest per normal.

class keg_auth.testing.AuthTests

These tests are designed so they can can be imported into an application’s tests and ran to ensure customization of KegAuth hasn’t broken basic functionality.

test_next_parameter_not_open_redirect()

ensure following the “next” parameter doesn’t allow for an open redirect

class keg_auth.testing.ViewTestBase

Simple helper class that will set up Permission tokens as specified, log in a user, and provide the test app client on the class for use in tests.

Usage: permissions class attribute can be scalar or list.

For tests:

  • self.current_user: User instance that is logged in
  • self.client: AuthTestApp instance
classmethod create_user()

Creates a User record for tests. By default, simply calls fake with permissions.

classmethod setup_user()

Hook to do further setup on cls.current_user.

keg_auth.testing.with_crypto_context(field, context=None)

Wrap a test to use a real cryptographic context for a KAPasswordType

Temporarily assign a passlib.context.CryptoContext to a particular entity column.

Parameters:(optional) (context) – passlib.context.CryptoContext to use for this test. The default value is keg_auth.core.DEFAULT_CRYPTO_SCHEMES.

In most situations we don’t want a real crypto scheme to run in the tests, it is slow on entities like Users which have a password. User.fake will generate a value for that instance and then hash which takes a bunch of time. However, when testing certain schemes, it is useful to execute the real behavior instead of the plaintext behaviour.

import bcrypt

bcrypt_context = passlib.context.CryptContext(scheme=['bcrypt'])

@with_crypto_context(ents.User.password, context=bcrypt_context)
def test_with_real_context():
    user = ents.User.fake(password='abc')
    assert bcrypt.checkpw('abc', user.password.hash)