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)
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
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
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}")
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
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
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)
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)