Skip to content

Commit 1391486

Browse files
authored
fix: Remove deprecated OOB code (#264)
* fix: Remove deprecated OOB code * Removing more oob references
1 parent bd7a36e commit 1391486

File tree

6 files changed

+5
-153
lines changed

6 files changed

+5
-153
lines changed

google_auth_oauthlib/flow.py

+2-76
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import hashlib
5353
import json
5454
import logging
55-
import warnings
5655

5756
try:
5857
from secrets import SystemRandom
@@ -70,11 +69,6 @@
7069

7170

7271
_LOGGER = logging.getLogger(__name__)
73-
_OOB_REDIRECT_URIS = [
74-
"urn:ietf:wg:oauth:2.0:oob",
75-
"urn:ietf:wg:oauth:2.0:oob:auto",
76-
"oob",
77-
]
7872

7973

8074
class Flow(object):
@@ -214,17 +208,8 @@ def redirect_uri(self):
214208

215209
@redirect_uri.setter
216210
def redirect_uri(self, value):
217-
if value in _OOB_REDIRECT_URIS:
218-
warnings.warn(
219-
"'{}' is an OOB redirect URI. The OAuth out-of-band (OOB) flow is deprecated. "
220-
"New clients will be unable to use this flow starting on Feb 28, 2022. "
221-
"This flow will be deprecated for all clients on Oct 3, 2022. "
222-
"Migrate to an alternative flow. "
223-
"See https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html?m=1#disallowed-oob".format(
224-
value
225-
),
226-
DeprecationWarning,
227-
)
211+
"""The OAuth 2.0 redirect URI. Pass-through to
212+
``self.oauth2session.redirect_uri``."""
228213
self.oauth2session.redirect_uri = value
229214

230215
def authorization_url(self, **kwargs):
@@ -370,8 +355,6 @@ class InstalledAppFlow(Flow):
370355
https://github.com/googleapis/google-api-python-client/blob/main/docs/oauth-installed.md
371356
"""
372357

373-
_OOB_REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"
374-
375358
_DEFAULT_AUTH_PROMPT_MESSAGE = (
376359
"Please visit this URL to authorize this application: {url}"
377360
)
@@ -385,63 +368,6 @@ class InstalledAppFlow(Flow):
385368
"The authentication flow has completed. You may close this window."
386369
)
387370

388-
def run_console(
389-
self,
390-
authorization_prompt_message=_DEFAULT_AUTH_PROMPT_MESSAGE,
391-
authorization_code_message=_DEFAULT_AUTH_CODE_MESSAGE,
392-
**kwargs
393-
):
394-
"""Run the flow using the console strategy.
395-
396-
.. deprecated:: 0.5.0
397-
Use :meth:`run_local_server` instead.
398-
399-
The OAuth out-of-band (OOB) flow is deprecated. New clients will be unable to
400-
use this flow starting on Feb 28, 2022. This flow will be deprecated
401-
for all clients on Oct 3, 2022. Migrate to an alternative flow.
402-
403-
See https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html?m=1#disallowed-oob"
404-
405-
The console strategy instructs the user to open the authorization URL
406-
in their browser. Once the authorization is complete the authorization
407-
server will give the user a code. The user then must copy & paste this
408-
code into the application. The code is then exchanged for a token.
409-
410-
Args:
411-
authorization_prompt_message (str | None): The message to display to tell
412-
the user to navigate to the authorization URL. If None or empty,
413-
don't display anything.
414-
authorization_code_message (str): The message to display when
415-
prompting the user for the authorization code.
416-
kwargs: Additional keyword arguments passed through to
417-
:meth:`authorization_url`.
418-
419-
Returns:
420-
google.oauth2.credentials.Credentials: The OAuth 2.0 credentials
421-
for the user.
422-
"""
423-
kwargs.setdefault("prompt", "consent")
424-
warnings.warn(
425-
"New clients will be unable to use `InstalledAppFlow.run_console` "
426-
"starting on Feb 28, 2022. All clients will be unable to use this method starting on Oct 3, 2022. "
427-
"Use `InstalledAppFlow.run_local_server` instead. For details on the OOB flow deprecation, "
428-
"see https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html?m=1#disallowed-oob",
429-
DeprecationWarning,
430-
)
431-
432-
self.redirect_uri = self._OOB_REDIRECT_URI
433-
434-
auth_url, _ = self.authorization_url(**kwargs)
435-
436-
if authorization_prompt_message:
437-
print(authorization_prompt_message.format(url=auth_url))
438-
439-
code = input(authorization_code_message)
440-
441-
self.fetch_token(code=code)
442-
443-
return self.credentials
444-
445371
def run_local_server(
446372
self,
447373
host="localhost",

google_auth_oauthlib/interactive.py

-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ def get_user_credentials(
156156
"installed": {
157157
"client_id": client_id,
158158
"client_secret": client_secret,
159-
"redirect_uris": ["urn:ietf:wg:oauth:2.0:oob"],
160159
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
161160
"token_uri": "https://oauth2.googleapis.com/token",
162161
}

google_auth_oauthlib/tool/__main__.py

+3-16
Original file line numberDiff line numberDiff line change
@@ -72,25 +72,15 @@
7272
default=os.path.join(click.get_app_dir(APP_NAME), DEFAULT_CREDENTIALS_FILENAME),
7373
help="Path to store OAuth2 credentials.",
7474
)
75-
@click.option(
76-
"--headless",
77-
is_flag=True,
78-
metavar="<headless_mode>",
79-
show_default=True,
80-
default=False,
81-
help="Run a console based flow.",
82-
)
83-
def main(client_secrets, scope, save, credentials, headless):
75+
def main(client_secrets, scope, save, credentials):
8476
"""Command-line tool for obtaining authorization and credentials from a user.
8577
8678
This tool uses the OAuth 2.0 Authorization Code grant as described
8779
in section 1.3.1 of RFC6749:
8880
https://tools.ietf.org/html/rfc6749#section-1.3.1
8981
9082
This tool is intended for assist developers in obtaining credentials
91-
for testing applications where it may not be possible or easy to run a
92-
complete OAuth 2.0 authorization flow, especially in the case of code
93-
samples or embedded devices without input / display capabilities.
83+
for testing applications or samples.
9484
9585
This is not intended for production use where a combination of
9686
companion and on-device applications should complete the OAuth 2.0
@@ -102,10 +92,7 @@ def main(client_secrets, scope, save, credentials, headless):
10292
client_secrets, scopes=scope
10393
)
10494

105-
if not headless:
106-
creds = flow.run_local_server()
107-
else:
108-
creds = flow.run_console()
95+
creds = flow.run_local_server()
10996

11097
creds_data = {
11198
"token": creds.token,

tests/unit/data/client_secrets.json

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
88
"client_secret": "itsasecrettoeveryone",
99
"redirect_uris": [
10-
"urn:ietf:wg:oauth:2.0:oob",
1110
"http://localhost"
1211
]
1312
}

tests/unit/test_flow.py

-33
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,6 @@ def test_from_client_secrets_file_with_redirect_uri(self):
5858
== mock.sentinel.redirect_uri
5959
)
6060

61-
def test_from_client_secrets_file_with_oob_redirect_uri(self):
62-
with pytest.deprecated_call():
63-
instance = flow.Flow.from_client_secrets_file(
64-
CLIENT_SECRETS_FILE,
65-
scopes=mock.sentinel.scopes,
66-
redirect_uri="urn:ietf:wg:oauth:2.0:oob",
67-
)
68-
69-
assert (
70-
instance.redirect_uri
71-
== instance.oauth2session.redirect_uri
72-
== "urn:ietf:wg:oauth:2.0:oob"
73-
)
74-
7561
def test_from_client_config_installed(self):
7662
client_config = {"installed": CLIENT_SECRETS_INFO["web"]}
7763
instance = flow.Flow.from_client_config(
@@ -296,25 +282,6 @@ def set_token(*args, **kwargs):
296282
with fetch_token_patch as fetch_token_mock:
297283
yield fetch_token_mock
298284

299-
@mock.patch("builtins.input", autospec=True)
300-
def test_run_console(self, input_mock, instance, mock_fetch_token):
301-
input_mock.return_value = mock.sentinel.code
302-
instance.code_verifier = "amanaplanacanalpanama"
303-
304-
with pytest.deprecated_call():
305-
credentials = instance.run_console()
306-
307-
assert credentials.token == mock.sentinel.access_token
308-
assert credentials._refresh_token == mock.sentinel.refresh_token
309-
assert credentials.id_token == mock.sentinel.id_token
310-
311-
mock_fetch_token.assert_called_with(
312-
CLIENT_SECRETS_INFO["web"]["token_uri"],
313-
client_secret=CLIENT_SECRETS_INFO["web"]["client_secret"],
314-
code=mock.sentinel.code,
315-
code_verifier="amanaplanacanalpanama",
316-
)
317-
318285
@pytest.mark.webtest
319286
@mock.patch("google_auth_oauthlib.flow.webbrowser", autospec=True)
320287
def test_run_local_server(self, webbrowser_mock, instance, mock_fetch_token, port):

tests/unit/test_tool.py

-26
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,6 @@ def local_server_mock(self, dummy_credentials):
5757
flow.return_value = dummy_credentials
5858
yield flow
5959

60-
@pytest.fixture
61-
def console_mock(self, dummy_credentials):
62-
run_console_patch = mock.patch.object(
63-
google_auth_oauthlib.flow.InstalledAppFlow, "run_console", autospec=True
64-
)
65-
66-
with run_console_patch as flow:
67-
flow.return_value = dummy_credentials
68-
yield flow
69-
7060
def test_help(self, runner):
7161
result = runner.invoke(cli.main, ["--help"])
7262
assert not result.exception
@@ -91,22 +81,6 @@ def test_defaults(self, runner, dummy_credentials, local_server_mock):
9181
assert creds.client_secret == dummy_credentials.client_secret
9282
assert creds.scopes == dummy_credentials.scopes
9383

94-
def test_headless(self, runner, dummy_credentials, console_mock):
95-
result = runner.invoke(
96-
cli.main,
97-
[
98-
"--client-secrets",
99-
CLIENT_SECRETS_FILE,
100-
"--scope",
101-
"somescope",
102-
"--headless",
103-
],
104-
)
105-
console_mock.assert_called_with(mock.ANY)
106-
assert not result.exception
107-
assert dummy_credentials.refresh_token in result.output
108-
assert result.exit_code == 0
109-
11084
def test_save_new_dir(self, runner, dummy_credentials, local_server_mock):
11185
credentials_tmpdir = tempfile.mkdtemp()
11286
credentials_path = os.path.join(

0 commit comments

Comments
 (0)