Exemplo n.º 1
0
async def test_new_users_admin(mock_opp):
    """Test newly created users are admin."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [
            {
                "type": "insecure_example",
                "users": [
                    {
                        "username": "******",
                        "password": "******",
                        "name": "Test Name",
                    }
                ],
            }
        ],
        [],
    )
    ensure_auth_manager_loaded(manager)

    user = await manager.async_create_user("Hello")
    assert user.is_admin

    user_cred = await manager.async_get_or_create_user(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=True,
        )
    )
    assert user_cred.is_admin
Exemplo n.º 2
0
async def test_auth_module_expired_session(mock_opp):
    """Test login as existing user."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [
            {
                "type": "insecure_example",
                "users": [
                    {
                        "username": "******",
                        "password": "******",
                        "name": "Test Name",
                    }
                ],
            }
        ],
        [
            {
                "type": "insecure_example",
                "data": [{"user_id": "mock-user", "pin": "test-pin"}],
            }
        ],
    )
    mock_opp.auth = manager
    ensure_auth_manager_loaded(manager)

    # Add fake user with credentials for example auth provider.
    user = MockUser(
        id="mock-user", is_owner=False, is_active=False, name="Paulus"
    ).add_to_auth_manager(manager)
    user.credentials.append(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        )
    )

    step = await manager.login_flow.async_init(("insecure_example", None))
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM

    step = await manager.login_flow.async_configure(
        step["flow_id"], {"username": "******", "password": "******"}
    )

    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert step["step_id"] == "mfa"

    with patch(
        "openpeerpower.util.dt.utcnow",
        return_value=dt_util.utcnow() + MFA_SESSION_EXPIRATION,
    ):
        step = await manager.login_flow.async_configure(
            step["flow_id"], {"pin": "test-pin"}
        )
        # login flow abort due session timeout
        assert step["type"] == data_entry_flow.RESULT_TYPE_ABORT
        assert step["reason"] == "login_expired"
Exemplo n.º 3
0
async def test_new_users(mock_opp):
    """Test newly created users."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [{
            "type":
            "insecure_example",
            "users": [
                {
                    "username": "******",
                    "password": "******",
                    "name": "Test Name",
                },
                {
                    "username": "******",
                    "password": "******",
                    "name": "Test Name",
                },
                {
                    "username": "******",
                    "password": "******",
                    "name": "Test Name",
                },
            ],
        }],
        [],
    )
    ensure_auth_manager_loaded(manager)

    user = await manager.async_create_user("Hello")
    # first user in the system is owner and admin
    assert user.is_owner
    assert user.is_admin
    assert user.groups == []

    user = await manager.async_create_user("Hello 2")
    assert not user.is_admin
    assert user.groups == []

    user = await manager.async_create_user("Hello 3", ["system-admin"])
    assert user.is_admin
    assert user.groups[0].id == "system-admin"

    user_cred = await manager.async_get_or_create_user(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=True,
        ))
    assert user_cred.is_admin
Exemplo n.º 4
0
async def test_async_remove_user(opp):
    """Test removing a user."""
    events = []

    @callback
    def user_removed(event):
        events.append(event)

    opp.bus.async_listen("user_removed", user_removed)

    manager = await auth.auth_manager_from_config(
        opp,
        [
            {
                "type": "insecure_example",
                "users": [
                    {
                        "username": "******",
                        "password": "******",
                        "name": "Test Name",
                    }
                ],
            }
        ],
        [],
    )
    opp.auth = manager
    ensure_auth_manager_loaded(manager)

    # Add fake user with credentials for example auth provider.
    user = MockUser(
        id="mock-user", is_owner=False, is_active=False, name="Paulus"
    ).add_to_auth_manager(manager)
    user.credentials.append(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        )
    )
    assert len(user.credentials) == 1

    await opp.auth.async_remove_user(user)

    assert len(await manager.async_get_users()) == 0
    assert len(user.credentials) == 0

    await opp.async_block_till_done()
    assert len(events) == 1
    assert events[0].data["user_id"] == user.id
async def test_match_existing_credentials(store, provider):
    """See if we match existing users."""
    existing = auth_models.Credentials(
        id=uuid.uuid4(),
        auth_provider_type="command_line",
        auth_provider_id=None,
        data={"username": "******"},
        is_new=False,
    )
    provider.async_credentials = Mock(return_value=mock_coro([existing]))
    credentials = await provider.async_get_or_create_credentials(
        {"username": "******", "password": "******"}
    )
    assert credentials is existing
Exemplo n.º 6
0
async def test_not_raise_exception_when_service_not_exist(opp):
    """Test login flow will not raise exception when notify service error."""
    opp.auth = await auth_manager_from_config(
        opp,
        [{
            "type": "insecure_example",
            "users": [{
                "username": "******",
                "password": "******"
            }],
        }],
        [{
            "type": "notify"
        }],
    )
    user = MockUser(id="mock-user",
                    is_owner=False,
                    is_active=False,
                    name="Paulus").add_to_auth_manager(opp.auth)
    await opp.auth.async_link_user(
        user,
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        ),
    )

    await opp.auth.async_enable_user_mfa(user, "notify",
                                         {"notify_service": "invalid-notify"})

    provider = opp.auth.auth_providers[0]

    result = await opp.auth.login_flow.async_init((provider.type, provider.id))
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

    with patch("pyotp.HOTP.at", return_value=MOCK_CODE):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {
                "username": "******",
                "password": "******"
            })
        assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
        assert result["reason"] == "unknown_error"

    # wait service call finished
    await opp.async_block_till_done()
Exemplo n.º 7
0
async def test_match_existing_credentials(store, provider):
    """See if we match existing users."""
    existing = auth_models.Credentials(
        id=uuid.uuid4(),
        auth_provider_type="insecure_example",
        auth_provider_id=None,
        data={"username": "******"},
        is_new=False,
    )
    provider.async_credentials = AsyncMock(return_value=[existing])
    credentials = await provider.async_get_or_create_credentials({
        "username":
        "******",
        "password":
        "******"
    })
    assert credentials is existing
Exemplo n.º 8
0
async def test_refresh_token_provider_validation(mock_opp):
    """Test that creating access token from refresh token checks with provider."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [{
            "type": "insecure_example",
            "users": [{
                "username": "******",
                "password": "******"
            }],
        }],
        [],
    )

    credential = auth_models.Credentials(
        id="mock-credential-id",
        auth_provider_type="insecure_example",
        auth_provider_id=None,
        data={"username": "******"},
        is_new=False,
    )

    user = MockUser().add_to_auth_manager(manager)
    user.credentials.append(credential)
    refresh_token = await manager.async_create_refresh_token(
        user, CLIENT_ID, credential=credential)
    ip = "127.0.0.1"

    assert manager.async_create_access_token(refresh_token, ip) is not None

    with patch(
            "openpeerpower.auth.providers.insecure_example.ExampleAuthProvider.async_validate_refresh_token",
            side_effect=InvalidAuthError("Invalid access"),
    ) as call, pytest.raises(InvalidAuthError):
        manager.async_create_access_token(refresh_token, ip)

    call.assert_called_with(refresh_token, ip)
Exemplo n.º 9
0
async def test_login_flow_validates_mfa(opp):
    """Test login flow with mfa enabled."""
    opp.auth = await auth_manager_from_config(
        opp,
        [{
            "type": "insecure_example",
            "users": [{
                "username": "******",
                "password": "******"
            }],
        }],
        [{
            "type": "notify"
        }],
    )
    user = MockUser(id="mock-user",
                    is_owner=False,
                    is_active=False,
                    name="Paulus").add_to_auth_manager(opp.auth)
    await opp.auth.async_link_user(
        user,
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        ),
    )

    notify_calls = async_mock_service(opp, "notify", "test-notify",
                                      NOTIFY_SERVICE_SCHEMA)

    await opp.auth.async_enable_user_mfa(user, "notify",
                                         {"notify_service": "test-notify"})

    provider = opp.auth.auth_providers[0]

    result = await opp.auth.login_flow.async_init((provider.type, provider.id))
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

    result = await opp.auth.login_flow.async_configure(result["flow_id"], {
        "username": "******",
        "password": "******"
    })
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert result["errors"]["base"] == "invalid_auth"

    result = await opp.auth.login_flow.async_configure(
        result["flow_id"], {
            "username": "******",
            "password": "******"
        })
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert result["errors"]["base"] == "invalid_auth"

    with patch("pyotp.HOTP.at", return_value=MOCK_CODE):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {
                "username": "******",
                "password": "******"
            })
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["step_id"] == "mfa"
        assert result["data_schema"].schema.get("code") == str

    # wait service call finished
    await opp.async_block_till_done()

    assert len(notify_calls) == 1
    notify_call = notify_calls[0]
    assert notify_call.domain == "notify"
    assert notify_call.service == "test-notify"
    message = notify_call.data["message"]
    message.opp = opp
    assert MOCK_CODE in message.async_render()

    with patch("pyotp.HOTP.verify", return_value=False):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {"code": "invalid-code"})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["step_id"] == "mfa"
        assert result["errors"]["base"] == "invalid_code"

    # wait service call finished
    await opp.async_block_till_done()

    # would not send new code, allow user retry
    assert len(notify_calls) == 1

    # retry twice
    with patch("pyotp.HOTP.verify",
               return_value=False), patch("pyotp.HOTP.at",
                                          return_value=MOCK_CODE_2):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {"code": "invalid-code"})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["step_id"] == "mfa"
        assert result["errors"]["base"] == "invalid_code"

        # after the 3rd failure, flow abort
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {"code": "invalid-code"})
        assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
        assert result["reason"] == "too_many_retry"

    # wait service call finished
    await opp.async_block_till_done()

    # restart login
    result = await opp.auth.login_flow.async_init((provider.type, provider.id))
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

    with patch("pyotp.HOTP.at", return_value=MOCK_CODE):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {
                "username": "******",
                "password": "******"
            })
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["step_id"] == "mfa"
        assert result["data_schema"].schema.get("code") == str

    # wait service call finished
    await opp.async_block_till_done()

    assert len(notify_calls) == 2
    notify_call = notify_calls[1]
    assert notify_call.domain == "notify"
    assert notify_call.service == "test-notify"
    message = notify_call.data["message"]
    message.opp = opp
    assert MOCK_CODE in message.async_render()

    with patch("pyotp.HOTP.verify", return_value=True):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {"code": MOCK_CODE})
        assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
        assert result["data"].id == "mock-user"
Exemplo n.º 10
0
async def test_login_with_multi_auth_module(mock_opp):
    """Test login as existing user with multiple auth modules."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [{
            "type":
            "insecure_example",
            "users": [{
                "username": "******",
                "password": "******",
                "name": "Test Name",
            }],
        }],
        [
            {
                "type": "insecure_example",
                "data": [{
                    "user_id": "mock-user",
                    "pin": "test-pin"
                }],
            },
            {
                "type": "insecure_example",
                "id": "module2",
                "data": [{
                    "user_id": "mock-user",
                    "pin": "test-pin2"
                }],
            },
        ],
    )
    mock_opp.auth = manager
    ensure_auth_manager_loaded(manager)

    # Add fake user with credentials for example auth provider.
    user = MockUser(id="mock-user",
                    is_owner=False,
                    is_active=False,
                    name="Paulus").add_to_auth_manager(manager)
    user.credentials.append(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        ))

    step = await manager.login_flow.async_init(("insecure_example", None))
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM

    step = await manager.login_flow.async_configure(step["flow_id"], {
        "username": "******",
        "password": "******"
    })

    # After auth_provider validated, request select auth module
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert step["step_id"] == "select_mfa_module"

    step = await manager.login_flow.async_configure(
        step["flow_id"], {"multi_factor_auth_module": "module2"})

    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert step["step_id"] == "mfa"

    step = await manager.login_flow.async_configure(step["flow_id"],
                                                    {"pin": "test-pin2"})

    # Finally passed, get credential
    assert step["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
    assert step["result"]
    assert step["result"].id == "mock-id"
Exemplo n.º 11
0
async def test_login_as_existing_user(mock_opp):
    """Test login as existing user."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [{
            "type":
            "insecure_example",
            "users": [{
                "username": "******",
                "password": "******",
                "name": "Test Name",
            }],
        }],
        [],
    )
    mock_opp.auth = manager
    ensure_auth_manager_loaded(manager)

    # Add a fake user that we're not going to log in with
    user = MockUser(id="mock-user2",
                    is_owner=False,
                    is_active=False,
                    name="Not user").add_to_auth_manager(manager)
    user.credentials.append(
        auth_models.Credentials(
            id="mock-id2",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        ))

    # Add fake user with credentials for example auth provider.
    user = MockUser(id="mock-user",
                    is_owner=False,
                    is_active=False,
                    name="Paulus").add_to_auth_manager(manager)
    user.credentials.append(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        ))

    step = await manager.login_flow.async_init(("insecure_example", None))
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM

    step = await manager.login_flow.async_configure(step["flow_id"], {
        "username": "******",
        "password": "******"
    })
    assert step["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY

    credential = step["result"]
    user = await manager.async_get_user_by_credentials(credential)
    assert user is not None
    assert user.id == "mock-user"
    assert user.is_owner is False
    assert user.is_active is False
    assert user.name == "Paulus"
Exemplo n.º 12
0
async def test_login_flow_validates_mfa(opp):
    """Test login flow with mfa enabled."""
    opp.auth = await auth_manager_from_config(
        opp,
        [{
            "type": "insecure_example",
            "users": [{
                "username": "******",
                "password": "******"
            }],
        }],
        [{
            "type": "totp"
        }],
    )
    user = MockUser(id="mock-user",
                    is_owner=False,
                    is_active=False,
                    name="Paulus").add_to_auth_manager(opp.auth)
    await opp.auth.async_link_user(
        user,
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        ),
    )

    await opp.auth.async_enable_user_mfa(user, "totp", {})

    provider = opp.auth.auth_providers[0]

    result = await opp.auth.login_flow.async_init((provider.type, provider.id))
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM

    result = await opp.auth.login_flow.async_configure(result["flow_id"], {
        "username": "******",
        "password": "******"
    })
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert result["errors"]["base"] == "invalid_auth"

    result = await opp.auth.login_flow.async_configure(
        result["flow_id"], {
            "username": "******",
            "password": "******"
        })
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert result["errors"]["base"] == "invalid_auth"

    result = await opp.auth.login_flow.async_configure(result["flow_id"], {
        "username": "******",
        "password": "******"
    })
    assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert result["step_id"] == "mfa"
    assert result["data_schema"].schema.get("code") == str

    with patch("pyotp.TOTP.verify", return_value=False):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {"code": "invalid-code"})
        assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
        assert result["step_id"] == "mfa"
        assert result["errors"]["base"] == "invalid_code"

    with patch("pyotp.TOTP.verify", return_value=True):
        result = await opp.auth.login_flow.async_configure(
            result["flow_id"], {"code": MOCK_CODE})
        assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
        assert result["data"].id == "mock-user"
Exemplo n.º 13
0
async def test_list(opp, opp_ws_client, opp_admin_user):
    """Test get users."""
    group = MockGroup().add_to_opp(opp)

    owner = MockUser(id="abc",
                     name="Test Owner",
                     is_owner=True,
                     groups=[group]).add_to_opp(opp)

    owner.credentials.append(
        auth_models.Credentials(
            auth_provider_type="openpeerpower",
            auth_provider_id=None,
            data={"username": "******"},
        ))

    system = MockUser(id="efg", name="Test Opp.io",
                      system_generated=True).add_to_opp(opp)

    inactive = MockUser(id="hij",
                        name="Inactive User",
                        is_active=False,
                        groups=[group]).add_to_opp(opp)

    refresh_token = await opp.auth.async_create_refresh_token(
        owner, CLIENT_ID, credential=owner.credentials[0])
    access_token = opp.auth.async_create_access_token(refresh_token)

    client = await opp_ws_client(opp, access_token)
    await client.send_json({"id": 5, "type": auth_config.WS_TYPE_LIST})

    result = await client.receive_json()
    assert result["success"], result
    data = result["result"]
    assert len(data) == 4
    assert data[0] == {
        "id": opp_admin_user.id,
        "username": "******",
        "name": "Mock User",
        "is_owner": False,
        "is_active": True,
        "system_generated": False,
        "group_ids": [group.id for group in opp_admin_user.groups],
        "credentials": [{
            "type": "openpeerpower"
        }],
    }
    assert data[1] == {
        "id": owner.id,
        "username": "******",
        "name": "Test Owner",
        "is_owner": True,
        "is_active": True,
        "system_generated": False,
        "group_ids": [group.id for group in owner.groups],
        "credentials": [{
            "type": "openpeerpower"
        }],
    }
    assert data[2] == {
        "id": system.id,
        "username": None,
        "name": "Test Opp.io",
        "is_owner": False,
        "is_active": True,
        "system_generated": True,
        "group_ids": [],
        "credentials": [],
    }
    assert data[3] == {
        "id": inactive.id,
        "username": None,
        "name": "Inactive User",
        "is_owner": False,
        "is_active": False,
        "system_generated": False,
        "group_ids": [group.id for group in inactive.groups],
        "credentials": [],
    }
Exemplo n.º 14
0
async def test_login_with_auth_module(mock_opp):
    """Test login as existing user with auth module."""
    manager = await auth.auth_manager_from_config(
        mock_opp,
        [
            {
                "type": "insecure_example",
                "users": [
                    {
                        "username": "******",
                        "password": "******",
                        "name": "Test Name",
                    }
                ],
            }
        ],
        [
            {
                "type": "insecure_example",
                "data": [{"user_id": "mock-user", "pin": "test-pin"}],
            }
        ],
    )
    mock_opp.auth = manager
    ensure_auth_manager_loaded(manager)

    # Add fake user with credentials for example auth provider.
    user = MockUser(
        id="mock-user", is_owner=False, is_active=False, name="Paulus"
    ).add_to_auth_manager(manager)
    user.credentials.append(
        auth_models.Credentials(
            id="mock-id",
            auth_provider_type="insecure_example",
            auth_provider_id=None,
            data={"username": "******"},
            is_new=False,
        )
    )

    step = await manager.login_flow.async_init(("insecure_example", None))
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM

    step = await manager.login_flow.async_configure(
        step["flow_id"], {"username": "******", "password": "******"}
    )

    # After auth_provider validated, request auth module input form
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert step["step_id"] == "mfa"

    step = await manager.login_flow.async_configure(
        step["flow_id"], {"pin": "invalid-pin"}
    )

    # Invalid code error
    assert step["type"] == data_entry_flow.RESULT_TYPE_FORM
    assert step["step_id"] == "mfa"
    assert step["errors"] == {"base": "invalid_code"}

    step = await manager.login_flow.async_configure(
        step["flow_id"], {"pin": "test-pin"}
    )

    # Finally passed, get user
    assert step["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
    user = step["result"]
    assert user is not None
    assert user.id == "mock-user"
    assert user.is_owner is False
    assert user.is_active is False
    assert user.name == "Paulus"