From a83151fa384a6f514568590f8daede6c7bec58d7 Mon Sep 17 00:00:00 2001 From: Nirvana Date: Tue, 20 Oct 2026 14:25:46 +0200 Subject: [PATCH] eon: oidc login for bg --- lib/streaming_providers/providers/eon/auth.py | 4 +++- .../providers/eon/constants.py | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/streaming_providers/providers/eon/auth.py b/lib/streaming_providers/providers/eon/auth.py index 7660426..9f25b83 100644 --- a/lib/streaming_providers/providers/eon/auth.py +++ b/lib/streaming_providers/providers/eon/auth.py @@ -374,7 +374,7 @@ class EonAuth: if self._oidc is None: return self._grant({"grant_type": "refresh_token", "refresh_token": refresh}) client = self._config.oidc_client - # UNVERIFIED against a browser capture: the standard public-client refresh + # UNVERIFIED against a browser capture: the standard refresh (same Basic auth as the code exchange) # request. A rejection just falls through to a full login (see _login). body = urlencode({ "grant_type": "refresh_token", @@ -395,6 +395,8 @@ class EonAuth: "Content-Type": "application/x-www-form-urlencoded", "Origin": client.origin, "Referer": client.origin + "/", + "Accept-Language": "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7", + **({"Authorization": client.basic_auth_value()} if client.client_secret else {}), } def _login_oidc(self) -> EonTokenResponse: diff --git a/lib/streaming_providers/providers/eon/constants.py b/lib/streaming_providers/providers/eon/constants.py index 6fbdbed..2d9481d 100644 --- a/lib/streaming_providers/providers/eon/constants.py +++ b/lib/streaming_providers/providers/eon/constants.py @@ -124,9 +124,12 @@ BRAND_LOGIN_FLOWS: Dict[str, str] = { @dataclass(frozen=True) class EonOidcClient: - """Public OAuth client of the operator's web app (no secret: PKCE).""" + """OAuth client of the operator's web app. PKCE, but the token endpoint + ALSO wants Basic client auth (the secret ships in the web app's JS, like + the PLATFORMS secrets). Never log it.""" client_id: str redirect_uri: str + client_secret: str = "" scope: str = "openid" device_type: str = "Browser" platform_identifier: str = "web" @@ -135,11 +138,16 @@ class EonOidcClient: def origin(self) -> str: return self.redirect_uri.rstrip("/") + def basic_auth_value(self) -> str: + raw = f"{self.client_id}:{self.client_secret}" + return "Basic " + base64.b64encode(raw.encode("ascii")).decode("ascii") + BRAND_OIDC_CLIENTS: Dict[str, EonOidcClient] = { "vivacom": EonOidcClient( client_id="b5826897-1736-4646-af04-0a0cf891e0ac", redirect_uri="https://eontv.bg", + client_secret="9xk3m5f2e7q1z0r4h8c6dypoavwsgntulbjmi", ), } @@ -266,7 +274,10 @@ class EonConfig: f"{EonDefaults.PROVIDER_LABEL}: brand {self.brand!r} has no known OIDC " f"client; set oidc_client_id and oidc_redirect_uri" ) - self.oidc_client = EonOidcClient(client_id=client_id, redirect_uri=redirect_uri) + self.oidc_client = EonOidcClient( + client_id=client_id, redirect_uri=redirect_uri, + client_secret=c.get("oidc_client_secret") or (base.client_secret if base else ""), + ) self.user_agent = c.get("user_agent") or self.platform.user_agent self.timeout = c.get("timeout", EonDefaults.TIMEOUT)