fix(hls): scope cookie name per-asset to prevent multi-video 403s
When a lesson has two or more uploaded videos each calls mintHlsCookie,
but all wrote to the same `cio_hls` cookie name. The last write won,
leaving every other video with a mismatched token and a 403 from the
CF Worker.
Cookie name is now `cio_hls_${assetId}` so each video owns its own
cookie. The tenant-router Worker, the Hono HLS fallback route, and the
transcripts route all read the per-asset name.
This commit is contained in:
@@ -111,7 +111,7 @@ export const hlsRouter = new Hono()
|
|||||||
let authorized = false;
|
let authorized = false;
|
||||||
let denyReason: 'no_token_or_session' | 'token_invalid' | 'session_no_role' | 'asset_missing' =
|
let denyReason: 'no_token_or_session' | 'token_invalid' | 'session_no_role' | 'asset_missing' =
|
||||||
'no_token_or_session';
|
'no_token_or_session';
|
||||||
const token = getCookie(c, HLS_COOKIE_NAME);
|
const token = getCookie(c, `${HLS_COOKIE_NAME}_${assetId}`);
|
||||||
if (token) {
|
if (token) {
|
||||||
const verified = await verifyHlsToken(token);
|
const verified = await verifyHlsToken(token);
|
||||||
if (verified?.assetId === assetId) {
|
if (verified?.assetId === assetId) {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export const transcriptsRouter = new Hono()
|
|||||||
if (!asset) return withCors(null, 404);
|
if (!asset) return withCors(null, 404);
|
||||||
|
|
||||||
let authorized = false;
|
let authorized = false;
|
||||||
const token = getCookie(c, HLS_COOKIE_NAME);
|
const token = getCookie(c, `${HLS_COOKIE_NAME}_${assetId}`);
|
||||||
if (token) {
|
if (token) {
|
||||||
const verified = await verifyHlsToken(token);
|
const verified = await verifyHlsToken(token);
|
||||||
if (verified?.assetId === assetId) authorized = true;
|
if (verified?.assetId === assetId) authorized = true;
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ async function handleHlsRequest(request: Request, env: Env): Promise<Response> {
|
|||||||
if (!assetId || !relativePath) return new Response('Not Found', { status: 404 });
|
if (!assetId || !relativePath) return new Response('Not Found', { status: 404 });
|
||||||
if (relativePath.includes('..')) return new Response('Bad Request', { status: 400 });
|
if (relativePath.includes('..')) return new Response('Bad Request', { status: 400 });
|
||||||
|
|
||||||
const token = readCookie(request.headers.get('cookie'), HLS_COOKIE_NAME);
|
const token = readCookie(request.headers.get('cookie'), `${HLS_COOKIE_NAME}_${assetId}`);
|
||||||
if (!token) return new Response('Unauthorized', { status: 401 });
|
if (!token) return new Response('Unauthorized', { status: 401 });
|
||||||
|
|
||||||
const verified = await verifyHlsToken(token, env.HLS_SIGNING_SECRET);
|
const verified = await verifyHlsToken(token, env.HLS_SIGNING_SECRET);
|
||||||
|
|||||||
@@ -714,7 +714,7 @@ export async function mintHlsToken(assetId: string): Promise<{
|
|||||||
return {
|
return {
|
||||||
token: `${payload}.${signature}`,
|
token: `${payload}.${signature}`,
|
||||||
expiresAt: new Date(exp * 1000).toISOString(),
|
expiresAt: new Date(exp * 1000).toISOString(),
|
||||||
cookieName: HLS_COOKIE_NAME,
|
cookieName: `${HLS_COOKIE_NAME}_${assetId}`,
|
||||||
maxAgeSeconds: HLS_COOKIE_TTL_SECONDS
|
maxAgeSeconds: HLS_COOKIE_TTL_SECONDS
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user