Required Technical Background for Extensions
Types of Extensions
There are several types of extensions:
- A panel extension appears in the panel area below the video player. Panel extensions remain active even when the channel is not live.
- A video-overlay extension renders on top of the video player as a transparent overlay. This type of extension is viewable only when the channel is live.
- A video-component extension renders on top of both the video player and any video-overlay extensions. Component extensions take up only part of the screen and can be hidden by viewers. This type of extension is viewable only when the channel is live.
Broadcasters can activate up to six extensions at a time: 3 panel, 1 video overlay (full screen), and 2 video component (smaller).
Any extension can also support mobile by adding an optional view. (For details, see Mobile Support in Building Extensions.)
If pop-out control is enabled, the extension iframe has an icon button that viewers can click to pop out the extension into its own window. If an extension is popped out:
- The extension iframe resizes to take up almost the full size of the new window (all but a minimal, Twitch-controlled UI that wraps the extension).
- The channel page retains a placeholder where the popped-out extension was previously. The placeholder has an icon button for the viewer to return the extension back to its original position on the channel page.
To determine whether an extension is popped out, developers can inspect the query string of their iframe for the
popout parameter (see Client Query Parameters in the Extensions Reference).
By default, pop-out control is enabled for panel Extensions and for extension “live configuration views” (see the Live Config Path setting under Asset Hosting in Releasing & Maintaining Extensions).
Extension Life Cycle
Each version of your extension is managed independently in the Extensions section of the developer site. For each version, the Version Status tab allows you to control the life cycle of your extension.
When the locally-hosted test version is satisfactory, the developer transitions it to Hosted Test. This uploads all extension assets to the Twitch CDN, allowing the developer to ensure that the extension still works when served from Twitch. Some sanity checks are performed on upload, such as making sure icons and screenshots are appropriately sized. While in either Local Test or Hosted Test, extensions are visible only to a developer-provided list of test accounts and a small subset of Twitch staff.
Once the hosted test is complete, the developer can submit the extension for Review. The developer can submit the extension for review as many times as desired, but only one version of an extension can be in review at a time. Once a version is submitted, the only way to change it is to put the extension back into Hosted Test and upload the assets again. While in review, all test accounts can continue to test the extension as before.
After the extension is reviewed by Twitch, it is placed into one of three states:
- Pending Action indicates that revisions are required. Using the provided author email address, the developer is contacted and told the reason(s) the extension was not approved. The developer can then take the extension back to a Test state, iterate on the issues, and re-submit the extension for review. No new version needs to be created.
- Rejected indicates that Twitch feels the extension is inappropriate and will not be accepted under any circumstances. This causes a permanent revocation of the extension’s Client ID (a unique identifier). Rejected is a permanent, terminal state.
- Accepted causes developers to be notified that they can make the extension live at any time. Accepted extensions may be transitioned back to a Test state if necessary, but this incurs another full review cycle.
To go live, the developer clicks Release on the version that was Accepted. It then becomes publicly visible and can no longer be updated, only replaced with a new version. When a new version is Released, any previous released version is transitioned to Deprecated, and any installations of that extension are immediately upgraded.
When a new version is Released, developers should:
- Be aware that some viewers or broadcasters may be using the old version at that very moment.
- Ensure that their Extension Backend Service (EBS) can handle traffic from older versions that have not yet been refreshed.
Components of Extensions
Each extension comprises these components:
- An optional EBS, a Web-service backend which stores data or state and communicates with the front ends, by either receiving AJAX requests or using Twitch’s PubSub architecture to broadcast to all viewers.
Extensions are front-end iframes. Typically they communicate via AJAX with an Extension Backend Service (EBS): a Web service that is developed, deployed, and maintained by the extension developer.
While an extension is being tested, the iframe and all its assets are sourced from a URL provided by the extension developer, allowing rapid development iteration. Once the extension is ready for review by Twitch, and later in production, assets to be hosted by Twitch are copied to the Twitch CDN (Content Delivery Network) and served from there.
The Twitch PubSub system provides an additional channel for your EBS to communicate with your extension. Your extension front end can use AJAX to directly call your EBS to retrieve initial state or send viewer-initiated events (like voting). PubSub is a very efficient way for the EBS to directly broadcast real-time events or provide incremental state changes to all instances of your extension.
In a typical use case, your EBS will use the Send Extension PubSub Message endpoint to broadcast messages to viewers using PubSub. Your extension front end will then use the Extension Helper to listen for incoming messages. For details, see the Extensions Reference.
JSON Web Tokens (JWTs)
When developing Twitch extensions, it’s important to fully understand how JSON Web Tokens (JWTs) provide secure communication across Twitch, a viewer’s extension, and your EBS. If you are not familiar with JWTs, visit the official site for an introduction.
Twitch Extensions uses JWTs in two contexts:
- When an extension is loaded in a broadcaster’s or viewer’s browser, a JWT is signed by Twitch and provided to the Extension Helper’s
onAuthorizedcallback. Whenever your extension communicates with your EBS, it is best practice to send the JWT and verify it using your extension’s shared secret. This allows your EBS to verify that the request was made on behalf of the viewer or broadcaster represented by the token, and it prevents malicious users from directly calling your EBS. For details about the callback, see the Extensions Reference.
- When an EBS needs to call a Twitch API, it must generate, sign, and include a JWT in the header. This is known as “bearer token authentication.” By signing your own token with the shared secret, Twitch can authenticate that the API request is coming from your EBS.
The secret is base64 encoded. The secret provided to you in the Extensions dashboard is a base64-encoded string. Depending on the JWT library you use, you probably will have to decode the string before using it as a parameter to sign or verify a JWT.
Example of proper verification of JWTs:
const secret = new Buffer('NOTAREALSECRET==', 'base64'); jwt.verify(token, secret);
Example of signing a JWT:
const secret = new Buffer('NOTAREALSECRET==', 'base64'); const signedToken = jwt.sign(tokenPayload, secret);
Keep your secret private. While this code contains the secret as an example, we strongly recommend that you do not store your secret in your code. It is always best practice to store sensitive information such as secrets, keys, and passwords separate from code, using a dedicated secret-management system.
The Extension Helper provides the iframe with an authentication JWT. When the iframe wants to communicate with its EBS, it sends this token in an HTTP header to the EBS. The JWT is signed by Twitch, using a secret shared between Twitch and the extension developer. The EBS can then use this secret to verify the incoming JWT and ensure that received messages are from a legitimate source. Also, the JWT itself contains reliable information about the role of the sender; e.g., whether the incoming message is from a viewer or a broadcaster.
The Extension Helper provides:
- Callback functions that are invoked with context information about the channel being viewed (e.g., video resolution, latency to the broadcaster, and channel ID).
- Opaque identifiers that identify viewers without revealing their Twitch identity. Using the opaque ID, developers can determine a viewer’s authenticated state. Logged-out users also have an opaque ID, but it is not guaranteed to be the same between channels or sessions.
Opaque IDs persist across all channels, and they do not change unless viewers explicitly request to rotate their identity. We encourage developers to use their EBS to store per-viewer information, using opaque IDs as keys. If your extension needs to know the viewer’s numeric Twitch ID, instructions are provided in Extension Capabilities.
An opaque ID that begins with “A” is a logged-out user and should not be persisted. It will change every time the logged-out user loads your extension.
When a viewer clicks into an extension, Twitch sends focus back to the player, to ensure that keyboard shortcuts for the player continue to work. However, if an extension asks viewers to click on a form field element (for example, “field,” “select,” “textarea”) and the viewer does so, the focus stays on the form element.
The Firefox browser has a known issue that prevents these input types from capturing focus.