mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 13:16:16 -08:00
fix(stalker): authenticate before serving a static collection stream
Second Codex P1 on #1364, and a regression this PR introduced. `create_link` was also the request that warmed the portal session. Tokens live in memory only (`StalkerSessionService.tokenCache` is a plain Map), and the collection header builder reads the raw `getCachedToken()`. So a cold start from global Favorites or Recently Viewed — the portal never opened this session — took the static path, found no token, and handed a same-host gated stream headers with no `Authorization`: a 403 on exactly the streams the header contract exists for. The same raw accessor cannot tell a token negotiated for a pre-edit identity from a current one. `StreamResolverService` now calls `ensureToken()` before building a static playback. It is the right primitive: handshake + `get_profile` with no link minted, identity fingerprint validated, concurrent callers deduped, and an immediate null for simple portals — and calling it keeps this change out of `stalker-session.service.ts`, which PR 6 (#1354) is splitting. Best-effort by design: a static URL may point at a CDN that needs no credentials, so a failed handshake degrades to the token-less header set instead of costing the user their playback. Both halves are pinned by tests, and removing the call makes the cold-start test fail. The portal routes need no equivalent and do not get one: an item cannot be selected before its catalog has loaded, and every catalog load authenticates. That reasoning is now written down rather than assumed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0278205984
commit
409d8235a2
3 files changed
+144
-2
No files matched your search
@@ -364,6 +364,26 @@ Callers pass the row they resolved the `cmd` from:
|
||||
An item with no row snapshot gets no verdict, except radio, which keeps its
|
||||
long-standing "directly usable command plays as-is" behaviour.
|
||||
|
||||
### The static path still needs the session
|
||||
|
||||
`create_link` was also the request that warmed the portal session, and tokens
|
||||
live in memory only (`StalkerSessionService.tokenCache`). Skipping it therefore
|
||||
has to account for streams that are still gated on the Bearer token:
|
||||
|
||||
- **Portal routes** (ITV, VOD, series, radio) are structurally warm. An item
|
||||
cannot be selected before its catalog has loaded, and every catalog load goes
|
||||
through `executeStalkerRequest`, which authenticates. No extra work needed.
|
||||
- **Collection routes** (global Favorites / Recently Viewed) are not. They read
|
||||
the persisted row and can play on a cold start, without the portal ever
|
||||
having been opened this session. `StreamResolverService` therefore calls
|
||||
`StalkerSessionService.ensureToken()` before building a static playback —
|
||||
handshake + `get_profile`, no link minted, and it validates the identity the
|
||||
cached token was negotiated for, which the raw `getCachedToken()` used by the
|
||||
header builder cannot. A simple portal returns `null` immediately.
|
||||
The call is best-effort: a static URL may point at a CDN needing no
|
||||
credentials at all, so a failed handshake degrades to the token-less header
|
||||
set rather than costing the user their playback.
|
||||
|
||||
### Resolved links are never stored
|
||||
|
||||
A temporary link lives about 5 seconds (`tv_tmp_link_ttl` /
|
||||
@@ -420,7 +440,8 @@ Revisit both only with a portal that demonstrably fails without them.
|
||||
the `series` exception, relative VOD commands.
|
||||
- `with-stalker-player.feature.spec.ts` — ITV/radio store paths and proof that
|
||||
Recently Viewed stores the `cmd`, never the stream URL.
|
||||
- `stream-resolver.service.spec.ts` — the collection route.
|
||||
- `stream-resolver.service.spec.ts` — the collection route, plus the cold
|
||||
full-portal session warm-up and its best-effort degradation.
|
||||
- `stalker-playback-context.service.spec.ts` — headers only, query-insensitive
|
||||
key.
|
||||
- `apps/web-e2e/src/stalker.e2e.ts` — mock scenario `00:1A:79:00:00:0A` serves
|
||||
|
||||
Reference in new issue
Block a user