Protecting API Keys in Angular When Embedding a Realtime Voice and Video Avatar

Protect Angular API keys for realtime voice/video avatars with backend sessions, scoped tokens, or iframe embeds.
Introduction
Embedding a realtime voice and video avatar in an Angular app sounds straightforward until you look at the auth boundary. If your frontend talks directly to a realtime avatar API with a long-lived API key, that key is effectively public: it can be extracted from your JavaScript bundle, browser devtools, or network logs. For a system that creates and manages live sessions, that is the wrong place for a secret.
This post walks through the safe patterns for Angular applications, explains why “just hide it in environment.ts” is not a real solution, and shows how to structure the backend or embedded flow so your app can render a synchronized talking avatar without exposing credentials. By the end, you should be able to choose between a server-mediated integration and a customer-managed iframe embed, and know when each one is appropriate.
Why API keys do not belong in Angular
Angular environment files are build-time substitution, not secret storage. If a value reaches the browser, it is no longer secret. That includes:
API keys embedded in `environment.ts` or `environment.prod.ts`
Tokens fetched once and cached in localStorage
“Hidden” values passed through compile-time constants
For a realtime avatar service, leaked credentials are particularly risky because they can be used to create sessions, consume billing, and potentially impersonate your application. If the service exposes quality tiers or rate-limited session creation, an attacker can still burn through quota or create unexpected cost even without deeper access.
The rule of thumb is simple: if the browser needs to call an authenticated API, the browser should only ever see a short-lived, narrowly scoped token that your backend minted for that exact purpose. If the API only supports long-lived secret keys, the browser should never call it directly.
The safe architecture: browser talks to your backend, backend talks to the API
The usual pattern is a thin server-side endpoint that owns the secret key. Your Angular app requests a session or capability from your backend, and your backend forwards the request to the avatar API using the secret stored in server-side configuration.
This gives you three important controls:
Secret isolation: the API key stays on the server.
Policy enforcement: you can restrict which users can create sessions, which avatar they can use, and how long the session may last.
Auditability: you can log who requested what without exposing credentials in the browser.
A minimal Python backend using the Protoface SDK might look like this:
Your Angular app then calls /api/avatar-session, receives only the data needed to connect, and never sees the server secret. The exact shape of the session payload depends on the API, but the security model does not change: the browser gets an ephemeral result, not a reusable credential.
Angular-specific implementation details that matter
In Angular, the practical rule is to keep the avatar integration inside a service and keep secret-bearing logic out of the component tree. Components should ask for session metadata; they should not know how credentials are generated.
A typical pattern looks like this:
Then in the component, use the returned connection data to initialize the UI. Keep the session creation request idempotent if possible, because Angular change detection and repeated button clicks can otherwise trigger duplicate sessions. A small loading guard is usually enough.
Also remember that browser-originated requests are subject to CORS and CSRF concerns. If your backend uses cookies for auth, protect the endpoint with proper CSRF defenses. If you use bearer tokens from your own identity layer, make sure those tokens are short-lived and scoped to the user who is allowed to create an avatar session.
What to avoid: insecure shortcuts that look convenient
There are a few common mistakes I still see in frontend integrations:
Shipping the API key in the Angular bundle. Obvious in hindsight, but still common.
Calling the avatar API directly from the browser. This usually fails security review and sometimes fails technically because the API expects server-to-server auth.
Using a “temporary” key with broad privileges. If it can create sessions, it can usually be abused.
Relying on obscurity. Minification, obfuscation, or source-map restrictions do not protect secrets.
Even if the app is internal, secrets in frontend code are still discoverable. Internal apps get copied, debugged, proxied, and inspected just like public ones. The attack surface is smaller, but the fundamental issue is unchanged.
When the iframe is the better answer
If your requirement is simply “put a realtime avatar on a page,” and you do not need to orchestrate the avatar session from your own backend, an iframe embed is often the cleanest option. In that model, the browser never sees an API key at all; the embed is customer-managed, and the parent app can be restricted by allowlist, rate limits, and session constraints.
That changes the security equation substantially. Instead of your Angular app brokering credentials, the embed service owns the session lifecycle. This is a good fit when you want the lowest integration burden and do not need deep server-side control over each avatar session.
If you are building a custom product experience around the avatar, though, the backend-mediated model is usually the right one. It gives you more control over user identity, billing attribution, and per-session policy. If you are just adding an avatar surface to a website, the iframe can save a lot of auth plumbing.
How Protoface fits this problem
Protoface is built around exactly these integration boundaries: server-side APIs and SDKs for controlled session creation, plus an iframe path when you want to avoid exposing secrets in the browser altogether. For Angular specifically, the important part is not “how do I cram the key into the frontend?” but “which surface should own the credential and session lifecycle?”
If you are using the REST API or the Python SDK, keep the API key in your backend and have Angular call your own endpoint. If you are embedding an avatar with an iframe, you can skip browser-held credentials completely. The plugin and SDK quickstarts in the docs and the GitHub examples are useful references when you need to wire a voice agent, a session, or a realtime avatar into an existing stack.
For a voice-agent setup, the LiveKit plugin path is also relevant: your agent remains server-side, and the avatar is attached as a synchronized video face inside the agent process. That keeps the browser out of the auth path entirely, which is exactly what you want for anything involving persistent keys.
Example server-side API call with curl, using a secret key stored only on the backend:
The exact endpoint and payload fields depend on the action you are performing; the key point is that this request belongs on your server, not in Angular.
Practical checklist for Angular teams
Never put long-lived API keys in Angular environment files.
Have Angular call your backend for any authenticated avatar/session operation.
Use short-lived, scoped results from the backend, not reusable secrets.
Prefer iframe embeds when you do not need server-side orchestration.
Store API keys in server environment variables or a secret manager.
Log session creation and watch for abnormal usage or burst traffic.
If you are wiring this into an existing codebase, the first implementation is usually small: one backend endpoint, one Angular service, and a component that renders the returned avatar session. The important work is making sure the browser never becomes part of the trust boundary for secret material.
Conclusion
In Angular, protecting API keys is mostly about respecting the browser/server boundary. Anything shipped to the client is exposed, so a realtime avatar integration should either go through your backend or use a browser-safe embed that never needs a secret in the first place.
For implementation details, check docs.protoface.com, and use the relevant SDK or plugin examples when you are ready to wire up session creation on the server. The secure pattern is not complicated; the trick is staying disciplined about where credentials live.
