def test_change_primary_method_to_inactive(active_user_with_email_otp):
    client = APIClient()
    first_step = login(active_user_with_email_otp)
    first_primary_method = \
        active_user_with_email_otp.mfa_methods.filter(
            is_primary=True,
        )[0]
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/mfa/change-primary-method/',
        data={
            'method': 'sms',
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    error_code = 'missing_method'
    assert response.status_code == 400
    assert response.data.get('non_field_errors')[0].code == error_code
def test_user_with_many_methods(active_user_with_many_otp_methods):
    client = APIClient()

    initial_active_methods_count = active_user_with_many_otp_methods.mfa_methods.filter(
        is_active=True).count()

    first_step = login(active_user_with_many_otp_methods)
    primary_method = active_user_with_many_otp_methods.mfa_methods.filter(
        is_primary=True, )
    # As user has several methods get first and get sure only 1 is primary
    assert len(primary_method) == 1

    secret = primary_method[0].secret
    second_step_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(secret),
        },
        format='json',
    )
    # Log in the user in the second step and make sure it is correct
    assert second_step_response.status_code == 200

    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(second_step_response)))
    active_methods_response = client.get(
        path='/auth/mfa/user-active-methods/', )

    # This user should have 3 methods, so we check that return has 3 methods
    assert len(active_methods_response.data) == initial_active_methods_count
Exemple #3
0
def test_backup_codes_regeneration(active_user_with_backup_codes):
    client = APIClient()
    first_step = login(active_user_with_backup_codes)
    first_primary_method = active_user_with_backup_codes.mfa_methods.first()
    old_backup_codes = first_primary_method.backup_codes
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/email/codes/regenerate/',
        data={
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    new_backup_codes = \
        active_user_with_backup_codes.mfa_methods.first().backup_codes
    assert response.status_code == 200
    assert old_backup_codes != new_backup_codes
def test_second_method_activation(active_user_with_email_otp):
    client = APIClient()
    first_step = login(active_user_with_email_otp)
    secret = active_user_with_email_otp.mfa_methods.first().secret
    response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(secret),
        },
        format='json',
    )
    assert response.status_code == 200
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(response)))

    # This user should have 1 methods, so we check that it has 1 methods.
    assert len(active_user_with_email_otp.mfa_methods.all()) == 1
    try:
        response = client.post(
            path='/auth/sms/activate/',
            data={
                'phone_number': '555-555-555',
            },
            format='json',
        )
    except (TwilioRestException, TwilioException):
        # twilio rises this exception in test, but the new mfa_method is
        # created anyway.
        pass

    # Now we check that the user has a new method after the activation.
    assert len(active_user_with_email_otp.mfa_methods.all()) == 2
def test_second_method_activation_already_active(active_user_with_email_otp):
    client = APIClient()
    first_step = login(active_user_with_email_otp)
    secret = active_user_with_email_otp.mfa_methods.first().secret
    response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(secret),
        },
        format='json',
    )
    assert response.status_code == 200
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(response)))

    # This user should have 1 methods, so we check that it has 1 methods.
    assert len(active_user_with_email_otp.mfa_methods.all()) == 1
    response = client.post(
        path='/auth/email/activate/',
        format='json',
    )
    error_msg = 'MFA method already active.'
    assert response.status_code == 400
    assert response.data.get('error') == error_msg
def test_backup_codes_regeneration_disabled_method(
    active_user_with_many_otp_methods, ):
    client = APIClient()
    first_step = login(active_user_with_many_otp_methods)
    first_primary_method = active_user_with_many_otp_methods.mfa_methods.filter(
        is_primary=True, )[0]
    sms_method = active_user_with_many_otp_methods.mfa_methods.get(
        name='sms', )
    sms_method.is_active = False
    sms_method.save()
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/sms/codes/regenerate/',
        format='json',
    )
    error_msg = 'Method is disabled.'
    assert response.status_code == 400
    assert response.data.get('error') == error_msg
def test_request_codes(active_user_with_email_otp):
    client = APIClient()
    first_step = login(active_user_with_email_otp)
    first_primary_method = active_user_with_email_otp.mfa_methods.first()
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))

    response = client.post(
        path='/auth/code/request/',
        data={
            'method': 'email',
        },
        format='json',
    )
    expected_msg = 'Email message with MFA code had been sent.'
    assert response.status_code == 200
    assert response.data.get('message') == expected_msg
def test_change_primary_disabled_method_wrong(active_user):
    client = APIClient()
    login_response = client.post(
        path='/auth/login/',
        data={
            'username': getattr(
                active_user,
                User.USERNAME_FIELD,
            ),
            'password': '******',
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/mfa/change-primary-method/',
        data={
            'method': 'sms',
            'code': 'code',
        },
        format='json',
    )
    error_code = 'not_enabled'
    assert response.status_code == 400
    assert response.data.get('non_field_errors')[0].code == error_code
def test_new_method_after_deactivation_user_doesnt_have_method(
        active_user_with_many_otp_methods):
    client = APIClient()
    first_step = login(active_user_with_many_otp_methods)
    first_primary_method = \
        active_user_with_many_otp_methods.mfa_methods.filter(
            is_primary=True,
        )[0]
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/email/deactivate/',
        data={'new_primary_method': 'test'},
        format='json',
    )

    assert response.status_code == 400
    error_code = 'method_not_registered_for_user'
    assert response.data.get('new_primary_method')[0].code == error_code
def test_change_primary_method_with_backup_code(
    active_user_with_many_otp_methods, ):
    client = APIClient()
    first_step = login(active_user_with_many_otp_methods)
    first_primary_method = \
        active_user_with_many_otp_methods.mfa_methods.filter(
            is_primary=True,
        )[0]
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/mfa/change-primary-method/',
        data={
            'method': 'sms',
            'code': first_primary_method.backup_codes.split(',')[0],
        },
        format='json',
    )
    new_primary_method = active_user_with_many_otp_methods.mfa_methods.filter(
        is_primary=True, )[0]
    assert response.status_code == 200
    assert first_primary_method != new_primary_method
    assert new_primary_method.name == 'sms'
def test_confirm_activation_otp(active_user):
    client = APIClient()
    login_response = login(active_user)
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    client.post(
        path='/auth/email/activate/',
        format='json',
    )
    # Until here only make user create a second step confirmation
    active_user_method = active_user.mfa_methods.first()
    active_user_method.is_primary = True
    active_user_method.is_active = True
    active_user_method.save()
    # We manually activate the method
    first_step = login(active_user)
    secret = active_user.mfa_methods.first().secret
    code = create_otp_code(secret)
    response = client.post(
        path='/auth/email/activate/confirm/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': code,
        },
        format='json',
    )
    # Confirm the response is OK and user gets 5 backup codes
    assert response.status_code == 200
    assert len(response.json().get('backup_codes')) == 5
def test_activation_otp(active_user):
    client = APIClient()
    first_step = login(active_user)
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(first_step)))
    response = client.post(
        path='/auth/email/activate/',
        format='json',
    )
    assert response.status_code == 200
def test_activation_otp_confirm_wrong(active_user):
    client = APIClient()
    first_step = login(active_user)
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(first_step)))
    response = client.post(
        path='/auth/email/activate/',
        format='json',
    )
    response = client.post(
        path='/auth/email/activate/confirm/',
        data={'code': 'test00'},
        format='json',
    )
    assert response.status_code == 400
    error_code = 'code_invalid_or_expired'
    assert error_code == response.data.get('code')[0].code
def test_confirm_activation_otp_with_backup_code(
    active_user_with_backup_codes, ):
    client = APIClient()
    first_step = login(active_user_with_backup_codes)
    backup_code = active_user_with_backup_codes.mfa_methods.first(
    ).backup_codes.split(',')[0]

    response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': backup_code,
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(response)))
    try:
        response = client.post(
            path='/auth/sms/activate/',
            data={
                'phone_number': '555-555-555',
            },
            format='json',
        )
    except (TwilioRestException, TwilioException):
        # twilio rises this exception in test, but the new mfa_method is
        # created anyway.
        pass
    sms_method = active_user_with_backup_codes.mfa_methods.all()[1]
    sms_method.backup_codes = generate_backup_codes()
    sms_method.save()
    backup_code = sms_method.backup_codes.split(',')[0]
    response = client.post(
        path='/auth/sms/activate/confirm/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': backup_code,
        },
        format='json',
    )
    # Confirm the response is OK and user gets 5 backup codes
    assert response.status_code == 200
    assert len(response.json().get('backup_codes')) == 5
Exemple #15
0
def test_add_user_mfa(active_user):
    client = APIClient()
    login_request = login(active_user)
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_request)))
    secret = create_secret()
    response = client.post(
        path='/auth/email/activate/',
        data={
            'secret': secret,
            'code': create_otp_code(secret),
            'user': getattr(
                active_user,
                active_user.USERNAME_FIELD,
            )
        },
        format='json',
    )
    assert response.status_code == 200
def test_deactivation_otp(active_user_with_email_otp):
    client = APIClient()
    first_step = login(active_user_with_email_otp)
    secret = active_user_with_email_otp.mfa_methods.first().secret
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/email/deactivate/',
        format='json',
    )
    assert response.status_code == 204
    assert not active_user_with_email_otp.mfa_methods.first().is_active
def test_request_code_non_existing_method(active_user_with_email_otp):
    client = APIClient()
    first_step = login(active_user_with_email_otp)
    first_primary_method = active_user_with_email_otp.mfa_methods.first()
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(first_primary_method.secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))

    response = client.post(
        path='/auth/code/request/',
        data={
            'method': 'test',
        },
        format='json',
    )
    assert response.status_code == 400
def test_deactivation_otp_already_disabled_method(
    active_user_with_email_and_inactive_other_methods_otp, ):
    client = APIClient()
    first_step = login(active_user_with_email_and_inactive_other_methods_otp)
    secret = active_user_with_email_and_inactive_other_methods_otp.mfa_methods.first(
    ).secret  # noqa
    login_response = client.post(
        path='/auth/login/code/',
        data={
            'token': first_step.data.get('ephemeral_token'),
            'code': create_otp_code(secret),
        },
        format='json',
    )
    client.credentials(HTTP_AUTHORIZATION=header_template.format(
        get_token_from_response(login_response)))
    response = client.post(
        path='/auth/sms/deactivate/',
        format='json',
    )
    msg_error = 'Method already disabled.'
    assert response.status_code == 400
    assert response.data.get('error') == msg_error