I realized that building an Iframe embed generator for Tweets should be fairly easy, and this tool is the result of that goal. It allows you to plug in the URL of a tweet, and get an IFrame embed code, with configurable options.
The tool is fairly simple: Plug in the URL of a tweet, hit the “generate” button, and get back IFrame embed code that you can paste into your own website, or forums that accept IFrame embeds. Unlike other approaches (e.g. Twitframe), my tool simply wraps the Twitter embed code in an IFrame wrapper, using some IFrame generation tricks.
I built it using vanilla JS – no frameworks. I’ve used React, Vue, and other frameworks on other projects, but wanted to get some practice coding things from scratch on this, especially since I wanted a fast build.
Learnings / Tools Used
- JSONP still is useful!
- It has been a while since I have had to use the JSONP workaround method, but it proved invaluable on this project, since Twitter does not provide the right headers for CORS, but does support JSONP responses.
- Twitter’s OEmbed API
- My previous research on different iframe generation methods.
- Materialize CSS
Why Not Use SRI?
Subresource Integrity (SRI) (MDN Docs) is a security feature baked into several modern browsers, that provides a way to verify (and enforce) that the external resource received from a remote source exactly matches what was requested.
You can use it by including a “hash digest” when you add
<script> and other resource tags to your website, as an
integrity attribute. In practical terms, this means if you add a script tag that loads
fake-external-website.com/script.js, but you hash and add the hash as an integrity key when adding it, you can be guaranteed that you will always get the exact same
script.js each time. This is an important security feature, because you can audit scripts as you add them, and if four months after adding them, the vendor suddenly adds a keylogger, the script will get blocked because the hash will no longer match the original hash.
This all sounds great, so why not use it with Twitter? Well, you can! But there are some downsides, which I’ll cover first:
- Every time Twitter changes their code (in
https://platform.twitter.com/widgets.js), it will break all embeds that rely on it
- Since the hashes have to exactly match, even them adding a single semicolon will cause the script to start getting blocked
- Each time they make an update, you would have to audit the change, then compute a new hash digest and update your embed code
- SRI is not the same as sandboxing
- With SRI, the only guarantee is that the external code has not changed; not that it is safe to use. Auditing the code is up to you, as a developer, and if you miss something, there could be catastrophic results (embedded keyloggers, PII stealers, etc.)
- In comparison, IFrames provide a high level of sandboxing by default
- SRI does not provide isolated styles
- Another benefit of Iframes are that they prevent conflicting CSS rules, by isolating the content inside the iframe from the content outside
- SRI is not supported by all browsers
- Adoption is growing though, and already has about ~95% global support
If you don’t mind all of those downsides, here is how you would go about enforcing SRI on a Twitter embed.
- Compute the hash digest of the Twitter embed JS file, with a given hash function. Once you have it, prefix the hash with the function type and a hyphen (e.g.
- At the time of writing this, for Twitter’s
widgets.js, the string would be:
- You can use online tools to get the hash, like srihash.org, or the OpenSSL CLI, with
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
- At the time of writing this, for Twitter’s
- In the Twitter embed snippet, find the
<script>, and add the integrity attribute with the string you generated above
<script async src="https://platform.twitter.com/widgets.js" integrity="sha384-SR82MxVe9kFn41L4YvfLllMtR3HJ/jl5ubYdBBHjbTUBG31k2Zo4ZTuZXFxeP3Gd" charset="utf-8"></script>
- Because Twitter does not return the right CORS headers, and SRI checking requires a value for the
crossoriginattribute, you also need to add
crossorigin="anonymous"as an attribute key-pair.
- Update example:
<script async src="https://platform.twitter.com/widgets.js" integrity="sha384-SR82MxVe9kFn41L4YvfLllMtR3HJ/jl5ubYdBBHjbTUBG31k2Zo4ZTuZXFxeP3Gd" crossorigin="anonymous" charset="utf-8"></script>
- Update example:
Why Not Twitframe?
Twitframe is a cool project that has the same end goal as mine; replace Twitter’s third party JS embeds with IFrame wrappers. However, Twitframe uses their own servers to proxy the Twitter request; this means that, at the end of the day, using their service still requires a level of trust of a third party. Since the content is now being served / proxied through Twitframe, you now have to trust that they will simply mirror the content from Twitter, and not alter it in any way.
Since the IFrame protects you from JS exploits, the worst case scenario using Twitframe is unwanted visual content on your site. For example, they could get hacked and someone could force it to response to every embed request with obscene content or clickbait malvertising.
My approach does not alter Twitter’s response or embed code in any way; it is truly just a “dumb” wrapper / sandbox around it. The actual network request for tweet content goes directly from your visitor’s computer to Twitter, and is not proxied through any third-party servers.
Downsides / Caveats
- Limited IE support
- No Responsive Design:
- The biggest drawback from this method is that the IFrames are not responsive (by default). Meaning, you must specify the height beforehand, and if the tweet ends up being larger (longer) than the height you set it at, there will either be a scrollbar in the embed to see the rest of the content, or, if you turned off overflow, it will simply be hidden.
- I could design a way to make these embeds responsive (likely using
- Blocking by user or extension
- Potentially, a user could have their browser set to block IFrames by default. However, this is extremely rare, and even ad-blockers don’t usually interfere with IFrames