For the Eagle 3D Streaming Web SDK on a page the public can reach. The demo puts your API key in the browser, which is fine while you are building and not fine once anyone can visit. This is the one change that fixes it.
Anything in a web page can be read by anyone who visits it. Your API key sits
in scripts/sdk-config.js, so it is one click of View Source away
— and it does not expire.
Start streaming sessions billed to your account, from their own page, for as long as the key exists. They do not need your app, your Control Panel login or anything else. The first sign is usually the bill, or your concurrent-user limit being used up by people you cannot identify.
Your server holds the key and asks Eagle 3D Streaming for a token; the browser only ever receives the token.
Browser Your server Eagle 3D Streaming
│ "I'd like to stream" │ │
├──────────────────────▶│ API key + app details │
│ ├───────────────────────────▶│
│ │ short-lived token │
│ just the token │◀───────────────────────────┤
│◀──────────────────────┤ │
│ start the session with that token │
├───────────────────────────────────────────────────▶│
A token expires in about a minute and covers a single session. Someone who copies one gets, at most, the session you were already going to give them. A key has no expiry and no limit.
One function. requestSessionToken() in
scripts/sdk-token.js currently calls the Eagle 3D Streaming token endpoint
directly, with your key in the header. Point it at your own endpoint instead:
async function requestSessionToken() {
// Your server. It knows the key; this page never does.
const response = await fetch("/api/streaming-token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ /* whatever your server needs to decide */ })
});
if (!response.ok) return null;
return await response.json();
}
Nothing else moves. main(), your callbacks, your controls and
your markup are untouched — they receive the same token they always did,
from a different place.
It makes the request the browser used to make, with the key it holds privately, and returns the answer:
// POST https://token.eagle3dstreaming.com/api/v2/token/create
// Authorization: Auth <your streaming API key>
{
"object": {
"core": { domain, userName, appName, configurationName, version },
"configurationToOverride": {}
},
"expiry": 60000,
"client": "your-username" // the same account username as core.userName
}
This is the part that is easy to miss, because it does not look like a security question until somebody asks it: who, exactly, can start a session billed to your account? The answer depends entirely on how you embedded the stream, and the three methods are not close.
| How you embedded it | Who can start a stream |
|---|---|
| Streaming URL | Anyone with the link. You can add a password or restrict the link in the configuration, but the link itself is what grants access — and you cannot revoke it for one person. |
| iframe | The same. Your page can require a login before it shows the frame, but the streaming URL inside is still a working link to anyone who reads your page source. |
| Web SDK | Your backend decides. The session starts from a short-lived token, so your server chooses who gets one, when, and for which app. |
View Source, then the Network tab. Your key must appear in neither. If it is
still in sdk-config.js because the file was copied across, the page
will work perfectly and still be leaking it — working is not the test
here, absence is.
Where the key comes from, and how to replace one you think is exposed.
Last updated