Recipe: Auth Tokens via baseUrl + auth
The baseUrl pattern covers the unauthenticated case: one origin, relative item paths. A real media server almost always sits behind auth too, baseUrl still supplies the origin, auth supplies the credentials every request against it carries, including the ones nomercy-video-player issues itself for HLS manifests and segments.
Wiring bearerToken
bearerToken accepts a plain string, a sync getter, or an async getter, so a reactive store’s current value is always read fresh instead of captured once at setup() time:
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import type { VideoPlaylistItem } from '@nomercy-entertainment/nomercy-video-player';
const player = nmplayer('player');
// Your own protected catalogue — this recipe is about the `auth` block,
// not about media, so this is your app's real playlist, not a fixture.
const playlist: VideoPlaylistItem[] = [];
player.setup({
baseUrl: 'https://media.your-domain.com/api/files',
auth: {
bearerToken: () => authStore.accessToken, // read fresh on every request
},
playlist,
});
An async getter works identically, useful when the token itself has to be fetched or decrypted before use:
auth: {
bearerToken: async () => (await tokenCache.get()) ?? '',
},
Reaching the HLS backend
Authorization: Bearer <token> is not only for fetch()-based calls (subtitles, chapters, thumbnails). nomercy-video-player’s HTML5 backend wires the same resolved bearer value into hls.js’s own manifest and segment requests automatically, there is nothing extra to configure for adaptive streaming specifically. Set auth once and every request path, kit-level fetch, hls.js, image resolution, uses it.
Handling a 401
refreshOnUnauthenticated runs exactly once per 401 response, never on a 403 (which propagates immediately, on the assumption a 403 means “not allowed”, not “token expired”). After it resolves, the original request retries once with freshly-resolved bearerToken / headers:
auth: {
bearerToken: () => authStore.accessToken,
refreshOnUnauthenticated: async () => {
await authStore.refresh(); // updates authStore.accessToken in place
},
retryAfterRefresh: 1, // default — 0 disables the retry entirely
},
The getter is what makes this work without extra plumbing: refreshOnUnauthenticated mutates the store, and the next bearerToken() call (the retry) reads the already-updated value, no manual “pass the new token back” step needed.
Rotating the token mid-session
For a token that expires on a schedule you already know (a short-lived signed URL scheme, for example), update auth directly on the live player instead of waiting for a 401 to trigger the refresh path:
player.auth({ bearerToken: newToken }); // merges onto the existing AuthConfig
Any object argument shallow-merges onto the current config; auth(null) clears it entirely. Passing just { bearerToken } here only changes that field, headers, credentials, and the rest of the current config stay intact. refreshAuth() runs the current config’s refreshOnUnauthenticated handler on demand, outside the 401 path, then emits auth:refreshed; if that handler throws it emits auth:failed instead of throwing. Reach for it to trigger a refresh you know is due without waiting for a 401 to force one.
Cookie-based auth instead of a bearer token
When the media server relies on a session cookie rather than a header, skip bearerToken and set credentials instead. The kit applies it to its own fetch() calls (subtitles, chapters, thumbnails, playlist):
auth: {
credentials: 'include',
},
The HLS backend is the exception: its hls.js manifest and segment requests carry cookies only when they are same-origin with the page, because the backend wires the bearer header but never sets withCredentials. So for a cross-origin media server, cookie auth covers the kit fetches but not adaptive streaming; reach for a bearer token or a same-origin proxy there. When a fetch is cross-origin, credentials: 'include' also needs the server’s CORS headers to line up (Access-Control-Allow-Credentials: true plus an explicit origin, never *); the browser enforces that regardless of anything this config does.
Next steps
- Adapter: Video Backend: how the resolved backend applies
authto every manifest and segment request it issues.