Ejemplo n.º 1
0
    def get_authorized_tokens(self, oauth_verifier, extra_args=None):
        """
        Returns a dict of authorized tokens after they go through the
        :class:`get_authentication_tokens` phase.

        :param oauth_verifier: (required) The oauth_verifier (or a.k.a PIN for
            non web-apps) retrieved from the callback url querystring
        :rtype: dict
        """
        if self.oauth_version != 1:
            raise ApiError(
                "This method can only be called when your OAuth version is 1.0."
            )

        request_args = {}
        if extra_args:
            for (k, v) in extra_args.items():
                if k not in request_args:
                    request_args[k] = v

        self.client.auth.client.verifier = oauth_verifier
        response = self.client.get(
            self.access_token_url,
            params=request_args,
            headers={"Content-Type": "application/json"},
        )
        self.client.auth.client.verifier = None

        if response.status_code != 200:
            # we already catch these
            if response.status_code not in (400, 401):
                raise ApiError("invalid status code")

        if response.status_code in (400, 401):
            try:
                try:
                    # try to get json
                    content = response.json()
                except AttributeError:  # pragma: no cover
                    # if unicode detected
                    content = json.loads(response.text)
            except ValueError:
                content = {}

            raise ApiError(
                content.get("error", "Invalid / expired Token"),
                error_code=response.status_code,
            )

        # requests: response.text is the decoded response; .content is raw bytes
        # requests/iso-http-spec defaults to latin-1 if no encoding is present
        # we know this is utf-8 because of the oauth spec
        # so we force utf-8 here off the .content
        authorized_tokens = dict(parse_qsl(response.content.decode("utf-8")))
        if not authorized_tokens:
            raise ApiError("Unable to decode authorized tokens.")

        return authorized_tokens  # pragma: no cover
Ejemplo n.º 2
0
        def callback__authorization_base_url_post(req):
            """POST /authority/oauth2/flow-a/authorization is visited by the USER_BROWSER after doing the GET"""
            assert req.url.startswith(
                oauth2_utils.OAUTH2__URL_AUTHORITY_FLOWA_AUTHORIZATION
            )
            payload = dict(parse_qsl(req.body))

            testapp_authority = test_env["testapp_authority"]
            res = testapp_authority.post(
                "/authority/oauth2/flow-a/authorization",
                payload,
                headers=req.headers,
                extra_environ=test_env["extra_environ_authority"],
                status=302,
            )
            test_env["requests_session_authority"].cookies.update(
                testapp_authority.cookies
            )  # update the session with the cookies from the response

            # assume this is a valid request
            # ResponseHeaders([('Location', 'https://app.example.com/application/flow-register/authorized-callback?state=XufmnJbYMKORxkgj1jtfIbojm1YFwm&code=bLE6gTXo7nxvdNlvWzXsIdOh53Xe1f')])

            assert "Location" in res.headers
            _uri_redirect = res.headers["Location"]
            assert _uri_redirect.startswith(
                oauth2_model.OAUTH2__URL_APP_FLOW_REGISTER_CALLBACK
            )

            _base, _qs = _uri_redirect.split("?")
            _qs = dict(parse_qsl(_qs))
            assert _qs.get("state")
            assert _qs.get("code")

            # status is '200 OK'
            # return in a format tailored for `requests`
            return (int(res.status.split(" ")[0]), res.headers, res.body)
Ejemplo n.º 3
0
        def callback__url_revoke_token_post(req):
            assert req.url == oauth2_utils.OAUTH2__URL_AUTHORITY_REVOKE_TOKEN
            payload = dict(parse_qsl(req.body))

            testapp_authority = test_env["testapp_authority"]
            res = testapp_authority.post(
                "/authority/oauth2/revoke_token",
                payload,
                headers=req.headers,
                extra_environ=test_env["extra_environ_authority"],
                status=200,
            )
            test_env["requests_session_authority"].cookies.update(
                testapp_authority.cookies
            )  # update the session with the cookies from the response

            # status is '200 OK'
            # return in a format tailored for `requests`
            return (int(res.status.split(" ")[0]), res.headers, res.body)
Ejemplo n.º 4
0
        def callback__url_token_limited__post(req):
            assert req.url == apiClient._url_token_limited
            payload = dict(parse_qsl(req.body))

            testapp_authority = test_env["testapp_authority"]
            res = testapp_authority.post(
                "/authority/oauth2/flow-c/token_limited",
                payload,
                headers=req.headers,
                extra_environ=test_env["extra_environ_authority"],
                status=400,
            )
            test_env["requests_session_authority"].cookies.update(
                testapp_authority.cookies
            )  # update the session with the cookies from the response

            # status is '200 OK'
            # return in a format tailored for `requests`
            return (int(res.status.split(" ")[0]), res.headers, res.body)
Ejemplo n.º 5
0
        def callback__authenticate_post(req, test_env=test_env):
            """/authority/oauth1/authorize is visited by the USER"""
            assert req.url.startswith(OAUTH1__URL_AUTHORITY_AUTHENTICATE)
            payload = dict(parse_qsl(req.body))

            testapp = test_env["testapp_authority"]
            res = testapp.post(
                "/authority/oauth1/authorize",
                payload,
                headers=req.headers,
                extra_environ=test_env["extra_environ_authority"],
                status=302,
            )
            test_env["requests_session_authority"].cookies.update(
                testapp.cookies
            )  # update the session with the cookies from the response

            # status is '200 OK'
            # return in a format tailored for `requests`
            return (int(res.status.split(" ")[0]), res.headers, res.body)
Ejemplo n.º 6
0
        def callback__token_url_post(req):
            """POST /authority/oauth2/flow-a/token is made by the client (IN THE SERVER) to get a token for the code"""
            assert req.url.startswith(oauth2_utils.OAUTH2__URL_AUTHORITY_FLOWA_TOKEN)
            payload = dict(parse_qsl(req.body))

            _headers = string_headers(
                req.headers
            )  # these can end up being unicode in tests
            testapp_authority = test_env["testapp_authority"]
            res = testapp_authority.post(
                "/authority/oauth2/flow-a/token",
                payload,
                headers=_headers,
                extra_environ=test_env["extra_environ_authority"],
                status=200,
            )
            test_env["requests_session_authority"].cookies.update(
                testapp_authority.cookies
            )  # update the session with the cookies from the response

            return (int(res.status.split(" ")[0]), res.headers, res.body)
Ejemplo n.º 7
0
    def get_authentication_tokens(
        self, callback_url=None, extra_args=None, force_login=False
    ):
        """
        Returns a dict including an authorization URL, ``auth_url``, to
        direct a user to

        :param callback_url: (optional) Url the user is returned to after
                             they authorize your app (web clients only)
        :param force_login: (optional) Forces the user to enter their
                            credentials to ensure the correct users
                            account is authorized.
        :rtype: dict

        """
        if self.oauth_version != 1:
            raise ApiError(
                "This method can only be called when your \
                               OAuth version is 1.0."
            )

        # we toggle this in, then fix
        _callback_uri_old = self.client.auth.client.callback_uri
        if callback_url:
            # python2 - this can be unicode or string
            # python3 - no issues i think
            if isinstance(callback_url, six.text_type):
                callback_url = callback_url
            else:
                callback_url = six.u(callback_url)
            self.client.auth.client.callback_uri = callback_url

        request_args = {}
        if extra_args:
            for (k, v) in extra_args.items():
                if k not in request_args:
                    request_args[k] = v

        response = self.client.get(self.request_token_url, params=request_args)
        if callback_url:
            self.client.auth.client.callback_uri = _callback_uri_old

        if response.status_code == 401:
            # requests: response.text is the decoded response; .content is raw bytes
            raise ApiAuthError(response.text, error_code=response.status_code)
        elif response.status_code != 200:
            # requests: response.text is the decoded response; .content is raw bytes
            raise ApiError(response.text, error_code=response.status_code)

        # requests: response.text is the decoded response; .content is raw bytes
        # requests/iso-http-spec defaults to latin-1 if no encoding is present
        # we know this is utf-8 because of the oauth spec
        # so we force utf-8 here off the .content
        request_tokens = dict(parse_qsl(response.content.decode("utf-8")))
        if not request_tokens:
            raise ApiError("Unable to decode request tokens.")

        oauth_callback_confirmed = (
            request_tokens.get("oauth_callback_confirmed") == "true"
        )

        auth_url_params = {"oauth_token": request_tokens["oauth_token"]}

        # Use old-style callback argument if server didn't accept new-style
        if callback_url and not oauth_callback_confirmed:
            auth_url_params["oauth_callback"] = self.callback_url

        request_tokens["auth_url"] = (
            self.authenticate_url + "?" + urlencode(auth_url_params, True)
        )

        return request_tokens