def _basic_auth_login(username, password, request): login_service = request.find_service(IUserService, context=None) breach_service = request.find_service(IPasswordBreachedService, context=None) userid = login_service.find_userid(username) if userid is not None: user = login_service.get_user(userid) is_disabled, disabled_for = login_service.is_disabled(user.id) if is_disabled and disabled_for == DisableReason.CompromisedPassword: # This technically violates the contract a little bit, this function is # meant to return None if the user cannot log in. However we want to present # a different error message than is normal when we're denying the log in # becasue of a compromised password. So to do that, we'll need to raise a # HTTPError that'll ultimately get returned to the client. This is OK to do # here because we've already successfully authenticated the credentials, so # it won't screw up the fall through to other authentication mechanisms # (since we wouldn't have fell through to them anyways). raise _format_exc_status(BasicAuthBreachedPassword(), breach_service.failure_message_plain) elif login_service.check_password( user.id, password, tags=["method:auth", "auth_method:basic"]): if breach_service.check_password( password, tags=["method:auth", "auth_method:basic"]): send_password_compromised_email(request, user) login_service.disable_password( user.id, reason=DisableReason.CompromisedPassword) raise _format_exc_status(BasicAuthBreachedPassword(), breach_service.failure_message_plain) else: login_service.update_user( user.id, last_login=datetime.datetime.utcnow()) return _authenticate(user.id, request)
def _basic_auth_check(username, password, request): request.authentication_method = AuthenticationMethod.BASIC_AUTH # Basic authentication can only be used for uploading if request.matched_route.name not in ["forklift.legacy.file_upload"]: return login_service = request.find_service(IUserService, context=None) breach_service = request.find_service(IPasswordBreachedService, context=None) userid = login_service.find_userid(username) if userid is not None: user = login_service.get_user(userid) is_disabled, disabled_for = login_service.is_disabled(user.id) if is_disabled and disabled_for == DisableReason.CompromisedPassword: # This technically violates the contract a little bit, this function is # meant to return None if the user cannot log in. However we want to present # a different error message than is normal when we're denying the log in # because of a compromised password. So to do that, we'll need to raise a # HTTPError that'll ultimately get returned to the client. This is OK to do # here because we've already successfully authenticated the credentials, so # it won't screw up the fall through to other authentication mechanisms # (since we wouldn't have fell through to them anyways). raise _format_exc_status(BasicAuthBreachedPassword(), breach_service.failure_message_plain) elif login_service.check_password( user.id, password, tags=[ "mechanism:basic_auth", "method:auth", "auth_method:basic" ], ): if breach_service.check_password( password, tags=["method:auth", "auth_method:basic"]): send_password_compromised_email_hibp(request, user) login_service.disable_password( user.id, reason=DisableReason.CompromisedPassword) raise _format_exc_status(BasicAuthBreachedPassword(), breach_service.failure_message_plain) login_service.update_user(user.id, last_login=datetime.datetime.utcnow()) return _authenticate(user.id, request) else: user.record_event( tag="account:login:failure", ip_address=request.remote_addr, additional={ "reason": "invalid_password", "auth_method": "basic" }, ) raise _format_exc_status( BasicAuthFailedPassword(), "Invalid or non-existent authentication information. " "See {projecthelp} for more information.".format( projecthelp=request.help_url(_anchor="invalid-auth")), )
@pytest.mark.parametrize( ("path", "expected"), [("/foo/bar/", True), ("/static/wat/", False), ("/_debug_toolbar/thing/", False)], ) def test_activate_hook(path, expected): request = pretend.stub(path=path) assert config.activate_hook(request) == expected @pytest.mark.parametrize( ("exc_info", "expected"), [ (None, False), ((ValueError, ValueError(), None), True), ((BasicAuthBreachedPassword, BasicAuthBreachedPassword(), None), False), ], ) def test_commit_veto(exc_info, expected): request = pretend.stub(exc_info=exc_info) response = pretend.stub() assert bool(config.commit_veto(request, response)) == expected @pytest.mark.parametrize("route_kw", [None, {}, {"foo": "bar"}]) def test_template_view(route_kw): configobj = pretend.stub( add_route=pretend.call_recorder(lambda *a, **kw: None), add_view=pretend.call_recorder(lambda *a, **kw: None),