Merge pull request #572 from jonparrott/auth-approval-prompt
Add warnings and helpers for prompt='consent'.
This commit is contained in:
@@ -1770,6 +1770,33 @@ class DeviceFlowInfo(collections.namedtuple('DeviceFlowInfo', (
|
|||||||
return cls(**kwargs)
|
return cls(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def _oauth2_web_server_flow_params(kwargs):
|
||||||
|
"""Configures redirect URI parameters for OAuth2WebServerFlow."""
|
||||||
|
params = {
|
||||||
|
'access_type': 'offline',
|
||||||
|
'response_type': 'code',
|
||||||
|
}
|
||||||
|
|
||||||
|
params.update(kwargs)
|
||||||
|
|
||||||
|
# Check for the presence of the deprecated approval_prompt param and
|
||||||
|
# warn appropriately.
|
||||||
|
approval_prompt = params.get('approval_prompt')
|
||||||
|
if approval_prompt is not None:
|
||||||
|
logger.warning(
|
||||||
|
'The approval_prompt parameter for OAuth2WebServerFlow is '
|
||||||
|
'deprecated. Please use the prompt parameter instead.')
|
||||||
|
|
||||||
|
if approval_prompt == 'force':
|
||||||
|
logger.warning(
|
||||||
|
'approval_prompt="force" has been adjusted to '
|
||||||
|
'prompt="consent"')
|
||||||
|
params['prompt'] = 'consent'
|
||||||
|
del params['approval_prompt']
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
class OAuth2WebServerFlow(Flow):
|
class OAuth2WebServerFlow(Flow):
|
||||||
"""Does the Web Server Flow for OAuth 2.0.
|
"""Does the Web Server Flow for OAuth 2.0.
|
||||||
|
|
||||||
@@ -1793,7 +1820,7 @@ class OAuth2WebServerFlow(Flow):
|
|||||||
"""Constructor for OAuth2WebServerFlow.
|
"""Constructor for OAuth2WebServerFlow.
|
||||||
|
|
||||||
The kwargs argument is used to set extra query parameters on the
|
The kwargs argument is used to set extra query parameters on the
|
||||||
auth_uri. For example, the access_type and approval_prompt
|
auth_uri. For example, the access_type and prompt
|
||||||
query parameters can be set via kwargs.
|
query parameters can be set via kwargs.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -1845,11 +1872,7 @@ class OAuth2WebServerFlow(Flow):
|
|||||||
self.device_uri = device_uri
|
self.device_uri = device_uri
|
||||||
self.token_info_uri = token_info_uri
|
self.token_info_uri = token_info_uri
|
||||||
self.authorization_header = authorization_header
|
self.authorization_header = authorization_header
|
||||||
self.params = {
|
self.params = _oauth2_web_server_flow_params(kwargs)
|
||||||
'access_type': 'offline',
|
|
||||||
'response_type': 'code',
|
|
||||||
}
|
|
||||||
self.params.update(kwargs)
|
|
||||||
|
|
||||||
@util.positional(1)
|
@util.positional(1)
|
||||||
def step1_get_authorize_url(self, redirect_uri=None, state=None):
|
def step1_get_authorize_url(self, redirect_uri=None, state=None):
|
||||||
@@ -2009,7 +2032,7 @@ class OAuth2WebServerFlow(Flow):
|
|||||||
if not refresh_token:
|
if not refresh_token:
|
||||||
logger.info(
|
logger.info(
|
||||||
'Received token response with no refresh_token. Consider '
|
'Received token response with no refresh_token. Consider '
|
||||||
"reauthenticating with approval_prompt='force'.")
|
"reauthenticating with prompt='consent'.")
|
||||||
token_expiry = None
|
token_expiry = None
|
||||||
if 'expires_in' in d:
|
if 'expires_in' in d:
|
||||||
delta = datetime.timedelta(seconds=int(d['expires_in']))
|
delta = datetime.timedelta(seconds=int(d['expires_in']))
|
||||||
|
|||||||
@@ -840,7 +840,7 @@ class DecoratorTests(unittest2.TestCase):
|
|||||||
decorator = appengine.OAuth2Decorator(
|
decorator = appengine.OAuth2Decorator(
|
||||||
client_id='foo_client_id', client_secret='foo_client_secret',
|
client_id='foo_client_id', client_secret='foo_client_secret',
|
||||||
user_agent='foo_user_agent', scope=['foo_scope', 'bar_scope'],
|
user_agent='foo_user_agent', scope=['foo_scope', 'bar_scope'],
|
||||||
access_type='offline', approval_prompt='force',
|
access_type='offline', prompt='consent',
|
||||||
revoke_uri='dummy_revoke_uri')
|
revoke_uri='dummy_revoke_uri')
|
||||||
request_handler = MockRequestHandler()
|
request_handler = MockRequestHandler()
|
||||||
decorator._create_flow(request_handler)
|
decorator._create_flow(request_handler)
|
||||||
@@ -848,7 +848,7 @@ class DecoratorTests(unittest2.TestCase):
|
|||||||
self.assertEqual('https://example.org/oauth2callback',
|
self.assertEqual('https://example.org/oauth2callback',
|
||||||
decorator.flow.redirect_uri)
|
decorator.flow.redirect_uri)
|
||||||
self.assertEqual('offline', decorator.flow.params['access_type'])
|
self.assertEqual('offline', decorator.flow.params['access_type'])
|
||||||
self.assertEqual('force', decorator.flow.params['approval_prompt'])
|
self.assertEqual('consent', decorator.flow.params['prompt'])
|
||||||
self.assertEqual('foo_user_agent', decorator.flow.user_agent)
|
self.assertEqual('foo_user_agent', decorator.flow.user_agent)
|
||||||
self.assertEqual('dummy_revoke_uri', decorator.flow.revoke_uri)
|
self.assertEqual('dummy_revoke_uri', decorator.flow.revoke_uri)
|
||||||
self.assertEqual(None, decorator.flow.params.get('user_agent', None))
|
self.assertEqual(None, decorator.flow.params.get('user_agent', None))
|
||||||
@@ -911,8 +911,8 @@ class DecoratorTests(unittest2.TestCase):
|
|||||||
decorator = appengine.OAuth2DecoratorFromClientSecrets(
|
decorator = appengine.OAuth2DecoratorFromClientSecrets(
|
||||||
datafile('client_secrets.json'),
|
datafile('client_secrets.json'),
|
||||||
scope=['foo_scope', 'bar_scope'],
|
scope=['foo_scope', 'bar_scope'],
|
||||||
approval_prompt='force')
|
prompt='consent')
|
||||||
self.assertTrue('approval_prompt' in decorator._kwargs)
|
self.assertIn('prompt', decorator._kwargs)
|
||||||
|
|
||||||
def test_decorator_from_cached_client_secrets(self):
|
def test_decorator_from_cached_client_secrets(self):
|
||||||
cache_mock = CacheMock()
|
cache_mock = CacheMock()
|
||||||
|
|||||||
@@ -1681,6 +1681,20 @@ class OAuth2WebServerFlowTest(unittest2.TestCase):
|
|||||||
self.assertEqual(client.OOB_CALLBACK_URN, q['redirect_uri'][0])
|
self.assertEqual(client.OOB_CALLBACK_URN, q['redirect_uri'][0])
|
||||||
self.assertEqual('online', q['access_type'][0])
|
self.assertEqual('online', q['access_type'][0])
|
||||||
|
|
||||||
|
def test__oauth2_web_server_flow_params(self):
|
||||||
|
params = client._oauth2_web_server_flow_params({})
|
||||||
|
self.assertEqual(params['access_type'], 'offline')
|
||||||
|
self.assertEqual(params['response_type'], 'code')
|
||||||
|
|
||||||
|
params = client._oauth2_web_server_flow_params({
|
||||||
|
'approval_prompt': 'force'})
|
||||||
|
self.assertEqual(params['prompt'], 'consent')
|
||||||
|
self.assertNotIn('approval_prompt', params)
|
||||||
|
|
||||||
|
params = client._oauth2_web_server_flow_params({
|
||||||
|
'approval_prompt': 'other'})
|
||||||
|
self.assertEqual(params['approval_prompt'], 'other')
|
||||||
|
|
||||||
@mock.patch('oauth2client.client.logger')
|
@mock.patch('oauth2client.client.logger')
|
||||||
def test_step1_get_authorize_url_redirect_override(self, logger):
|
def test_step1_get_authorize_url_redirect_override(self, logger):
|
||||||
flow = client.OAuth2WebServerFlow('client_id+1', scope='foo',
|
flow = client.OAuth2WebServerFlow('client_id+1', scope='foo',
|
||||||
|
|||||||
Reference in New Issue
Block a user