示例#1
0
    def oauth2_exchange_code_for_tokens(self, auth_code):
        """
        Exchange an authorization code for a token or tokens.

        :rtype: :class:`OAuthTokenResponse \
        <globus_sdk.auth.token_response.OAuthTokenResponse>`

        :param auth_code: An auth code typically obtained by sending the user to the
            authorize URL. The code is a very short-lived credential which this method
            is exchanging for tokens. Tokens are the credentials used to authenticate
            against Globus APIs.
        :type auth_code: str
        """
        self.logger.info(("Final Step of 3-legged OAuth2 Flows: "
                          "Exchanging authorization code for token(s)"))
        if not self.current_oauth2_flow_manager:
            self.logger.error(("OutOfOrderOperations("
                               "exchange_code before start_flow)"))
            raise exc.GlobusSDKUsageError(
                ("Cannot exchange auth code until starting an OAuth2 flow. "
                 "Call the oauth2_start_flow() method on this "
                 "AuthClient to resolve"))

        return self.current_oauth2_flow_manager.exchange_code_for_tokens(
            auth_code)
示例#2
0
    def oauth2_get_authorize_url(self,
                                 *,
                                 query_params: Optional[Dict[str, Any]] = None
                                 ) -> str:
        """
        Get the authorization URL to which users should be sent.
        This method may only be called after ``oauth2_start_flow``
        has been called on this ``AuthClient``.

        :param query_params: Additional query parameters to include in the
            authorize URL. Primarily for internal use
        :type query_params: dict, optional
        :rtype: ``string``
        """
        if not self.current_oauth2_flow_manager:
            log.error(
                "OutOfOrderOperations(get_authorize_url before start_flow)")
            raise exc.GlobusSDKUsageError(
                "Cannot get authorize URL until starting an OAuth2 flow. "
                "Call the oauth2_start_flow() method on this "
                "AuthClient to resolve")
        auth_url = self.current_oauth2_flow_manager.get_authorize_url(
            query_params=query_params)
        log.info(f"Got authorization URL: {auth_url}")
        return auth_url
示例#3
0
    def oauth2_get_authorize_url(self, additional_params=None):
        """
        Get the authorization URL to which users should be sent.
        This method may only be called after ``oauth2_start_flow``
        has been called on this ``AuthClient``.

        **Parameters**

            ``additional_params`` (*dict*)
              A ``dict`` or ``None``, which specifies additional query
              parameters to include in the authorize URL. Primarily for
              internal use

        :rtype: ``string``
        """
        if not self.current_oauth2_flow_manager:
            self.logger.error(('OutOfOrderOperations('
                               'get_authorize_url before start_flow)'))
            raise exc.GlobusSDKUsageError(
                ('Cannot get authorize URL until starting an OAuth2 flow. '
                 'Call the oauth2_start_flow() method on this '
                 'AuthClient to resolve'))
        auth_url = self.current_oauth2_flow_manager.get_authorize_url(
            additional_params=additional_params)
        self.logger.info('Got authorization URL: {0}'.format(auth_url))
        return auth_url
示例#4
0
    def __init__(
        self,
        access_token: Optional[str] = None,
        expires_at: Optional[int] = None,
        on_refresh: Optional[Callable[["OAuthTokenResponse"], Any]] = None,
    ):
        self._access_token = None
        self._access_token_hash = None

        log.info("Setting up a RenewingAuthorizer. It will use an "
                 "auth type of Bearer and can handle 401s.")

        if (access_token is not None
                and expires_at is None) or (access_token is None
                                            and expires_at is not None):
            raise exc.GlobusSDKUsageError(
                "A RenewingAuthorizer cannot be initialized with one of "
                "access_token and expires_at. Either provide both or neither.")

        self.access_token = access_token
        self.expires_at = expires_at
        self.on_refresh = on_refresh

        if self.access_token is not None:
            log.info("RenewingAuthorizer will start by using access_token "
                     f'with hash "{self._access_token_hash}"')
        # if data were unspecified, fetch a new access token
        else:
            log.info("Creating RenewingAuthorizer without Access "
                     "Token. Fetching initial token now.")
            self._get_new_access_token()
    def __init__(self, client_id: str, **kwargs: Any) -> None:
        if "authorizer" in kwargs:
            log.error("ArgumentError(NativeAppClient.authorizer)")
            raise exc.GlobusSDKUsageError(
                "Cannot give a NativeAppAuthClient an authorizer"
            )

        super().__init__(client_id=client_id, authorizer=NullAuthorizer(), **kwargs)
        log.info(f"Finished initializing client, client_id={client_id}")
 def __init__(self, client_id: str, client_secret: str, **kwargs: Any):
     if "authorizer" in kwargs:
         log.error("ArgumentError(ConfidentialAppClient.authorizer)")
         raise exc.GlobusSDKUsageError(
             "Cannot give a ConfidentialAppAuthClient an authorizer")
     super().__init__(
         client_id=client_id,
         authorizer=BasicAuthorizer(client_id, client_secret),
         **kwargs,
     )
     log.info(f"Finished initializing client, client_id={client_id}")
示例#7
0
    def decode_id_token(
        self,
        openid_configuration: Optional[Union[GlobusHTTPResponse,
                                             Dict[str, Any]]] = None,
        jwk: Optional[RSAPublicKey] = None,
        jwt_params: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        """
        Parse the included ID Token (OIDC) as a dict and return it.

        If you provide the `jwk`, you must also provide `openid_configuration`.

        :param openid_configuration: The OIDC config as a GlobusHTTPResponse or dict.
            When not provided, it will be fetched automatically.
        :type openid_configuration: dict or GlobusHTTPResponse
        :param jwk: The JWK as a cryptography public key object. When not provided, it
            will be fetched and parsed automatically.
        :type jwk: RSAPublicKey
        :param jwt_params: An optional dict of parameters to pass to the jwt decode
            step. These are passed verbatim to the jwt library.
        :type jwt_params: dict
        """
        logger.info('Decoding ID Token "%s"', self["id_token"])
        auth_client = cast("AuthClient", self.client)

        jwt_params = jwt_params or {}

        if not openid_configuration:
            if jwk:
                raise exc.GlobusSDKUsageError(
                    "passing jwk without openid configuration is not allowed")
            logger.debug("No OIDC Config provided, autofetching...")
            oidc_config: Union[GlobusHTTPResponse, Dict[
                str, Any]] = auth_client.get_openid_configuration()
        else:
            oidc_config = openid_configuration

        if not jwk:
            logger.debug("No JWK provided, autofetching + decoding...")
            jwk = auth_client.get_jwk(openid_configuration=oidc_config,
                                      as_pem=True)

        logger.debug("final step: decode with JWK")
        signing_algos = oidc_config["id_token_signing_alg_values_supported"]
        decoded = jwt.decode(
            self["id_token"],
            key=jwk,
            algorithms=signing_algos,
            audience=auth_client.client_id,
            options=jwt_params,
        )
        logger.debug("decode ID token finished successfully")
        return decoded
示例#8
0
    def oauth2_get_authorize_url(self, additional_params=None):
        """
        Get the authorization URL to which users should be sent.
        This method may only be called after ``oauth2_start_flow``
        has been called on this ``AuthClient``.

        :param additional_params: Additional query parameters to include in the
            authorize URL. Primarily for internal use
        :type additional_params: dict, optional
        :rtype: ``string``
        """
        if not self.current_oauth2_flow_manager:
            self.logger.error(("OutOfOrderOperations("
                               "get_authorize_url before start_flow)"))
            raise exc.GlobusSDKUsageError(
                ("Cannot get authorize URL until starting an OAuth2 flow. "
                 "Call the oauth2_start_flow() method on this "
                 "AuthClient to resolve"))
        auth_url = self.current_oauth2_flow_manager.get_authorize_url(
            additional_params=additional_params)
        self.logger.info("Got authorization URL: {}".format(auth_url))
        return auth_url
示例#9
0
    def __init__(self,
                 service,
                 environment=None,
                 base_url=None,
                 base_path=None,
                 authorizer=None,
                 app_name=None,
                 http_timeout=None,
                 *args,
                 **kwargs):
        self._init_logger_adapter()
        self.logger.info('Creating client of type {} for service "{}"'.format(
            type(self), service))
        # if restrictions have been placed by a child class on the allowed
        # authorizer types, make sure we are not in violation of those
        # constraints
        if self.allowed_authorizer_types is not None and (
                authorizer is not None
                and type(authorizer) not in self.allowed_authorizer_types):
            self.logger.error("{} doesn't support authorizer={}".format(
                type(self), type(authorizer)))
            raise exc.GlobusSDKUsageError(
                ("{0} can only take authorizers from {1}, "
                 "but you have provided {2}").format(
                     type(self), self.allowed_authorizer_types,
                     type(authorizer)))

        # defer this default until instantiation time so that logging can
        # capture the execution of the config load
        if environment is None:
            environment = config.get_default_environ()

        self.environment = environment
        self.authorizer = authorizer

        if base_url is None:
            self.base_url = config.get_service_url(environment, service)
        else:
            self.base_url = base_url
        if base_path is not None:
            self.base_url = slash_join(self.base_url, base_path)

        # setup the basics for wrapping a Requests Session
        # including basics for internal header dict
        self._session = requests.Session()
        self._headers = {
            'Accept': 'application/json',
            'User-Agent': self.BASE_USER_AGENT
        }

        # verify SSL? Usually true
        self._verify = config.get_ssl_verify(environment)
        # HTTP connection timeout
        # this is passed verbatim to `requests`, and we therefore technically
        # support a tuple for connect/read timeouts, but we don't need to
        # advertise that... Just declare it as an float value
        if http_timeout is None:
            http_timeout = config.get_http_timeout(environment)
        self._http_timeout = http_timeout
        # handle -1 by passing None to requests
        if self._http_timeout == -1:
            self._http_timeout = None

        # set application name if given
        self.app_name = None
        if app_name is not None:
            self.set_app_name(app_name)
示例#10
0
    def __init__(
        self,
        service,
        environment=None,
        base_url=None,
        base_path=None,
        authorizer=None,
        app_name=None,
        http_timeout=None,
        *args,
        **kwargs
    ):
        self._init_logger_adapter()
        self.logger.info(
            'Creating client of type {} for service "{}"'.format(type(self), service)
        )
        # if restrictions have been placed by a child class on the allowed
        # authorizer types, make sure we are not in violation of those
        # constraints
        if self.allowed_authorizer_types is not None and (
            authorizer is not None
            and type(authorizer) not in self.allowed_authorizer_types
        ):
            self.logger.error(
                "{} doesn't support authorizer={}".format(type(self), type(authorizer))
            )
            raise exc.GlobusSDKUsageError(
                (
                    "{0} can only take authorizers from {1}, "
                    "but you have provided {2}"
                ).format(type(self), self.allowed_authorizer_types, type(authorizer))
            )

        # if an environment was passed, it will be used, but otherwise lookup
        # the env var -- and in the special case of `production` translate to
        # `default`, regardless of the source of that value
        # logs the environment when it isn't `default`
        self.environment = config.get_globus_environ(inputenv=environment)

        self.authorizer = authorizer

        if base_url is None:
            self.base_url = config.get_service_url(self.environment, service)
        else:
            self.base_url = base_url
        self.base_url = slash_join(self.base_url, base_path)

        # setup the basics for wrapping a Requests Session
        # including basics for internal header dict
        self._session = requests.Session()
        self._headers = {
            "Accept": "application/json",
            "User-Agent": self.BASE_USER_AGENT,
        }

        # verify SSL? Usually true
        self._verify = config.get_ssl_verify(self.environment)
        # HTTP connection timeout
        # this is passed verbatim to `requests`, and we therefore technically
        # support a tuple for connect/read timeouts, but we don't need to
        # advertise that... Just declare it as an float value
        if http_timeout is None:
            http_timeout = config.get_http_timeout(self.environment)
        self._http_timeout = http_timeout
        # handle -1 by passing None to requests
        if self._http_timeout == -1:
            self._http_timeout = None

        # set application name if given
        self.app_name = None
        if app_name is not None:
            self.set_app_name(app_name)