Use VIAPLAY-AT auth scheme for account overview.

Bearer was rejected with Forbidden; manage-account HAR uses VIAPLAY-AT.
This commit is contained in:
Jos Vooges | STH 2026-09-22 23:14:40 +02:00
parent 1c939acd59
commit 0424ec4a10
4 changed files with 18 additions and 10 deletions

View file

@ -536,7 +536,7 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
onChange={(e) => setEditAccessToken(e.target.value)}
rows={2}
disabled={busy}
placeholder="nieuw accessToken (voor pakketinfo vereist)"
placeholder="JWT of VIAPLAY-AT … (cookie accessToken)"
style={{ fontFamily: "monospace", fontSize: "0.8rem" }}
/>
</label>

View file

@ -130,7 +130,10 @@ export function createAccountStored(
const email = input.email.trim().toLowerCase();
if (!email) throw new Error("E-mail verplicht");
const session = input.session?.trim();
const accessToken = input.accessToken?.trim().replace(/^Bearer\s+/i, "").trim();
const accessToken = input.accessToken
?.trim()
.replace(/^(VIAPLAY-AT|MTG-AT|Bearer)\s+/i, "")
.trim();
if (!session || !accessToken) {
throw new Error("session + accessToken verplicht");
}

View file

@ -77,7 +77,10 @@ function normalizeAccessToken(raw: string | null | undefined): string | null {
if (!raw) return null;
const trimmed = raw.trim();
if (!trimmed) return null;
return trimmed.replace(/^Bearer\s+/i, "").trim() || null;
// Browser/HAR kan "VIAPLAY-AT …", "MTG-AT …" of "Bearer …" plakken
return (
trimmed.replace(/^(VIAPLAY-AT|MTG-AT|Bearer)\s+/i, "").trim() || null
);
}
function accessTokenExpiryInfo(token: string): {
@ -98,7 +101,7 @@ function accessTokenExpiryInfo(token: string): {
/**
* Pakketinfo komt van account.mtg-api.com/overview.
* Browser stuurt alleen Authorization: Bearer (geen cookies) — cookies geven Forbidden.
* Browser (HAR): Authorization: VIAPLAY-AT <jwt> — geen cookies, geen Bearer.
*/
export async function fetchAccountOverview(
creds: ViaplayAccountCreds,
@ -118,15 +121,14 @@ export async function fetchAccountOverview(
}
const tokenInfo = accessTokenExpiryInfo(token);
// Exact zoals manage-account in de browser (HAR): Bearer-only + Content-Type
const headers: Record<string, string> = {
Accept: "*/*",
"Content-Type": "application/json",
"Accept-Language": "nl,en-US;q=0.7,en;q=0.3",
"Accept-Language": "nl,en-US;q=0.9,en;q=0.8",
Origin: "https://viaplay.com",
Referer: "https://viaplay.com/",
"User-Agent": VIAPLAY_USER_AGENT,
Authorization: `Bearer ${token}`,
Authorization: `VIAPLAY-AT ${token}`,
};
let lastStatus = 0;
@ -177,8 +179,8 @@ export async function fetchAccountOverview(
(lastStatus === 401 || lastStatus === 403 || /forbidden|unauthorized/i.test(lastError))
) {
lastError = tokenInfo.expired
? "accessToken verlopen — plak een verse accessToken uit de browser en Check opnieuw"
: "overview Forbidden — plak een verse accessToken (Bearer) uit de browser; sessiecookie is niet genoeg";
? "accessToken verlopen — vernieuw tokens en Check opnieuw"
: `overview ${lastError} (Authorization moet VIAPLAY-AT zijn)`;
}
return {

View file

@ -261,7 +261,10 @@ export async function updateViaplayAccount(
sessionEnc = encryptSecret(input.session.trim(), sessionSecret);
}
if (input.accessToken?.trim()) {
const token = input.accessToken.trim().replace(/^Bearer\s+/i, "").trim();
const token = input.accessToken
.trim()
.replace(/^(VIAPLAY-AT|MTG-AT|Bearer)\s+/i, "")
.trim();
accessTokenEnc = encryptSecret(token, sessionSecret);
}
if (input.profileId !== undefined) {