From cde632bf5739c5614d218419fe9df4787756363e Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Tue, 17 Mar 2026 11:12:17 -0400 Subject: [PATCH 1/2] Add suggestion to use cross-device workflow too 'aws login' and 'aws sso login' --- .../next-release/enhancement-SSO-20061.json | 5 ++++ awscli/botocore/utils.py | 2 ++ awscli/customizations/login/utils.py | 1 + awscli/customizations/sso/utils.py | 23 ++++++++++++++----- tests/unit/botocore/test_utils.py | 1 + tests/unit/customizations/sso/test_utils.py | 1 + 6 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 .changes/next-release/enhancement-SSO-20061.json diff --git a/.changes/next-release/enhancement-SSO-20061.json b/.changes/next-release/enhancement-SSO-20061.json new file mode 100644 index 000000000000..0911fb078773 --- /dev/null +++ b/.changes/next-release/enhancement-SSO-20061.json @@ -0,0 +1,5 @@ +{ + "type": "enhancement", + "category": "SSO", + "description": "Add suggestion to use ``--use-device-code`` for ``aws sso login`` and ``--remote`` for ``aws login`` for users who are unable to open the URL on the same device" +} diff --git a/awscli/botocore/utils.py b/awscli/botocore/utils.py index 078a0399ce87..dbbfcd66abb1 100644 --- a/awscli/botocore/utils.py +++ b/awscli/botocore/utils.py @@ -3405,6 +3405,7 @@ def _authorize_client(self, start_url, registration): 'verificationUri': response['verificationUri'], 'verificationUriComplete': response['verificationUriComplete'], 'expiresAt': self._time_fetcher() + expires_in, + 'cross_device_flag': None, } if 'interval' in response: authorization['interval'] = response['interval'] @@ -3682,6 +3683,7 @@ def _get_new_token(self, start_url, session_name, registration_scopes): 'verificationUri': authorization_uri, 'verificationUriComplete': authorization_uri, 'userCode': None, + 'cross_device_flag': '--use-device-code', } # Open/display the link, then block until the redirect uri is hit and diff --git a/awscli/customizations/login/utils.py b/awscli/customizations/login/utils.py index 4a50053e6783..ca74d4fb729b 100644 --- a/awscli/customizations/login/utils.py +++ b/awscli/customizations/login/utils.py @@ -85,6 +85,7 @@ def _get_browser_handler_args(authorization_uri): 'verificationUri': authorization_uri, 'verificationUriComplete': authorization_uri, 'userCode': None, + 'cross_device_flag': '--remote', } def _exchange_auth_code_for_access_token( diff --git a/awscli/customizations/sso/utils.py b/awscli/customizations/sso/utils.py index 94062460f55d..4ee71ad85d7a 100644 --- a/awscli/customizations/sso/utils.py +++ b/awscli/customizations/sso/utils.py @@ -136,7 +136,12 @@ def open_browser_with_original_ld_path(url): class BaseAuthorizationhandler: def __call__( - self, userCode, verificationUri, verificationUriComplete, **kwargs + self, + userCode, + verificationUri, + verificationUriComplete, + cross_device_flag, + **kwargs, ): # Pending authorization handlers should always take **kwargs in case # the API begins to return new values. @@ -177,7 +182,12 @@ def __init__(self, outfile=None, open_browser=None): self._open_browser = open_browser def __call__( - self, userCode, verificationUri, verificationUriComplete, **kwargs + self, + userCode, + verificationUri, + verificationUriComplete, + cross_device_flag, + **kwargs, ): if userCode: # only the device code flow supports different devices opening_msg = ( @@ -189,10 +199,11 @@ def __call__( ) else: opening_msg = ( - f'Attempting to open your default browser.\n' - f'If the browser does not open, open ' - f'the following URL:\n' - f'\n{verificationUri}\n' + f'Attempting to open your default browser. ' + f'If the browser does not open, open the following URL.\n' + f'If you are unable to open the URL on this device, ' + f'run this command again with the \'{cross_device_flag}\' option.\n' + f'\n{verificationUri}\n\n' ) user_code_msg = f'\nThen enter the code:\n\n{userCode}\n' diff --git a/tests/unit/botocore/test_utils.py b/tests/unit/botocore/test_utils.py index 4d05764741c8..fcf4dac630ec 100644 --- a/tests/unit/botocore/test_utils.py +++ b/tests/unit/botocore/test_utils.py @@ -3635,6 +3635,7 @@ def test_on_pending_authorization_callback_called(self): expiresAt=self._expires_at(600), verificationUri='https://sso.fake/device', verificationUriComplete='https://sso.fake/device?user_code=foo', + cross_device_flag='--use-device-code', ) def test_fetch_token_authorization_expires(self): diff --git a/tests/unit/customizations/sso/test_utils.py b/tests/unit/customizations/sso/test_utils.py index c75669709039..647132b8e143 100644 --- a/tests/unit/customizations/sso/test_utils.py +++ b/tests/unit/customizations/sso/test_utils.py @@ -154,6 +154,7 @@ def setUp(self): 'userCode': self.user_code, 'verificationUri': self.verification_uri, 'verificationUriComplete': self.verification_uri_complete, + 'cross_device_flag': '--use-device-code', } def assert_text_in_output(self, *args): From 5c672ac120a1b4e25ed073d44ae02257f2844655 Mon Sep 17 00:00:00 2001 From: Alex Shovlin Date: Tue, 17 Mar 2026 14:04:06 -0400 Subject: [PATCH 2/2] Fix expected call in test --- tests/unit/botocore/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/botocore/test_utils.py b/tests/unit/botocore/test_utils.py index fcf4dac630ec..a7d47d714f2d 100644 --- a/tests/unit/botocore/test_utils.py +++ b/tests/unit/botocore/test_utils.py @@ -3635,7 +3635,7 @@ def test_on_pending_authorization_callback_called(self): expiresAt=self._expires_at(600), verificationUri='https://sso.fake/device', verificationUriComplete='https://sso.fake/device?user_code=foo', - cross_device_flag='--use-device-code', + cross_device_flag=None, ) def test_fetch_token_authorization_expires(self):