Why should a WebRTC application give browsers short-lived TURN credentials instead of one fixed username and password, and how is such a credential usually built?
answer
- anyone can read page code
- a relay is paid bandwidth
- expiry inside the username
- shared secret, HMAC, no RFC
- the 401 exchange is unchanged
basics
~20 sAny TURN credential a browser receives is readable by whoever loads the page, so a fixed password turns the relay into free, identity-masking bandwidth for anyone. Credentials minted per user by the backend and expiring soon limit that abuse to a short window.
solid answer
~50 sRFC 8656 has a TURN server authenticate requests, normally with STUN's long-term credential mechanism, because a relay costs its provider and can hide an attacker's address. The W3C API hands the `username` and `credential` to page script, so they are never secret from the user. No RFC gives a long-term credential an expiry, so the usual answer is a **convention**, not a standard: the backend and the TURN server share a secret; after authenticating the user, the backend returns `iceServers` whose `username` embeds an expiry timestamp (often with a user id) and whose `credential` is an HMAC of that username under the shared secret, base64-encoded. The TURN server recomputes the password from the username, refuses expired ones and needs no per-user database. The client still runs the normal 401, realm and nonce exchange. A leaked credential works until its expiry; rotating the shared secret revokes all of them at once.
code
pseudocode · 17 lines// backend, after the user's session is authenticated
expiry = now() + 6 hours
username = to_string(unix_seconds(expiry)) + ":" + user_id
credential = base64(hmac(SHARED_SECRET, username))
return {
iceServers: [ {
urls: [ "turn:turn.example.org?transport=udp",
"turns:turn.example.org:443?transport=tcp" ],
username: username,
credential: credential } ]
}
// TURN server, on a request carrying USERNAME
if leading_timestamp(USERNAME) < unix_seconds(now()):
reject with 401
password = base64(hmac(SHARED_SECRET, USERNAME))
verify MESSAGE-INTEGRITY using (USERNAME, REALM, password)go deeper
Remember that anything the browser receives, including a TURN password, can be read by the user of that browser.
Explain the convention end to end: shared secret, expiry in the username, HMAC as the password, and the unchanged 401 realm and nonce exchange.
Choose the validity window against call length and leak exposure, and say how you would revoke credentials early without breaking live calls.
Weigh the HMAC convention against standard token-based authorization and against a network-provided relay for enterprise customers.
## Why a fixed TURN password is a liability A **TURN server** relays packets between a WebRTC endpoint and its peer when no direct path works. In the W3C API the application gives the browser the server's `username` and `credential` inside an `RTCIceServer` entry, so they sit in page script or in a response the page fetched. Whatever the browser holds, its user can read. With one fixed password for every user: - anyone can copy it and use the relay for their own traffic, at the provider's bandwidth cost; - the relay hides the user's own address from whoever they talk to, which RFC 8656 names as a reason attackers want unauthorised allocations; - revoking it means changing the password for every legitimate client at once. ## What the specifications require RFC 8656 says a TURN server **MUST** require authentication, using the **long-term credential mechanism** of RFC 8489 or the third-party authorization extension of RFC 7635, unless it is a server offered by the local or access network, which **MAY** accept unauthenticated requests. The long-term mechanism runs like this: 1. The client sends an Allocate with no credentials. 2. The server answers with a 401 error carrying a `REALM` and a `NONCE`. 3. The client retries with `USERNAME`, `REALM`, `NONCE` and a `MESSAGE-INTEGRITY` value keyed from the user name, realm and password. 4. Later Refresh, CreatePermission and ChannelBind requests are authenticated the same way; a stale nonce draws a 438 error and a retry. The mechanism defines **no expiry for the credential** itself, and RFC 8656 warns it is open to offline dictionary attacks when passwords are low-entropy. ## The time-limited credential convention The widely used fix is not defined in any RFC; it is a convention between the application backend and the TURN server, layered on the unchanged long-term mechanism: 1. The backend and the TURN server are configured with the same **shared secret**. 2. After the user signs in, the backend builds `username` = expiry time in Unix seconds, often followed by `:` and a user id. 3. It computes `credential` = base64 of an HMAC of that username keyed with the shared secret. 4. It returns these inside `iceServers`, over the same authenticated HTTPS channel as the rest of the session. 5. The TURN server, seeing the `USERNAME`, recomputes the expected password, checks the embedded expiry and verifies `MESSAGE-INTEGRITY` as usual. Because the password is derived, the TURN server stores no per-user accounts, and the HMAC output has the high entropy that defeats dictionary guessing. ## Choosing the validity window - **Long enough for the call.** A TURN allocation lasts 10 minutes by default and the client keeps it alive with authenticated Refresh requests. Whether a server rejects refreshes once the embedded expiry passes is the server implementation's choice, so the window should outlast the longest expected call. - **Short enough to matter.** A leaked credential works until its expiry; hours, not months, is the usual trade-off. - **Renewable.** A long session can fetch fresh credentials, apply them with `setConfiguration`, and restart ICE so new allocations use them. | Approach | Where defined | A leaked credential works until | How to revoke early | |---|---|---|---| | Fixed long-term password | RFC 8489 / RFC 8656 | the password is changed | change it for every client | | Time-limited HMAC user name | deployment convention | the embedded expiry | rotate the shared secret | | Third-party authorization token | RFC 7635 | the token expires | the authorization server | ## Operating the issuing endpoint - **Authenticate first.** Issue credentials only to a signed-in session; an anonymous issuing endpoint gives the relay away as surely as a fixed password. - **Rate-limit issuance.** One user needs a credential per session or per call, not hundreds per minute. - **Record what was issued.** A user id embedded in the username lets relay logs be tied back to an account when abuse is reported. - **Plan secret rotation.** Accepting both the old and the new shared secret for one validity window lets the secret rotate without failing live calls. ## What the credential does not do - It does **not** protect the media. WebRTC media is encrypted end to end by DTLS-SRTP between the peers; the relay forwards ciphertext. - It does **not** let anyone join the call. A relay forwards only to peers the client has granted permissions to. - It **does** spend the provider's bandwidth, so the issuing endpoint should apply the same rate limits as any other paid resource.
- A short-lived TURN credential leaks into a support ticket; what can an attacker do with it, and for how long?Until the expiry embedded in the username, they can open allocations on your TURN server and relay their own traffic through it, at your cost and behind your relay's address. They cannot decrypt the user's calls, because media is protected end to end by DTLS-SRTP. To stop them sooner, rotate the shared secret, which also invalidates every legitimate credential still in use.
- Why does the endpoint that issues TURN credentials need the same protection as a login API?The credential is a bearer secret: whoever reads the response can use the relay. The endpoint must authenticate the caller before issuing, be served over TLS, and be rate limited, otherwise an attacker simply asks it for fresh credentials and the expiry protects nothing.
saying these in an interview costs you the question
- The TURN specification sets a standard 24-hour expiry for credentials.
- Minifying the page code keeps an embedded TURN password secret.
- The TURN credential protects the media from the relay operator.
- Time-limited HMAC usernames are a mechanism defined in RFC 8656.
- Short-lived credentials need a per-user account database on the TURN server.