Source code for

import logging
from typing import Any, Dict, Iterable, Optional, Union

from globus_sdk import exc, utils
from globus_sdk.authorizers import NullAuthorizer

from ..flow_managers import GlobusNativeAppFlowManager
from ..response import OAuthTokenResponse
from .base import AuthClient

log = logging.getLogger(__name__)

[docs]class NativeAppAuthClient(AuthClient): """ This type of ``AuthClient`` is used to represent a Native App's communications with Globus Auth. It requires a Client ID, and cannot take an ``authorizer``. Native Apps are applications, like the Globus CLI, which are run client-side and therefore cannot keep secrets. Unable to possess client credentials, several Globus Auth interactions have to be specialized to accommodate the absence of a secret. Any keyword arguments given are passed through to the ``AuthClient`` constructor. .. automethodlist:: globus_sdk.NativeAppAuthClient """ 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)"Finished initializing client, client_id={client_id}")
[docs] @utils.doc_api_method( "The PKCE Security Protocol", "auth/developer-guide/#pkce", external_format_str=( "The Globus Auth specification for Native App grants details modifications " "to the Authorization Code grant flow as `{message} <{base_url}/{link}>`_." ), ) def oauth2_start_flow( self, requested_scopes: Optional[Union[str, Iterable[str]]] = None, *, redirect_uri: Optional[str] = None, state: str = "_default", verifier: Optional[str] = None, refresh_tokens: bool = False, prefill_named_grant: Optional[str] = None, ) -> GlobusNativeAppFlowManager: """ Starts a Native App OAuth2 flow. This is done internally by instantiating a :class:`GlobusNativeAppFlowManager <.GlobusNativeAppFlowManager>` While the flow is in progress, the ``NativeAppAuthClient`` becomes non thread-safe as temporary state is stored during the flow. :param requested_scopes: The scopes on the token(s) being requested, as a space-separated string or iterable of strings. Defaults to ``openid profile email`` :type requested_scopes: str or iterable of str, optional :param redirect_uri: The page that users should be directed to after authenticating at the authorize URL. Defaults to '', which displays the resulting ``auth_code`` for users to copy-paste back into your application (and thereby be passed back to the ``GlobusNativeAppFlowManager``) :param state: The ``redirect_uri`` page will have this included in a query parameter, so you can use it to pass information to that page if you use a custom page. It defaults to the string '_default' :type state: str, optional :param verifier: A secret used for the Native App flow. It will by default be a freshly generated random string, known only to this ``GlobusNativeAppFlowManager`` instance :type verifier: str, optional :param refresh_tokens: When True, request refresh tokens in addition to access tokens. [Default: ``False``] :type refresh_tokens: bool, optional :param prefill_named_grant: Prefill the named grant label on the consent page :type prefill_named_grant: str, optional **Examples** You can see an example of this flow :ref:`in the usage examples <examples_native_app_login>` """"Starting Native App Grant Flow") self.current_oauth2_flow_manager = GlobusNativeAppFlowManager( self, requested_scopes=requested_scopes, redirect_uri=redirect_uri, state=state, verifier=verifier, refresh_tokens=refresh_tokens, prefill_named_grant=prefill_named_grant, ) return self.current_oauth2_flow_manager
[docs] def oauth2_refresh_token( self, refresh_token: str, *, body_params: Optional[Dict[str, Any]] = None ) -> OAuthTokenResponse: """ ``NativeAppAuthClient`` specializes the refresh token grant to include its client ID as a parameter in the POST body. It needs this specialization because it cannot authenticate the refresh grant call with client credentials, as is normal. """"Executing token refresh without client credentials") form_data = { "refresh_token": refresh_token, "grant_type": "refresh_token", "client_id": self.client_id, } return self.oauth2_token(form_data, body_params=body_params)