Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-google-auth-oauthlib for openSUSE:Factory checked in at 2026-03-04 21:10:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-auth-oauthlib (Old) and /work/SRC/openSUSE:Factory/.python-google-auth-oauthlib.new.561 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth-oauthlib" Wed Mar 4 21:10:30 2026 rev:22 rq:1336386 version:1.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-auth-oauthlib/python-google-auth-oauthlib.changes 2026-01-19 18:42:43.909544679 +0100 +++ /work/SRC/openSUSE:Factory/.python-google-auth-oauthlib.new.561/python-google-auth-oauthlib.changes 2026-03-04 21:11:01.814854641 +0100 @@ -1,0 +2,7 @@ +Wed Mar 4 10:00:47 UTC 2026 - John Paul Adrian Glaubitz <[email protected]> + +- Update to 1.3.0 + * Log the flow.run_local_server redirect URL (#362) + * Raise meaningful exception when oauth callback times out (#363) + +------------------------------------------------------------------- Old: ---- google_auth_oauthlib-1.2.4.tar.gz New: ---- google_auth_oauthlib-1.3.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-auth-oauthlib.spec ++++++ --- /var/tmp/diff_new_pack.JQwnSc/_old 2026-03-04 21:11:02.470881551 +0100 +++ /var/tmp/diff_new_pack.JQwnSc/_new 2026-03-04 21:11:02.470881551 +0100 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-google-auth-oauthlib -Version: 1.2.4 +Version: 1.3.0 Release: 0 Summary: Google authentication library License: Apache-2.0 ++++++ google_auth_oauthlib-1.2.4.tar.gz -> google_auth_oauthlib-1.3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth_oauthlib-1.2.4/PKG-INFO new/google_auth_oauthlib-1.3.0/PKG-INFO --- old/google_auth_oauthlib-1.2.4/PKG-INFO 2026-01-15 22:59:23.335595100 +0100 +++ new/google_auth_oauthlib-1.3.0/PKG-INFO 2026-02-26 19:44:14.592100000 +0100 @@ -1,8 +1,8 @@ Metadata-Version: 2.4 Name: google-auth-oauthlib -Version: 1.2.4 +Version: 1.3.0 Summary: Google Authentication Library -Home-page: https://github.com/GoogleCloudPlatform/google-auth-library-python-oauthlib +Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth-oauthlib Author: Google Cloud Platform Author-email: [email protected] License: Apache 2.0 @@ -50,8 +50,6 @@ This library provides `oauthlib`_ integration with `google-auth`_. -.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=main - :target: https://googleapis.dev/python/google-auth-oauthlib/latest/index.html .. |pypi| image:: https://img.shields.io/pypi/v/google-auth-oauthlib.svg :target: https://pypi.python.org/pypi/google-auth-oauthlib @@ -95,4 +93,4 @@ Apache 2.0 - See `the LICENSE`_ for more information. -.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/main/LICENSE +.. _the LICENSE: https://github.com/googleapis/google-cloud-python/blob/main/LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth_oauthlib-1.2.4/README.rst new/google_auth_oauthlib-1.3.0/README.rst --- old/google_auth_oauthlib-1.2.4/README.rst 2026-01-15 22:59:03.000000000 +0100 +++ new/google_auth_oauthlib-1.3.0/README.rst 2026-02-26 19:42:51.000000000 +0100 @@ -5,8 +5,6 @@ This library provides `oauthlib`_ integration with `google-auth`_. -.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=main - :target: https://googleapis.dev/python/google-auth-oauthlib/latest/index.html .. |pypi| image:: https://img.shields.io/pypi/v/google-auth-oauthlib.svg :target: https://pypi.python.org/pypi/google-auth-oauthlib @@ -50,4 +48,4 @@ Apache 2.0 - See `the LICENSE`_ for more information. -.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/main/LICENSE +.. _the LICENSE: https://github.com/googleapis/google-cloud-python/blob/main/LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth_oauthlib-1.2.4/google_auth_oauthlib/flow.py new/google_auth_oauthlib-1.3.0/google_auth_oauthlib/flow.py --- old/google_auth_oauthlib-1.2.4/google_auth_oauthlib/flow.py 2026-01-15 22:59:03.000000000 +0100 +++ new/google_auth_oauthlib-1.3.0/google_auth_oauthlib/flow.py 2026-02-26 19:42:51.000000000 +0100 @@ -160,7 +160,7 @@ # these args cannot be passed to requests_oauthlib.OAuth2Session code_verifier = kwargs.pop("code_verifier", None) - autogenerate_code_verifier = kwargs.pop("autogenerate_code_verifier", None) + autogenerate_code_verifier = kwargs.pop("autogenerate_code_verifier", True) ( session, @@ -237,7 +237,7 @@ specify the ``state`` when constructing the :class:`Flow`. """ kwargs.setdefault("access_type", "offline") - if self.autogenerate_code_verifier: + if self.code_verifier is None and self.autogenerate_code_verifier: chars = ascii_letters + digits + "-._~" rnd = SystemRandom() random_verifier = [rnd.choice(chars) for _ in range(0, 128)] @@ -410,8 +410,9 @@ in the user's browser. redirect_uri_trailing_slash (bool): whether or not to add trailing slash when constructing the redirect_uri. Default value is True. - timeout_seconds (int): It will raise an error after the timeout timing - if there are no credentials response. The value is in seconds. + timeout_seconds (int): It will raise a WSGITimeoutError exception after the + timeout timing if there are no credentials response. The value is in + seconds. When set to None there is no timeout. Default value is None. token_audience (str): Passed along with the request for an access @@ -425,6 +426,10 @@ Returns: google.oauth2.credentials.Credentials: The OAuth 2.0 credentials for the user. + + Raises: + WSGITimeoutError: If there is a timeout when waiting for the response from the + authorization server. """ wsgi_app = _RedirectWSGIApp(success_message) # Fail fast if the address is occupied @@ -447,6 +452,7 @@ webbrowser.get(browser).open(auth_url, new=1, autoraise=True) if authorization_prompt_message: + _LOGGER.info(authorization_prompt_message.format(url=auth_url)) print(authorization_prompt_message.format(url=auth_url)) local_server.timeout = timeout_seconds @@ -454,7 +460,15 @@ # Note: using https here because oauthlib is very picky that # OAuth 2.0 should only occur over https. - authorization_response = wsgi_app.last_request_uri.replace("http", "https") + try: + authorization_response = wsgi_app.last_request_uri.replace( + "http", "https" + ) + except AttributeError as e: + raise WSGITimeoutError( + "Timed out waiting for response from authorization server" + ) from e + self.fetch_token( authorization_response=authorization_response, audience=token_audience ) @@ -505,3 +519,7 @@ start_response("200 OK", [("Content-type", "text/plain; charset=utf-8")]) self.last_request_uri = wsgiref.util.request_uri(environ) return [self._success_message.encode("utf-8")] + + +class WSGITimeoutError(AttributeError): + """Raised when the WSGI server times out waiting for a response.""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth_oauthlib-1.2.4/google_auth_oauthlib.egg-info/PKG-INFO new/google_auth_oauthlib-1.3.0/google_auth_oauthlib.egg-info/PKG-INFO --- old/google_auth_oauthlib-1.2.4/google_auth_oauthlib.egg-info/PKG-INFO 2026-01-15 22:59:23.000000000 +0100 +++ new/google_auth_oauthlib-1.3.0/google_auth_oauthlib.egg-info/PKG-INFO 2026-02-26 19:44:14.000000000 +0100 @@ -1,8 +1,8 @@ Metadata-Version: 2.4 Name: google-auth-oauthlib -Version: 1.2.4 +Version: 1.3.0 Summary: Google Authentication Library -Home-page: https://github.com/GoogleCloudPlatform/google-auth-library-python-oauthlib +Home-page: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth-oauthlib Author: Google Cloud Platform Author-email: [email protected] License: Apache 2.0 @@ -50,8 +50,6 @@ This library provides `oauthlib`_ integration with `google-auth`_. -.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=main - :target: https://googleapis.dev/python/google-auth-oauthlib/latest/index.html .. |pypi| image:: https://img.shields.io/pypi/v/google-auth-oauthlib.svg :target: https://pypi.python.org/pypi/google-auth-oauthlib @@ -95,4 +93,4 @@ Apache 2.0 - See `the LICENSE`_ for more information. -.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/main/LICENSE +.. _the LICENSE: https://github.com/googleapis/google-cloud-python/blob/main/LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth_oauthlib-1.2.4/setup.py new/google_auth_oauthlib-1.3.0/setup.py --- old/google_auth_oauthlib-1.2.4/setup.py 2026-01-15 22:59:03.000000000 +0100 +++ new/google_auth_oauthlib-1.3.0/setup.py 2026-02-26 19:42:50.000000000 +0100 @@ -32,7 +32,7 @@ long_description = fh.read() -version = "1.2.4" +version = "1.3.0" setup( name="google-auth-oauthlib", @@ -41,7 +41,7 @@ author_email="[email protected]", description="Google Authentication Library", long_description=long_description, - url="https://github.com/GoogleCloudPlatform/google-auth-library-python-oauthlib", + url="https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth-oauthlib", packages=find_namespace_packages( exclude=( "docs*", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google_auth_oauthlib-1.2.4/tests/unit/test_flow.py new/google_auth_oauthlib-1.3.0/tests/unit/test_flow.py --- old/google_auth_oauthlib-1.2.4/tests/unit/test_flow.py 2026-01-15 22:59:03.000000000 +0100 +++ new/google_auth_oauthlib-1.3.0/tests/unit/test_flow.py 2026-02-26 19:42:50.000000000 +0100 @@ -16,6 +16,7 @@ import datetime from functools import partial import json +import logging import os import re import socket @@ -34,6 +35,9 @@ with open(CLIENT_SECRETS_FILE, "r") as fh: CLIENT_SECRETS_INFO = json.load(fh) +VALID_PKCE_VERIFIER_REGEX = r"^[A-Za-z0-9-._~]{128}$" +VALID_CODE_CHALLENGE_REGEX = r"^[A-Za-z0-9-_]{43}$" + class TestFlow(object): def test_from_client_secrets_file(self): @@ -114,10 +118,14 @@ assert CLIENT_SECRETS_INFO["web"]["auth_uri"] in url assert scope in url + assert "code_challenge=" in url + assert "code_challenge_method=S256" in url authorization_url_spy.assert_called_with( CLIENT_SECRETS_INFO["web"]["auth_uri"], access_type="offline", prompt="consent", + code_challenge=mock.ANY, + code_challenge_method="S256", ) def test_authorization_url_code_verifier(self, instance): @@ -183,10 +191,8 @@ assert kwargs["code_challenge_method"] == "S256" assert len(instance.code_verifier) == 128 assert len(kwargs["code_challenge"]) == 43 - valid_verifier = r"^[A-Za-z0-9-._~]*$" - valid_challenge = r"^[A-Za-z0-9-_]*$" - assert re.match(valid_verifier, instance.code_verifier) - assert re.match(valid_challenge, kwargs["code_challenge"]) + assert re.fullmatch(VALID_PKCE_VERIFIER_REGEX, instance.code_verifier) + assert re.fullmatch(VALID_CODE_CHALLENGE_REGEX, kwargs["code_challenge"]) def test_fetch_token(self, instance): instance.code_verifier = "amanaplanacanalpanama" @@ -263,6 +269,7 @@ @pytest.fixture def socket(self, port): s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Enable SO_REUSEADDR s.bind(("localhost", port)) yield s s.close() @@ -307,13 +314,13 @@ assert credentials.id_token == mock.sentinel.id_token assert webbrowser_mock.get().open.called assert instance.redirect_uri == f"http://localhost:{port}/" - + assert re.fullmatch(VALID_PKCE_VERIFIER_REGEX, instance.code_verifier) expected_auth_response = auth_redirect_url.replace("http", "https") mock_fetch_token.assert_called_with( CLIENT_SECRETS_INFO["web"]["token_uri"], client_secret=CLIENT_SECRETS_INFO["web"]["client_secret"], authorization_response=expected_auth_response, - code_verifier=None, + code_verifier=mock.ANY, audience=None, ) @@ -352,7 +359,7 @@ CLIENT_SECRETS_INFO["web"]["token_uri"], client_secret=CLIENT_SECRETS_INFO["web"]["client_secret"], authorization_response=expected_auth_response, - code_verifier=None, + code_verifier=mock.ANY, audience=self.AUDIENCE, ) @@ -455,3 +462,55 @@ instance.run_local_server() server_mock.server_close.assert_called_once() + + @mock.patch("builtins.print") + @mock.patch("google_auth_oauthlib.flow.webbrowser", autospec=True) + def test_run_local_server_logs_and_prints_url( + self, webbrowser_mock, print_mock, instance, mock_fetch_token, port, caplog + ): + auth_redirect_url = urllib.parse.urljoin( + f"http://localhost:{port}", self.REDIRECT_REQUEST_PATH + ) + + # Configure caplog to capture INFO logs + caplog.set_level(logging.INFO, logger="google_auth_oauthlib.flow") + + with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: + future = pool.submit(partial(instance.run_local_server, port=port)) + + while not future.done(): + try: + requests.get(auth_redirect_url) + except requests.ConnectionError: + pass + + future.result() + + # Verify log message + assert "Please visit this URL" in caplog.text + assert urllib.parse.quote(instance.redirect_uri, safe="") in caplog.text + + # Verify print message + print_mock.assert_called_once() + assert "Please visit this URL" in print_mock.call_args[0][0] + assert ( + urllib.parse.quote(instance.redirect_uri, safe="") + in print_mock.call_args[0][0] + ) + + @mock.patch("google_auth_oauthlib.flow.webbrowser", autospec=True) + @mock.patch("wsgiref.simple_server.make_server", autospec=True) + def test_run_local_server_timeout( + self, make_server_mock, webbrowser_mock, instance, mock_fetch_token + ): + mock_server = mock.Mock() + make_server_mock.return_value = mock_server + + # handle_request does nothing (simulating timeout), so last_request_uri remains None + mock_server.handle_request.return_value = None + + with pytest.raises(flow.WSGITimeoutError): + instance.run_local_server(timeout_seconds=1) + + webbrowser_mock.get.assert_called_with(None) + webbrowser_mock.get.return_value.open.assert_called_once()
