From bb4b0f6663c166a4efa485ba946778fc3cda3275 Mon Sep 17 00:00:00 2001 From: Teddi Date: Mon, 29 Dec 2025 13:07:32 +0000 Subject: [PATCH 1/6] Add exception handling to reduce the types of data that can be returned to reduce footguns --- pysteamsignin/steamsignin.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pysteamsignin/steamsignin.py b/pysteamsignin/steamsignin.py index a8bbb7b..e6e02b4 100644 --- a/pysteamsignin/steamsignin.py +++ b/pysteamsignin/steamsignin.py @@ -131,9 +131,13 @@ def ValidateResults(self, results): parsedArgs = urlencode(validationArgs).encode("utf-8") logger.info('Encoded the validation arguments, prepped to send.') - with urllib.request.urlopen(self._provider, parsedArgs, timeout = OPENID_TIMEOUT) as requestData: - responseData = requestData.read().decode('utf-8') - logger.info(f"Sent request to {self._provider}, got back a response.") + try: + with urllib.request.urlopen(self._provider, parsedArgs, timeout = OPENID_TIMEOUT) as requestData: + responseData = requestData.read().decode("utf-8") + logger.info(f"Sent request to {self._provider}, got back a response.") + except Exception as e: + logger.warning(f"Steam OpenID verification failed: {e}") + return False fields = {} From 8f5fe4d25277f38bde145123e144fd6d28400442 Mon Sep 17 00:00:00 2001 From: Teddi Date: Mon, 29 Dec 2025 13:14:16 +0000 Subject: [PATCH 2/6] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b86008a..5ccc6b5 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="steamsignin", - version="1.1.2", + version="1.1.3", author="TeddiO", author_email="", description="OpenID 2.0 sign in for Steam", From 397a0d63dec8bef634789b4b3f56eab7e559f896 Mon Sep 17 00:00:00 2001 From: Teddi Date: Mon, 29 Dec 2025 13:25:32 +0000 Subject: [PATCH 3/6] Add some basic tests --- test/tests.py | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test/tests.py diff --git a/test/tests.py b/test/tests.py new file mode 100644 index 0000000..a2b6f1a --- /dev/null +++ b/test/tests.py @@ -0,0 +1,93 @@ +import unittest +import sys +import os +import logging +from unittest.mock import patch +import urllib.error +import socket + +sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)))) +from pysteamsignin.steamsignin import SteamSignIn + + +def valid_results(): + steam_id = "12345678901234567" + claimed = f"https://steamcommunity.com/openid/id/{steam_id}" + + return { + "openid.assoc_handle": "assoc", + "openid.signed": "claimed_id,identity", + "openid.sig": "sig", + "openid.ns": "http://specs.openid.net/auth/2.0", + "openid.claimed_id": claimed, + "openid.identity": claimed, + } + + +class FakeSteamResponse: + def __init__(self, body): + self._body = body.encode("utf-8") + + def read(self): + return self._body + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + pass + + +class TestSteamSignIn(unittest.TestCase): + + @patch("urllib.request.urlopen") + def test_valid_openid_response_returns_steamid_string(self, mock_urlopen): + mock_urlopen.return_value = FakeSteamResponse("is_valid:true\n") + + signin = SteamSignIn() + result = signin.ValidateResults(valid_results()) + + self.assertEqual(result, "12345678901234567") + + @patch("urllib.request.urlopen") + def test_steam_is_valid_false_denies_login(self, mock_urlopen): + mock_urlopen.return_value = FakeSteamResponse("is_valid:false\n") + + signin = SteamSignIn() + result = signin.ValidateResults(valid_results()) + + self.assertFalse(result) + + @patch("urllib.request.urlopen", side_effect = socket.timeout("timed out")) + def test_openid_timeout_fails_closed_and_logs_warning(self, mock_urlopen): + with self.assertLogs("pysteamsignin.steamsignin", level = logging.WARNING) as logs: + signin = SteamSignIn() + result = signin.ValidateResults(valid_results()) + + self.assertFalse(result) + self.assertIn("Steam OpenID verification failed", logs.output[0]) + + @patch("urllib.request.urlopen", side_effect = urllib.error.URLError("connection failed")) + def test_network_error_fails_closed_and_logs_warning(self, mock_urlopen): + with self.assertLogs("pysteamsignin.steamsignin", level = logging.WARNING) as logs: + signin = SteamSignIn() + result = signin.ValidateResults(valid_results()) + + self.assertFalse(result) + self.assertIn("Steam OpenID verification failed", logs.output[0]) + + @patch("urllib.request.urlopen") + def test_claimed_id_identity_mismatch_fails_validation(self, mock_urlopen): + mock_urlopen.return_value = FakeSteamResponse("is_valid:true\n") + + results = valid_results() + results["openid.identity"] = "https://steamcommunity.com/openid/id/DIFFERENT" + + signin = SteamSignIn() + result = signin.ValidateResults(results) + + self.assertFalse(result) + + +if __name__ == "__main__": + unittest.main() From ccf333e19833a23e27f1e6bd6b11246dc365db68 Mon Sep 17 00:00:00 2001 From: Teddi Date: Mon, 29 Dec 2025 13:31:11 +0000 Subject: [PATCH 4/6] Add a GH Workflow for running the tests --- .github/workflows/tests.yml | 32 ++++++++++++++++++++++++++++++++ setup.py | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..867cd4d --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,32 @@ +name: Run unit tests + +on: + pull_request: + +jobs: + tests: + runs-on: ubuntu-latest + + strategy: + matrix: + python-version: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + - "3.13" + - "3.14" + + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + + - name: Run unit tests + run: | + python -m unittest discover -s test -v diff --git a/setup.py b/setup.py index 5ccc6b5..1da7f6f 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,6 @@ "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", "Operating System :: OS Independent", ], - packages=setuptools.find_packages(exclude=('samples')), + packages=setuptools.find_packages(exclude=('samples', '.github')), python_requires=">=3.6" ) \ No newline at end of file From 511652299b11c707eab591789226c3eb125f3333 Mon Sep 17 00:00:00 2001 From: Teddi Date: Mon, 29 Dec 2025 13:33:46 +0000 Subject: [PATCH 5/6] test to see if 3.6/3.7 still work --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 867cd4d..bda8656 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,6 +10,8 @@ jobs: strategy: matrix: python-version: + - "3.6" + - "3.7" - "3.8" - "3.9" - "3.10" From 012c642d8dbb5e429f2f692440089975b04b89c0 Mon Sep 17 00:00:00 2001 From: Teddi Date: Mon, 29 Dec 2025 13:34:16 +0000 Subject: [PATCH 6/6] revert --- .github/workflows/tests.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bda8656..867cd4d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,8 +10,6 @@ jobs: strategy: matrix: python-version: - - "3.6" - - "3.7" - "3.8" - "3.9" - "3.10"