Ejemplo n.º 1
0
    def page(self) -> CBORPageResult:
        assert user.id is not None

        if not is_two_factor_login_enabled(user.id):
            raise MKGeneralException(
                _("Two-factor authentication not enabled"))

        data: dict[str, object] = cbor.decode(request.get_data())
        credential_id = data["credentialId"]
        client_data = ClientData(data["clientDataJSON"])
        auth_data = AuthenticatorData(data["authenticatorData"])
        signature = data["signature"]
        logger.debug("ClientData: %r", client_data)
        logger.debug("AuthenticatorData: %r", auth_data)

        make_fido2_server().authenticate_complete(
            session.session_info.webauthn_action_state,
            [
                AttestedCredentialData.unpack_from(v["credential_data"])[0]
                for v in load_two_factor_credentials(user.id)
                ["webauthn_credentials"].values()
            ],
            credential_id,
            client_data,
            auth_data,
            signature,
        )
        session.session_info.webauthn_action_state = None
        set_two_factor_completed()
        return {"status": "OK"}
Ejemplo n.º 2
0
    def page(self) -> None:
        assert user.id is not None

        html.set_render_headfoot(False)
        html.add_body_css_class("login")
        html.add_body_css_class("two_factor")
        html.header(_("Two-factor authentication"), Breadcrumb(), javascripts=[])

        html.open_div(id_="login")

        html.open_div(id_="login_window")

        html.open_a(href="https://checkmk.com")
        html.img(
            src=theme.detect_icon_path(icon_name="logo", prefix="mk-"),
            id_="logo",
            class_="custom" if theme.has_custom_logo() else None,
        )
        html.close_a()

        if not is_two_factor_login_enabled(user.id):
            raise MKGeneralException(_("Two-factor authentication not enabled"))

        html.begin_form(
            "two_factor_login", method="POST", add_transid=False, action="user_login_two_factor.py"
        )
        html.prevent_password_auto_completion()
        html.hidden_field(
            "_origtarget", origtarget := request.get_url_input("_origtarget", "index.py")
        )

        if backup_code := request.get_ascii_input("_backup_code"):
            if is_two_factor_backup_code_valid(user.id, backup_code):
                set_two_factor_completed()
                raise HTTPRedirect(origtarget)
Ejemplo n.º 3
0
def test_disable_two_factor_authentication(user_id: UserId) -> None:
    credentials = userdb.TwoFactorCredentials({
        "webauthn_credentials": {
            "id":
            userdb.WebAuthnCredential({
                "credential_id": "id",
                "registered_at": 1337,
                "alias": "Steckding",
                "credential_data": b"whatever",
            }),
        },
        "backup_codes": [],
    })
    userdb.save_two_factor_credentials(user_id, credentials)

    assert userdb.is_two_factor_login_enabled(user_id) is True
    userdb.disable_two_factor_authentication(user_id)
    assert userdb.is_two_factor_login_enabled(user_id) is False
Ejemplo n.º 4
0
def _redirect_for_two_factor_authentication(user_id: UserId) -> None:
    if requested_file_name(request) in (
            "user_login_two_factor",
            "user_webauthn_login_begin",
            "user_webauthn_login_complete",
    ):
        return

    if userdb.is_two_factor_login_enabled(
            user_id) and not userdb.is_two_factor_completed():
        raise HTTPRedirect("user_login_two_factor.py?_origtarget=%s" %
                           urlencode(makeuri(request, [])))
Ejemplo n.º 5
0
    def page(self) -> CBORPageResult:
        assert user.id is not None

        if not is_two_factor_login_enabled(user.id):
            raise MKGeneralException(_("Two-factor authentication not enabled"))

        auth_data, state = make_fido2_server().authenticate_begin(
            [
                AttestedCredentialData.unpack_from(v["credential_data"])[0]
                for v in load_two_factor_credentials(user.id)["webauthn_credentials"].values()
            ],
            user_verification="discouraged",
        )

        session.session_info.webauthn_action_state = state
        logger.debug("Authentication data: %r", auth_data)
        return auth_data
Ejemplo n.º 6
0
    # We pick the first successful authentication method, which means the precedence is the same
    # as the order in the code.
    final_candidate = verified[0]
    user_id = final_candidate["sub"]
    if not userdb.is_customer_user_allowed_to_login(user_id):
        raise MKAuthException(f"{user_id} may not log in here.")

    if userdb.user_locked(user_id):
        raise MKAuthException(f"{user_id} not authorized.")

    if change_reason := userdb.need_to_change_pw(user_id, now):
        raise MKAuthException(
            f"{user_id} needs to change the password ({change_reason}).")

    if userdb.is_two_factor_login_enabled(user_id):
        if final_candidate["scope"] != "cookie":
            raise MKAuthException(
                f"{user_id} has two-factor authentication enabled, which can only be used in "
                "interactive GUI sessions.")
        if not userdb.is_two_factor_completed():
            raise MKAuthException(
                "The two-factor authentication needs to be passed first.")

    return final_candidate


def user_from_basic_header(auth_header: str) -> Tuple[UserId, str]:
    """Decode a Basic Authorization header

    Examples:
Ejemplo n.º 7
0
    def _do_login(self) -> None:
        """handle the sent login form"""
        if not request.var("_login"):
            return

        try:
            if not config.user_login:
                raise MKUserError(None,
                                  _("Login is not allowed on this site."))

            username_var = request.get_str_input("_username", "")
            assert username_var is not None
            username = UserId(username_var.rstrip())
            if not username:
                raise MKUserError("_username", _("Missing username"))

            password = request.var("_password", "")
            if not password:
                raise MKUserError("_password", _("Missing password"))

            default_origtarget = url_prefix() + "check_mk/"
            origtarget = request.get_url_input("_origtarget",
                                               default_origtarget)

            # Disallow redirections to:
            #  - logout.py: Happens after login
            #  - side.py: Happens when invalid login is detected during sidebar refresh
            if "logout.py" in origtarget or "side.py" in origtarget:
                origtarget = default_origtarget

            result = userdb.check_credentials(username, password)
            if result:
                # use the username provided by the successful login function, this function
                # might have transformed the username provided by the user. e.g. switched
                # from mixed case to lower case.
                username = result

                session_id = userdb.on_succeeded_login(username)

                # The login succeeded! Now:
                # a) Set the auth cookie
                # b) Unset the login vars in further processing
                # c) Redirect to really requested page
                _create_auth_session(username, session_id)

                # Never use inplace redirect handling anymore as used in the past. This results
                # in some unexpected situations. We simpy use 302 redirects now. So we have a
                # clear situation.
                # userdb.need_to_change_pw returns either False or the reason description why the
                # password needs to be changed
                change_pw_result = userdb.need_to_change_pw(username)
                if change_pw_result:
                    raise HTTPRedirect(
                        "user_change_pw.py?_origtarget=%s&reason=%s" %
                        (urlencode(origtarget), change_pw_result))

                if userdb.is_two_factor_login_enabled(username):
                    raise HTTPRedirect(
                        "user_login_two_factor.py?_origtarget=%s" %
                        urlencode(makeuri(request, [])))

                raise HTTPRedirect(origtarget)

            userdb.on_failed_login(username)
            raise MKUserError(None, _("Invalid login"))
        except MKUserError as e:
            user_errors.add(e)