Exemplo n.º 1
0
def test_loginAndLogout() -> None:
    preferences = Preferences()
    authorization_service = AuthorizationService(OAUTH_SETTINGS, preferences)
    authorization_service.onAuthenticationError.emit = MagicMock()
    authorization_service.onAuthStateChanged.emit = MagicMock()
    authorization_service.initialize()

    # Let the service think there was a succesfull response
    with patch.object(AuthorizationHelpers,
                      "parseJWT",
                      return_value=UserProfile()):
        authorization_service._onAuthStateChanged(SUCCESFULL_AUTH_RESPONSE)

    # Ensure that the error signal was not triggered
    assert authorization_service.onAuthenticationError.emit.call_count == 0

    # Since we said that it went right this time, validate that we got a signal.
    assert authorization_service.onAuthStateChanged.emit.call_count == 1
    assert authorization_service.getUserProfile() is not None
    assert authorization_service.getAccessToken() == "beep"

    # Check that we stored the authentication data, so next time the user won't have to log in again.
    assert preferences.getValue("test/auth_data") is not None

    # We're logged in now, also check if logging out works
    authorization_service.deleteAuthData()
    assert authorization_service.onAuthStateChanged.emit.call_count == 2
    assert authorization_service.getUserProfile() is None

    # Ensure the data is gone after we logged out.
    assert preferences.getValue("test/auth_data") == "{}"
Exemplo n.º 2
0
def test__parseJWTNoRefreshToken():
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(NO_REFRESH_AUTH_RESPONSE)
    assert authorization_service._parseJWT() is None
Exemplo n.º 3
0
def test__parseJWTNoRefreshToken():
    """
    Tests parsing the user profile if there is no refresh token stored, but there is a normal authentication token.

    The request for the user profile using the authentication token should still work normally.
    """
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(NO_REFRESH_AUTH_RESPONSE)

    mock_callback = Mock()  # To log the final profile response.
    mock_reply = Mock(
    )  # The user profile that the service should respond with.
    mock_reply.error = Mock(return_value=QNetworkReply.NetworkError.NoError)
    http_mock = Mock()
    http_mock.get = lambda url, headers_dict, callback, error_callback: callback(
        mock_reply)
    http_mock.readJSON = Mock(return_value={
        "data": {
            "user_id": "id_ego_or_superego",
            "username": "******"
        }
    })

    with patch(
            "UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance",
            MagicMock(return_value=http_mock)):
        authorization_service._parseJWT(mock_callback)
    mock_callback.assert_called_once()
    profile_reply = mock_callback.call_args_list[0][0][0]
    assert profile_reply.user_id == "id_ego_or_superego"
    assert profile_reply.username == "Ghostkeeper"
Exemplo n.º 4
0
def test__parseJWTFailOnRefresh():
    """
    Tries to refresh the authentication token using an invalid refresh token. The request should fail.
    """
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(SUCCESSFUL_AUTH_RESPONSE)

    mock_callback = Mock()  # To log the final profile response.
    mock_reply = Mock(
    )  # The response that the request should give, containing an error about it failing to authenticate.
    mock_reply.error = Mock(
        return_value=QNetworkReply.NetworkError.AuthenticationRequiredError
    )  # The reply is 403: Authentication required, meaning the server responded with a "Can't do that, Dave".
    http_mock = Mock()
    http_mock.get = lambda url, headers_dict, callback, error_callback: callback(
        mock_reply)
    http_mock.post = lambda url, data, headers_dict, callback, error_callback: callback(
        mock_reply)

    with patch(
            "UM.TaskManagement.HttpRequestManager.HttpRequestManager.readJSON",
            Mock(
                return_value={"error_description": "Mock a failed request!"})):
        with patch(
                "UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance",
                MagicMock(return_value=http_mock)):
            authorization_service._parseJWT(mock_callback)
    mock_callback.assert_called_once_with(None)
Exemplo n.º 5
0
 def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
     try:
         token_request = requests.get(
             "{}/check-token".format(self._settings.OAUTH_SERVER_URL),
             headers={"Authorization": "Bearer {}".format(access_token)})
     except requests.exceptions.ConnectionError:
         # Connection was suddenly dropped. Nothing we can do about that.
         Logger.log(
             "w",
             "Something failed while attempting to parse the JWT token")
         return None
     if token_request.status_code not in (200, 201):
         Logger.log("w",
                    "Could not retrieve token data from auth server: %s",
                    token_request.text)
         return None
     user_data = token_request.json().get("data")
     if not user_data or not isinstance(user_data, dict):
         Logger.log("w", "Could not parse user data from token: %s",
                    user_data)
         return None
     return UserProfile(user_id=user_data["user_id"],
                        username=user_data["username"],
                        profile_image_url=user_data.get(
                            "profile_image_url", ""))
Exemplo n.º 6
0
def test_wrongServerResponses() -> None:
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    authorization_service.initialize()
    with patch.object(AuthorizationHelpers,
                      "parseJWT",
                      return_value=UserProfile()):
        authorization_service._onAuthStateChanged(MALFORMED_AUTH_RESPONSE)
    assert authorization_service.getUserProfile() is None
Exemplo n.º 7
0
def test__parseJWTFailOnRefresh():
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(SUCCESSFUL_AUTH_RESPONSE)

    with patch.object(AuthorizationHelpers,
                      "getAccessTokenUsingRefreshToken",
                      return_value=FAILED_AUTH_RESPONSE):
        assert authorization_service._parseJWT() is None
Exemplo n.º 8
0
def test_refreshAccessTokenFailed():
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    authorization_service.initialize()
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(SUCCESSFUL_AUTH_RESPONSE)
    authorization_service.onAuthStateChanged.emit = MagicMock()
    with patch.object(AuthorizationHelpers,
                      "getAccessTokenUsingRefreshToken",
                      return_value=FAILED_AUTH_RESPONSE):
        authorization_service.refreshAccessToken()
        assert authorization_service.onAuthStateChanged.emit.called_with(False)
Exemplo n.º 9
0
def test__parseJWTSucceedOnRefresh():
    """
    Tries to refresh the authentication token using a valid refresh token. The request should succeed.
    """
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    authorization_service.initialize()
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(EXPIRED_AUTH_RESPONSE)

    mock_callback = Mock()  # To log the final profile response.
    mock_reply_success = Mock(
    )  # The reply should be a failure when using the expired access token, but succeed when using the refresh token.
    mock_reply_success.error = Mock(
        return_value=QNetworkReply.NetworkError.NoError)
    mock_reply_failure = Mock()
    mock_reply_failure.error = Mock(
        return_value=QNetworkReply.NetworkError.AuthenticationRequiredError)
    http_mock = Mock()

    def mock_get(url, headers_dict, callback, error_callback):
        if (headers_dict == {"Authorization": "Bearer beep"}):
            callback(mock_reply_success)
        else:
            callback(mock_reply_failure)

    http_mock.get = mock_get
    http_mock.readJSON = Mock(return_value={
        "data": {
            "user_id": "user_idea",
            "username": "******"
        }
    })

    def mock_refresh(self, refresh_token,
                     callback):  # Refreshing gives a valid token.
        callback(SUCCESSFUL_AUTH_RESPONSE)

    with patch(
            "cura.OAuth2.AuthorizationHelpers.AuthorizationHelpers.getAccessTokenUsingRefreshToken",
            mock_refresh):
        with patch(
                "UM.TaskManagement.HttpRequestManager.HttpRequestManager.getInstance",
                MagicMock(return_value=http_mock)):
            authorization_service._parseJWT(mock_callback)

    mock_callback.assert_called_once()
    profile_reply = mock_callback.call_args_list[0][0][0]
    assert profile_reply.user_id == "user_idea"
    assert profile_reply.username == "Ghostkeeper"
Exemplo n.º 10
0
def test__parseJWTSucceedOnRefresh():
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    authorization_service.initialize()
    with patch.object(AuthorizationService,
                      "getUserProfile",
                      return_value=UserProfile()):
        authorization_service._storeAuthData(SUCCESSFUL_AUTH_RESPONSE)

    with patch.object(AuthorizationHelpers,
                      "getAccessTokenUsingRefreshToken",
                      return_value=SUCCESSFUL_AUTH_RESPONSE):
        with patch.object(AuthorizationHelpers, "parseJWT",
                          MagicMock(return_value=None)) as mocked_parseJWT:
            authorization_service._parseJWT()
            mocked_parseJWT.assert_called_with("beep")
Exemplo n.º 11
0
 def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
     token_request = requests.get(
         "{}/check-token".format(self._settings.OAUTH_SERVER_URL),
         headers={"Authorization": "Bearer {}".format(access_token)})
     if token_request.status_code not in (200, 201):
         Logger.log("w",
                    "Could not retrieve token data from auth server: %s",
                    token_request.text)
         return None
     user_data = token_request.json().get("data")
     if not user_data or not isinstance(user_data, dict):
         Logger.log("w", "Could not parse user data from token: %s",
                    user_data)
         return None
     return UserProfile(user_id=user_data["user_id"],
                        username=user_data["username"],
                        profile_image_url=user_data.get(
                            "profile_image_url", ""))
Exemplo n.º 12
0
    def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
        """Calls the authentication API endpoint to get the token data.

        :param access_token: The encoded JWT token.
        :return: Dict containing some profile data.
        """

        try:
            check_token_url = "{}/check-token".format(
                self._settings.OAUTH_SERVER_URL)
            Logger.log("d", "Checking the access token for [%s]",
                       check_token_url)
            token_request = requests.get(
                check_token_url,
                headers={"Authorization": "Bearer {}".format(access_token)})
        except (requests.exceptions.ConnectionError,
                requests.exceptions.Timeout):
            # Connection was suddenly dropped. Nothing we can do about that.
            Logger.logException(
                "w",
                "Something failed while attempting to parse the JWT token")
            return None
        if token_request.status_code not in (200, 201):
            Logger.log("w",
                       "Could not retrieve token data from auth server: %s",
                       token_request.text)
            return None
        user_data = token_request.json().get("data")
        if not user_data or not isinstance(user_data, dict):
            Logger.log("w", "Could not parse user data from token: %s",
                       user_data)
            return None

        return UserProfile(
            user_id=user_data["user_id"],
            username=user_data["username"],
            profile_image_url=user_data.get("profile_image_url", ""),
            organization_id=user_data.get("organization",
                                          {}).get("organization_id"),
            subscriptions=user_data.get("subscriptions", []))
Exemplo n.º 13
0
def user_profile():
    result = UserProfile()
    result.username = "******"
    result.profile_image_url = "profile_image_url!"
    result.user_id = "user_id!"
    return result
Exemplo n.º 14
0
    authorization_service._onAuthStateChanged(FAILED_AUTH_RESPONSE)

    # Check that the error signal was triggered
    assert authorization_service.onAuthenticationError.emit.call_count == 1

    # Since nothing changed, this should still be 0.
    assert authorization_service.onAuthStateChanged.emit.call_count == 0

    # Validate that there is no user profile or token
    assert authorization_service.getUserProfile() is None
    assert authorization_service.getAccessToken() is None


@patch.object(AuthorizationService,
              "getUserProfile",
              return_value=UserProfile())
def test_storeAuthData(get_user_profile) -> None:
    preferences = Preferences()
    authorization_service = AuthorizationService(OAUTH_SETTINGS, preferences)
    authorization_service.initialize()

    # Write stuff to the preferences.
    authorization_service._storeAuthData(SUCCESFULL_AUTH_RESPONSE)
    preference_value = preferences.getValue(
        OAUTH_SETTINGS.AUTH_DATA_PREFERENCE_KEY)
    # Check that something was actually put in the preferences
    assert preference_value is not None and preference_value != {}

    # Create a second auth service, so we can load the data.
    second_auth_service = AuthorizationService(OAUTH_SETTINGS, preferences)
    second_auth_service.initialize()
Exemplo n.º 15
0
def user_profile():
    result = UserProfile()
    result.username = "******"
    result.profile_image_url = "profile_image_url!"
    result.user_id = "user_id!"
    return result
Exemplo n.º 16
0
    # Let the service think there was a failed response
    authorization_service._onAuthStateChanged(FAILED_AUTH_RESPONSE)

    # Check that the error signal was triggered
    assert authorization_service.onAuthenticationError.emit.call_count == 1

    # Since nothing changed, this should still be 0.
    assert authorization_service.onAuthStateChanged.emit.call_count == 0

    # Validate that there is no user profile or token
    assert authorization_service.getUserProfile() is None
    assert authorization_service.getAccessToken() is None


@patch.object(AuthorizationService, "getUserProfile", return_value=UserProfile())
def test_storeAuthData(get_user_profile) -> None:
    preferences = Preferences()
    authorization_service = AuthorizationService(OAUTH_SETTINGS, preferences)
    authorization_service.initialize()

    # Write stuff to the preferences.
    authorization_service._storeAuthData(SUCCESSFUL_AUTH_RESPONSE)
    preference_value = preferences.getValue(OAUTH_SETTINGS.AUTH_DATA_PREFERENCE_KEY)
    # Check that something was actually put in the preferences
    assert preference_value is not None and preference_value != {}

    # Create a second auth service, so we can load the data.
    second_auth_service = AuthorizationService(OAUTH_SETTINGS, preferences)
    second_auth_service.initialize()
    second_auth_service.loadAuthDataFromPreferences()