From 7b7c96fb59a6978c62d4e99b72d51c5de03eed86 Mon Sep 17 00:00:00 2001 From: Matthew Grossman Date: Fri, 4 Sep 2026 16:27:11 -0700 Subject: [PATCH] Ignore API load balancer stickiness cookies Signed-off-by: Matthew Grossman --- simplipy/api.py | 7 +++++++ tests/test_api.py | 17 ++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/simplipy/api.py b/simplipy/api.py index 977b817d..43b884ac 100644 --- a/simplipy/api.py +++ b/simplipy/api.py @@ -32,6 +32,7 @@ from simplipy.util.dt import utcnow from simplipy.websocket import WebsocketClient +API_COOKIE_OVERRIDES = {"AWSALB": "", "AWSALBCORS": ""} API_URL_HOSTNAME = "api.simplisafe.com" API_URL_BASE = f"https://{API_URL_HOSTNAME}/v1" @@ -224,6 +225,12 @@ async def _async_api_request( if self.access_token: kwargs["headers"]["Authorization"] = f"Bearer {self.access_token}" + if url_base == API_URL_BASE: + kwargs["cookies"] = { + **(kwargs.get("cookies") or {}), + **API_COOKIE_OVERRIDES, + } + data: dict[str, Any] | str = {} async with self.session.request( method, f"{url_base}/{endpoint}", **kwargs diff --git a/tests/test_api.py b/tests/test_api.py index 289a2477..a1205512 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,12 +5,14 @@ import asyncio from datetime import timedelta +from http.cookies import SimpleCookie from typing import Any from unittest.mock import AsyncMock, Mock, patch import aiohttp import pytest from aresponses import ResponsesMockServer +from yarl import URL from simplipy import API from simplipy.errors import InvalidCredentialsError, RequestError, SimplipyError @@ -114,12 +116,20 @@ async def test_401_refresh_token_success( v2_settings_response: An API response payload. v2_subscriptions_response: An API response payload. """ + + def unauthorized(request: Any) -> aresponses.Response: + """Return a 401 after checking that ALB cookies are masked.""" + cookies = SimpleCookie(request.headers["Cookie"]) + assert cookies["AWSALB"].value == "" + assert cookies["AWSALBCORS"].value == "" + return aresponses.Response(text="Unauthorized", status=401) + async with authenticated_simplisafe_server: authenticated_simplisafe_server.add( "api.simplisafe.com", f"/v1/users/{TEST_SUBSCRIPTION_ID}/subscriptions", "get", - response=aresponses.Response(text="Unauthorized", status=401), + response=unauthorized, ) api_token_response["access_token"] = "jjhhgg66" # noqa: S105 @@ -153,6 +163,11 @@ async def test_401_refresh_token_success( TEST_AUTHORIZATION_CODE, TEST_CODE_VERIFIER, session=session ) + session.cookie_jar.update_cookies( + {"AWSALB": "stale", "AWSALBCORS": "stale"}, + response_url=URL("https://api.simplisafe.com"), + ) + # Manually set the expiration datetime to force a refresh token flow: simplisafe._token_last_refreshed = utcnow() - timedelta(seconds=30)