Repository: globus/globus-sdk-python

Issue:
Add `prefill_named_grant` support to NativeApp grant flow
Per globus/globus-cli#176 , there's an option to prefill the named grant label, `prefill_named_grant`. It's probably a string.

We need to support this so that the CLI and similar applications can use it.

Not considering this blocked on documentation.

Discussion:

Patch:
diff --git a/globus_sdk/auth/client_types/native_client.py b/globus_sdk/auth/client_types/native_client.py
index 0f8da1d3..e2ab435e 100644
--- a/globus_sdk/auth/client_types/native_client.py
+++ b/globus_sdk/auth/client_types/native_client.py
@@ -46,7 +46,8 @@ class NativeAppAuthClient(AuthClient):
 
     def oauth2_start_flow(
             self, requested_scopes=None, redirect_uri=None,
-            state='_default', verifier=None, refresh_tokens=False):
+            state='_default', verifier=None, refresh_tokens=False,
+            prefill_named_grant=None):
         """
         Starts a Native App OAuth2 flow by instantiating a
         :class:`GlobusNativeAppFlowManager
@@ -61,7 +62,8 @@ class NativeAppAuthClient(AuthClient):
         self.current_oauth2_flow_manager = GlobusNativeAppFlowManager(
             self, requested_scopes=requested_scopes,
             redirect_uri=redirect_uri, state=state, verifier=verifier,
-            refresh_tokens=refresh_tokens)
+            refresh_tokens=refresh_tokens,
+            prefill_named_grant=prefill_named_grant)
         return self.current_oauth2_flow_manager
 
     def oauth2_refresh_token(self, refresh_token):
diff --git a/globus_sdk/auth/oauth2_native_app.py b/globus_sdk/auth/oauth2_native_app.py
index b53f77a7..daa8f4d7 100644
--- a/globus_sdk/auth/oauth2_native_app.py
+++ b/globus_sdk/auth/oauth2_native_app.py
@@ -77,11 +77,14 @@ class GlobusNativeAppFlowManager(GlobusOAuthFlowManager):
 
         ``refresh_tokens`` (*bool*)
           When True, request refresh tokens in addition to access tokens
+
+          ``prefill_named_grant`` (*string*)
+          Optionally prefill the named grant label on the consent page
     """
 
     def __init__(self, auth_client, requested_scopes=None,
                  redirect_uri=None, state='_default', verifier=None,
-                 refresh_tokens=False):
+                 refresh_tokens=False, prefill_named_grant=None):
         self.auth_client = auth_client
 
         # set client_id, then check for validity
@@ -109,6 +112,7 @@ class GlobusNativeAppFlowManager(GlobusOAuthFlowManager):
         # store the remaining parameters directly, with no transformation
         self.refresh_tokens = refresh_tokens
         self.state = state
+        self.prefill_named_grant = prefill_named_grant
 
         logger.debug('Starting Native App Flow with params:')
         logger.debug('auth_client.client_id={}'.format(auth_client.client_id))
@@ -118,6 +122,10 @@ class GlobusNativeAppFlowManager(GlobusOAuthFlowManager):
         logger.debug('requested_scopes={}'.format(self.requested_scopes))
         logger.debug('verifier=<REDACTED>,challenge={}'.format(self.challenge))
 
+        if prefill_named_grant is not None:
+            logger.debug('prefill_named_grant={}'.format(
+                self.prefill_named_grant))
+
     def get_authorize_url(self, additional_params=None):
         """
         Start a Native App flow by getting the authorization URL to which users
@@ -153,6 +161,8 @@ class GlobusNativeAppFlowManager(GlobusOAuthFlowManager):
             'code_challenge_method': 'S256',
             'access_type': (self.refresh_tokens and 'offline') or 'online'
         }
+        if self.prefill_named_grant is not None:
+            params['prefill_named_grant'] = self.prefill_named_grant
         if additional_params:
             params.update(additional_params)
 


Test patch:
diff --git a/tests/unit/test_oauth2_native_app.py b/tests/unit/test_oauth2_native_app.py
index 1403795d..0826a81f 100644
--- a/tests/unit/test_oauth2_native_app.py
+++ b/tests/unit/test_oauth2_native_app.py
@@ -81,6 +81,27 @@ class GlobusNativeAppFlowManagerTests(CapturedIOTestCase):
         for param, value in params.items():
             self.assertIn(param + "=" + value, param_url)
 
+    def test_prefill_named_grant(self):
+        """
+        Should add the `prefill_named_grant` query string parameter
+        to the authorize url.
+        """
+        flow_with_prefill = globus_sdk.auth.GlobusNativeAppFlowManager(
+            self.ac, requested_scopes="scopes", redirect_uri="uri",
+            state="state", verifier="verifier", prefill_named_grant="test")
+
+        authorize_url = flow_with_prefill.get_authorize_url()
+
+        self.assertIn('prefill_named_grant=test', authorize_url)
+
+        flow_without_prefill = globus_sdk.auth.GlobusNativeAppFlowManager(
+            self.ac, requested_scopes="scopes", redirect_uri="uri",
+            state="state", verifier="verifier")
+
+        authorize_url = flow_without_prefill.get_authorize_url()
+
+        self.assertNotIn('prefill_named_grant=', authorize_url)
+
     def test_exchange_code_for_tokens(self):
         """
         Makes a token exchange with the mock AuthClient,