예제 #1
0
    def parseTokenResponse(
            token_response: requests.models.Response
    ) -> "AuthenticationResponse":
        token_data = None

        try:
            token_data = json.loads(token_response.text)
        except ValueError:
            Logger.log("w", "Could not parse token response data: %s",
                       token_response.text)

        if not token_data:
            return AuthenticationResponse(success=False,
                                          err_message=catalog.i18nc(
                                              "@message",
                                              "Could not read response."))

        if token_response.status_code not in (200, 201):
            return AuthenticationResponse(
                success=False, err_message=token_data["error_description"])

        return AuthenticationResponse(
            success=True,
            token_type=token_data["token_type"],
            access_token=token_data["access_token"],
            refresh_token=token_data["refresh_token"],
            expires_in=token_data["expires_in"],
            scope=token_data["scope"],
            received_at=datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT))
    def _handleCallback(
        self, query: Dict[Any, List]
    ) -> Tuple[ResponseData, Optional[AuthenticationResponse]]:
        code = self._queryGet(query, "code")
        if code and self.authorization_helpers is not None and self.verification_code is not None:
            # If the code was returned we get the access token.
            token_response = self.authorization_helpers.getAccessTokenUsingAuthorizationCode(
                code, self.verification_code)

        elif self._queryGet(query, "error_code") == "user_denied":
            # Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).
            token_response = AuthenticationResponse(
                success=False,
                err_message=
                "Please give the required permissions when authorizing this application."
            )

        else:
            # We don't know what went wrong here, so instruct the user to check the logs.
            token_response = AuthenticationResponse(
                success=False,
                error_message=
                "Something unexpected happened when trying to log in, please try again."
            )
        if self.authorization_helpers is None:
            return ResponseData(), token_response

        return ResponseData(status=HTTP_STATUS["REDIRECT"],
                            data_stream=b"Redirecting...",
                            redirect_uri=self.authorization_helpers.settings.
                            AUTH_SUCCESS_REDIRECT if token_response.success
                            else self.authorization_helpers.settings.
                            AUTH_FAILED_REDIRECT), token_response
예제 #3
0
    def loadAuthDataFromPreferences(self) -> None:
        if self._preferences is None:
            Logger.log(
                "e",
                "Unable to load authentication data, since no preference has been set!"
            )
            return
        try:
            preferences_data = json.loads(
                self._preferences.getValue(
                    self._settings.AUTH_DATA_PREFERENCE_KEY))
            if preferences_data:
                self._auth_data = AuthenticationResponse(**preferences_data)
                # Also check if we can actually get the user profile information.
                user_profile = self.getUserProfile()
                if user_profile is not None:
                    self.onAuthStateChanged.emit(logged_in=True)
                else:
                    if self._unable_to_get_data_message is not None:
                        self._unable_to_get_data_message.hide()

                    self._unable_to_get_data_message = Message(
                        i18n_catalog.i18nc(
                            "@info",
                            "Unable to reach the Ultimaker account server."),
                        title=i18n_catalog.i18nc("@info:title", "Warning"))
                    self._unable_to_get_data_message.addAction(
                        "retry", i18n_catalog.i18nc("@action:button", "Retry"),
                        "[no_icon]", "[no_description]")
                    self._unable_to_get_data_message.actionTriggered.connect(
                        self._onMessageActionTriggered)
                    self._unable_to_get_data_message.show()
        except ValueError:
            Logger.logException("w",
                                "Could not load auth data from preferences")
예제 #4
0
    def loadAuthDataFromPreferences(self) -> None:
        """Load authentication data from preferences."""
        Logger.log("d", "Attempting to load the auth data from preferences.")
        if self._preferences is None:
            Logger.log("e", "Unable to load authentication data, since no preference has been set!")
            return
        try:
            preferences_data = json.loads(self._preferences.getValue(self._settings.AUTH_DATA_PREFERENCE_KEY))
            if preferences_data:
                self._auth_data = AuthenticationResponse(**preferences_data)
                # Also check if we can actually get the user profile information.
                user_profile = self.getUserProfile()
                if user_profile is not None:
                    self.onAuthStateChanged.emit(logged_in = True)
                    Logger.log("d", "Auth data was successfully loaded")
                else:
                    if self._unable_to_get_data_message is not None:
                        self._unable_to_get_data_message.hide()

                    self._unable_to_get_data_message = Message(i18n_catalog.i18nc("@info",
                                                                                  "Unable to reach the Ultimaker account server."),
                                                               title = i18n_catalog.i18nc("@info:title", "Warning"),
                                                               message_type = Message.MessageType.ERROR)
                    Logger.log("w", "Unable to load auth data from preferences")
                    self._unable_to_get_data_message.show()
        except (ValueError, TypeError):
            Logger.logException("w", "Could not load auth data from preferences")
예제 #5
0
    def getAccessTokenUsingAuthorizationCode(
            self, authorization_code: str,
            verification_code: str) -> "AuthenticationResponse":
        """Request the access token from the authorization server.

        :param authorization_code: The authorization code from the 1st step.
        :param verification_code: The verification code needed for the PKCE extension.
        :return: An AuthenticationResponse object.
        """

        data = {
            "client_id":
            self._settings.CLIENT_ID
            if self._settings.CLIENT_ID is not None else "",
            "redirect_uri":
            self._settings.CALLBACK_URL
            if self._settings.CALLBACK_URL is not None else "",
            "grant_type":
            "authorization_code",
            "code":
            authorization_code,
            "code_verifier":
            verification_code,
            "scope":
            self._settings.CLIENT_SCOPES
            if self._settings.CLIENT_SCOPES is not None else "",
        }
        try:
            return self.parseTokenResponse(
                requests.post(self._token_url, data=data))  # type: ignore
        except requests.exceptions.ConnectionError:
            return AuthenticationResponse(
                success=False,
                err_message="Unable to connect to remote server")
예제 #6
0
    def getAccessTokenUsingRefreshToken(
            self, refresh_token: str) -> "AuthenticationResponse":
        """Request the access token from the authorization server using a refresh token.

        :param refresh_token:
        :return: An AuthenticationResponse object.
        """

        Logger.log("d", "Refreshing the access token.")
        data = {
            "client_id":
            self._settings.CLIENT_ID
            if self._settings.CLIENT_ID is not None else "",
            "redirect_uri":
            self._settings.CALLBACK_URL
            if self._settings.CALLBACK_URL is not None else "",
            "grant_type":
            "refresh_token",
            "refresh_token":
            refresh_token,
            "scope":
            self._settings.CLIENT_SCOPES
            if self._settings.CLIENT_SCOPES is not None else "",
        }
        try:
            return self.parseTokenResponse(
                requests.post(self._token_url, data=data))  # type: ignore
        except requests.exceptions.ConnectionError:
            return AuthenticationResponse(
                success=False,
                err_message="Unable to connect to remote server")
 def getAccessTokenUsingAuthorizationCode(
         self, authorization_code: str,
         verification_code: str) -> "AuthenticationResponse":
     data = {
         "client_id":
         self._settings.CLIENT_ID
         if self._settings.CLIENT_ID is not None else "",
         "redirect_uri":
         self._settings.CALLBACK_URL
         if self._settings.CALLBACK_URL is not None else "",
         "grant_type":
         "authorization_code",
         "code":
         authorization_code,
         "code_verifier":
         verification_code,
         "scope":
         self._settings.CLIENT_SCOPES
         if self._settings.CLIENT_SCOPES is not None else "",
     }
     try:
         return self.parseTokenResponse(
             requests.post(self._token_url, data=data))  # type: ignore
     except requests.exceptions.ConnectionError:
         return AuthenticationResponse(
             success=False,
             err_message="Unable to connect to remote server")
예제 #8
0
 def loadAuthDataFromPreferences(self) -> None:
     if self._preferences is None:
         Logger.log("e", "Unable to load authentication data, since no preference has been set!")
         return
     try:
         preferences_data = json.loads(self._preferences.getValue(self._settings.AUTH_DATA_PREFERENCE_KEY))
         if preferences_data:
             self._auth_data = AuthenticationResponse(**preferences_data)
             self.onAuthStateChanged.emit(logged_in = True)
     except ValueError:
         Logger.logException("w", "Could not load auth data from preferences")
예제 #9
0
CALLBACK_PORT = 32118
OAUTH_ROOT = "https://account.ultimaker.com"
CLOUD_API_ROOT = "https://api.ultimaker.com"

OAUTH_SETTINGS = OAuth2Settings(
    OAUTH_SERVER_URL=OAUTH_ROOT,
    CALLBACK_PORT=CALLBACK_PORT,
    CALLBACK_URL="http://localhost:{}/callback".format(CALLBACK_PORT),
    CLIENT_ID="",
    CLIENT_SCOPES="",
    AUTH_DATA_PREFERENCE_KEY="test/auth_data",
    AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(OAUTH_ROOT),
    AUTH_FAILED_REDIRECT="{}/app/auth-error".format(OAUTH_ROOT))

FAILED_AUTH_RESPONSE = AuthenticationResponse(success=False,
                                              err_message="FAILURE!")

SUCCESFULL_AUTH_RESPONSE = AuthenticationResponse(access_token="beep",
                                                  refresh_token="beep?")

MALFORMED_AUTH_RESPONSE = AuthenticationResponse()


def test_cleanAuthService() -> None:
    # Ensure that when setting up an AuthorizationService, no data is set.
    authorization_service = AuthorizationService(OAUTH_SETTINGS, Preferences())
    authorization_service.initialize()
    assert authorization_service.getUserProfile() is None
    assert authorization_service.getAccessToken() is None

예제 #10
0
파일: TestOAuth2.py 프로젝트: zlh6630/test
CALLBACK_PORT = 32118
OAUTH_ROOT = "https://account.ultimaker.com"
CLOUD_API_ROOT = "https://api.ultimaker.com"

OAUTH_SETTINGS = OAuth2Settings(
    OAUTH_SERVER_URL=OAUTH_ROOT,
    CALLBACK_PORT=CALLBACK_PORT,
    CALLBACK_URL="http://localhost:{}/callback".format(CALLBACK_PORT),
    CLIENT_ID="",
    CLIENT_SCOPES="",
    AUTH_DATA_PREFERENCE_KEY="test/auth_data",
    AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(OAUTH_ROOT),
    AUTH_FAILED_REDIRECT="{}/app/auth-error".format(OAUTH_ROOT))

FAILED_AUTH_RESPONSE = AuthenticationResponse(success=False,
                                              err_message="FAILURE!")

SUCCESSFUL_AUTH_RESPONSE = AuthenticationResponse(
    access_token="beep",
    refresh_token="beep?",
    received_at=datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT),
    expires_in=300,  # 5 minutes should be more than enough for testing
    success=True)

NO_REFRESH_AUTH_RESPONSE = AuthenticationResponse(
    access_token="beep",
    received_at=datetime.now().strftime(TOKEN_TIMESTAMP_FORMAT),
    expires_in=300,  # 5 minutes should be more than enough for testing
    success=True)

MALFORMED_AUTH_RESPONSE = AuthenticationResponse(success=False)
예제 #11
0
    def _handleCallback(
        self, query: Dict[Any, List]
    ) -> Tuple[ResponseData, Optional[AuthenticationResponse]]:
        """Handler for the callback URL redirect.

        :param query: Dict containing the HTTP query parameters.
        :return: HTTP ResponseData containing a success page to show to the user.
        """

        code = self._queryGet(query, "code")
        state = self._queryGet(query, "state")
        if state != self.state:
            token_response = AuthenticationResponse(
                success=False,
                err_message=catalog.i18nc(
                    "@message", "The provided state is not correct."))
        elif code and self.authorization_helpers is not None and self.verification_code is not None:
            token_response = AuthenticationResponse(
                success=False,
                err_message=catalog.i18nc(
                    "@message",
                    "Timeout when authenticating with the account server."))
            # If the code was returned we get the access token.
            lock = Lock()
            lock.acquire()

            def callback(response: AuthenticationResponse) -> None:
                nonlocal token_response
                token_response = response
                lock.release()

            self.authorization_helpers.getAccessTokenUsingAuthorizationCode(
                code, self.verification_code, callback)
            lock.acquire(
                timeout=60
            )  # Block thread until request is completed (which releases the lock). If not acquired, the timeout message stays.

        elif self._queryGet(query, "error_code") == "user_denied":
            # Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).
            token_response = AuthenticationResponse(
                success=False,
                err_message=catalog.i18nc(
                    "@message",
                    "Please give the required permissions when authorizing this application."
                ))

        else:
            # We don't know what went wrong here, so instruct the user to check the logs.
            token_response = AuthenticationResponse(
                success=False,
                error_message=catalog.i18nc(
                    "@message",
                    "Something unexpected happened when trying to log in, please try again."
                ))
        if self.authorization_helpers is None:
            return ResponseData(), token_response

        return ResponseData(status=HTTP_STATUS["REDIRECT"],
                            data_stream=b"Redirecting...",
                            redirect_uri=self.authorization_helpers.settings.
                            AUTH_SUCCESS_REDIRECT if token_response.success
                            else self.authorization_helpers.settings.
                            AUTH_FAILED_REDIRECT), token_response