Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Strubbl/5e98222ebde4fc8f2c4cc41bc2a055b2 to your computer and use it in GitHub Desktop.
Save Strubbl/5e98222ebde4fc8f2c4cc41bc2a055b2 to your computer and use it in GitHub Desktop.
$ curl -Lv https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529
* Trying 52.1.119.170...
* TCP_NODELAY set
* Connected to hueniverse.com (52.1.119.170) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: OU=Domain Control Validated; OU=PositiveSSL; CN=hueniverse.com
* start date: Apr 3 00:00:00 2017 GMT
* expire date: Apr 3 23:59:59 2018 GMT
* subjectAltName: host "hueniverse.com" matched cert's "hueniverse.com"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0xfb2120)
> GET /oauth-2-0-and-the-road-to-hell-8eec45921529 HTTP/2
> Host: hueniverse.com
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 302
< server: nginx
< date: Tue, 09 May 2017 21:36:47 GMT
< content-type: text/html
< content-length: 154
< location: https://medium.com/m/global-identity?redirectUrl=https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529
<
* Ignoring the response-body
* Connection #0 to host hueniverse.com left intact
* Issue another request to this URL: 'https://medium.com/m/global-identity?redirectUrl=https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529'
* Trying 104.16.121.127...
* TCP_NODELAY set
* Connected to medium.com (104.16.121.127) port 443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: businessCategory=Private Organization; jurisdictionC=US; jurisdictionST=Delaware; serialNumber=5010624; street=760 Market Street; postalCode=94102; C=US; ST=California; L=San Francisco; O=A Medium Corporation; CN=medium.com
* start date: May 21 00:00:00 2015 GMT
* expire date: Aug 18 12:00:00 2017 GMT
* subjectAltName: host "medium.com" matched cert's "medium.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 Extended Validation Server CA
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0xfb2120)
> GET /m/global-identity?redirectUrl=https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529 HTTP/2
> Host: medium.com
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 302
< date: Tue, 09 May 2017 21:36:48 GMT
< set-cookie: __cfduid=d4e8190bf0879d752823fd15eb0eabbc61494365807; expires=Wed, 09-May-18 21:36:47 GMT; path=/; domain=.medium.com; HttpOnly
< content-security-policy: default-src 'self'; connect-src https://localhost https://*.instapaper.com https://*.stripe.com https://getpocket.com https://medium.com:443 https://*.medium.com:443 https://*.medium.com https://medium.com https://*.medium.com https://*.algolia.net https://cdn-static-1.medium.com https://dnqgz544uhbo8.cloudfront.net https://*.lightstep.com https://app.zencoder.com 'self'; font-src data: https://*.amazonaws.com https://*.medium.com https://medium.com https://*.gstatic.com https://dnqgz544uhbo8.cloudfront.net https://use.typekit.net https://cdn-static-1.medium.com 'self'; frame-src chromenull: https: webviewprogressproxy: medium: 'self'; img-src blob: data: https: 'self'; media-src https://*.cdn.vine.co https://d1fcbxp97j4nb2.cloudfront.net https://d262ilb51hltx0.cloudfront.net https://*.medium.com https://gomiro.medium.com https://miro.medium.com https://pbs.twimg.com 'self'; object-src 'self'; script-src 'unsafe-eval' 'unsafe-inline' about: https: 'self'; style-src 'unsafe-inline' data: https: 'self'; report-uri https://csp.medium.com
< x-frame-options: sameorigin
< x-content-type-options: nosniff
< x-xss-protection: 1; mode=block
< x-ua-compatible: IE=edge, Chrome=1
< x-powered-by: Medium
< x-obvious-tid: 1494365807928:c2db17804d48
< x-obvious-info: 28895-2c69272,2c69272
< link: <https://medium.com/humans.txt>; rel="humans"
< cache-control: no-cache, no-store, max-age=0, must-revalidate
< expires: Thu, 09 Sep 1999 09:09:09 GMT
< pragma: no-cache
< set-cookie: uid=lo_b364a39284f5; path=/; expires=Wed, 09 May 2018 21:36:47 GMT; domain=.medium.com; secure; httponly
< set-cookie: sid=1:by8wOtQ1+6KN8egUoaVw1dLU6esSY172D/CbdLHyxqm4DcvnDWQMSgH27+38Rdal; path=/; expires=Wed, 09 May 2018 21:36:47 GMT; domain=.medium.com; secure; httponly
< tk: T
< location: https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529?gi=c74d25f59452
< strict-transport-security: max-age=15552000; includeSubDomains; preload
< server: cloudflare-nginx
< cf-ray: 35c7cbd97a592d71-TXL
<
* Connection #1 to host medium.com left intact
* Issue another request to this URL: 'https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529?gi=c74d25f59452'
* Found bundle for host hueniverse.com: 0xfc7640 [can multiplex]
* Re-using existing connection! (#0) with host hueniverse.com
* Connected to hueniverse.com (52.1.119.170) port 443 (#0)
* Using Stream ID: 3 (easy handle 0xfb2120)
> GET /oauth-2-0-and-the-road-to-hell-8eec45921529?gi=c74d25f59452 HTTP/2
> Host: hueniverse.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/2 200
< server: nginx
< date: Tue, 09 May 2017 21:36:48 GMT
< content-type: text/html; charset=utf-8
< content-length: 113527
< content-security-policy: default-src 'self'; connect-src https://localhost https://*.instapaper.com https://*.stripe.com https://getpocket.com https://hueniverse.com https://*.hueniverse.com https://*.medium.com https://medium.com https://*.medium.com https://*.algolia.net https://cdn-static-1.medium.com https://dnqgz544uhbo8.cloudfront.net https://*.lightstep.com https://app.zencoder.com 'self'; font-src data: https://*.amazonaws.com https://*.medium.com https://medium.com https://*.gstatic.com https://dnqgz544uhbo8.cloudfront.net https://use.typekit.net https://cdn-static-1.medium.com 'self'; frame-src chromenull: https: webviewprogressproxy: medium: 'self'; img-src blob: data: https: 'self'; media-src https://*.cdn.vine.co https://d1fcbxp97j4nb2.cloudfront.net https://d262ilb51hltx0.cloudfront.net https://*.medium.com https://gomiro.medium.com https://miro.medium.com https://pbs.twimg.com 'self'; object-src 'self'; script-src 'unsafe-eval' 'unsafe-inline' about: https: 'self'; style-src 'unsafe-inline' data: https: 'self'; report-uri https://csp.medium.com
< x-frame-options: sameorigin
< x-content-type-options: nosniff
< x-xss-protection: 1; mode=block
< x-ua-compatible: IE=edge, Chrome=1
< x-powered-by: Medium
< x-obvious-tid: 1494365808166:1fd9e3737d29
< x-obvious-info: 28895-2c69272,2c69272
< link: <https://medium.com/humans.txt>; rel="humans"
< cache-control: no-cache, no-store, max-age=0, must-revalidate
< expires: Thu, 09 Sep 1999 09:09:09 GMT
< pragma: no-cache
< set-cookie: uid=lo_b364a39284f5; path=/; expires=Wed, 09 May 2018 21:36:48 GMT; secure; httponly
< set-cookie: sid=1:cMP9xnClFZD1DuCIwjPMGouqYq+GL4uJUpsrpPbwNzsV11jk/zFGrwPFZs4lr3iC; path=/; expires=Wed, 09 May 2018 21:36:48 GMT; secure; httponly
< tk: T
<
<!DOCTYPE html><html xmlns:cc="http://creativecommons.org/ns#"><head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# medium-com: http://ogp.me/ns/fb/medium-com#"><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>OAuth 2.0 and the Road to Hell – hueniverse</title><link rel="canonical" href="https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529"><meta name="title" content="OAuth 2.0 and the Road to Hell – hueniverse"><meta name="referrer" content="unsafe-url"><meta name="description" content="Last month I reached the painful conclusion that I can no longer be associated with the OAuth 2.0 standard. I resigned my role as lead author and editor, withdraw my name from the specification, and…"><meta name="theme-color" content="#000000"><meta property="og:title" content="OAuth 2.0 and the Road to Hell – hueniverse"><meta property="og:url" content="https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529"><meta property="fb:app_id" content="542599432471018"><meta property="og:description" content="Last month I reached the painful conclusion that I can no longer be associated with the OAuth 2.0 standard. I resigned my role as lead author and editor, withdraw my name from the specification, and…"><meta name="twitter:description" content="Last month I reached the painful conclusion that I can no longer be associated with the OAuth 2.0 standard. I resigned my role as lead author and editor, withdraw my name from the specification, and…"><link rel="publisher" href="https://plus.google.com/103654360130207659246"><link rel="author" href="https://hueniverse.com/@eranhammer"><meta property="author" content="Eran Hammer"><meta property="og:type" content="article"><meta name="twitter:card" content="summary"><meta property="article:publisher" content="https://www.facebook.com/medium"><meta property="article:author" content="https://hueniverse.com/@eranhammer"><meta property="fb:smart_publish:robots" content="noauto"><meta name="robots" content="index, follow"><meta property="article:published_time" content="2012-07-26T07:37:23.000Z"><meta name="twitter:creator" content="@eranhammer"><meta name="twitter:site" content="@eranhammer"><meta property="og:site_name" content="hueniverse"><meta name="twitter:label1" value="Reading time"><meta name="twitter:data1" value="8 min read"><script type="application/ld+json">{"@context":"http://schema.org","@type":"NewsArticle","image":{"@type":"ImageObject","width":1920,"height":534,"url":"https://cdn-images-1.medium.com/max/1920/1*5ztbgEt4NqpVaxTc64C-XA.png"},"datePublished":"2012-07-26T07:37:23.000Z","dateModified":"2017-04-24T09:53:57.587Z","headline":"OAuth 2.0 and the Road to Hell","name":"OAuth 2.0 and the Road to Hell","keywords":["Oauth","Open Web"],"author":{"@type":"Person","name":"Eran Hammer","url":"https://hueniverse.com/@eranhammer"},"creator":["Eran Hammer"],"publisher":{"@type":"Organization","name":"hueniverse","url":"https://hueniverse.com","logo":{"@type":"ImageObject","width":215,"height":60,"url":"https://cdn-images-1.medium.com/max/215/1*5ztbgEt4NqpVaxTc64C-XA.png"}},"mainEntityOfPage":"https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529"}</script><meta name="twitter:app:name:iphone" content="Medium"><meta name="twitter:app:id:iphone" content="828256236"><meta name="twitter:app:url:iphone" content="medium://p/8eec45921529"><meta property="al:ios:app_name" content="Medium"><meta property="al:ios:app_store_id" content="828256236"><meta property="al:android:package" content="com.medium.reader"><meta property="al:android:app_name" content="Medium"><meta property="al:ios:url" content="medium://p/8eec45921529"><meta property="al:android:url" content="medium://p/8eec45921529"><meta property="al:web:url" content="https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529"><link rel="search" type="application/opensearchdescription+xml" title="Medium" href="/osd.xml" /><link rel="alternate" href="android-app://com.medium.reader/https/medium.com/p/8eec45921529" /><link rel="stylesheet" href="https://cdn-static-1.medium.com/_/fp/css/main-base.BSzNYMd8CpAc8O9hTez-JA.css"><script>if (window.top !== window.self) window.top.location = window.self.location.href;var OB_startTime = new Date().getTime(); var OB_loadErrors = []; function _onerror(e) { OB_loadErrors.push(e) }; if (document.addEventListener) document.addEventListener("error", _onerror, true); else if (document.attachEvent) document.attachEvent("onerror", _onerror); function _asyncScript(u) {var d = document, f = d.getElementsByTagName("script")[0], s = d.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = u; f.parentNode.insertBefore(s, f);}function _asyncStyles(u) {var d = document, f = d.getElementsByTagName("script")[0], s = d.createElement("link"); s.rel = "stylesheet"; s.href = u; f.parentNode.insertBefore(s, f); return s}(new Image()).src = "/_/stat?event=pixel.load&origin=" + encodeURIComponent(location.origin);</script><script>window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date; ga("create", "UA-24232453-2", "auto", {"allowLinker": true, "legacyCookieDomain": window.location.hostname}); ga("send", "pageview");</script><script async src="https://www.google-analytics.com/analytics.js"></script><script>(function () {var height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; document.write("<style>section.section-image--fullBleed.is-backgrounded {padding-top: " + Math.round(1.1 * height) + "px;}section.section-image--fullScreen.is-backgrounded, section.section-image--coverFade.is-backgrounded {min-height: " + height + "px; padding-top: " + Math.round(0.5 * height) + "px;}.u-sizeViewHeight100 {height: " + height + "px !important;}.u-sizeViewHeight110 {height: " + Math.round(1.1 * height) + "px !important;}.u-sizeViewHeightMin100 {min-height: " + height + "px !important;}.u-sizeViewHeightMax100 {max-height: " + height + "px !important;}section.section-image--coverFade {height: " + height + "px;}.section-aspectRatioViewportPlaceholder, .section-aspectRatioViewportCropPlaceholder {max-height: " + height + "px;}.section-aspectRatioViewportBottomSpacer, .section-aspectRatioViewportBottomPlaceholder {max-height: " + Math.round(0.5 * height) + "px;}.zoomable:before {top: " + (-1 * height) + "px; left: " + (-1 * width) + "px; padding: " + height + "px " + width + "px;}</style>");})()</script><!--[if lt IE 9]><script charset="UTF-8" src="https://cdn-static-1.medium.com/_/fp/js/shiv.RI2ePTZ5gFmMgLzG5bEVAA.js"></script><![endif]--><link rel="icon" href="https://cdn-static-1.medium.com/_/fp/icons/favicon-medium.TAS6uQ-Y7kcKgi0xjcYHXw.ico" class="js-favicon"><link rel="apple-touch-icon" sizes="152x152" href="https://cdn-images-1.medium.com/fit/c/152/152/1*FucaTWCRPOZ6XdfDCe3c4Q.png"><link rel="apple-touch-icon" sizes="120x120" href="https://cdn-images-1.medium.com/fit/c/120/120/1*FucaTWCRPOZ6XdfDCe3c4Q.png"><link rel="apple-touch-icon" sizes="76x76" href="https://cdn-images-1.medium.com/fit/c/76/76/1*FucaTWCRPOZ6XdfDCe3c4Q.png"><link rel="apple-touch-icon" sizes="60x60" href="https://cdn-images-1.medium.com/fit/c/60/60/1*FucaTWCRPOZ6XdfDCe3c4Q.png"><link rel="mask-icon" href="https://cdn-static-1.medium.com/_/fp/icons/favicon.KjTfUJo7yJH_fCoUzzH3cg.svg" color="#171717"></head><body itemscope class=" postShowScreen is-noJs"><script>document.body.className = document.body.className.replace(/(^|\s)is-noJs(\s|$)/, "$1is-js$2")</script><div class="site-main" id="container"><div class="butterBar butterBar--error"></div><div class="surface"><div id="prerendered" class="screenContent"><canvas class="canvas-renderer"></canvas><div class="container u-maxWidth740 u-xs-margin0 notesPositionContainer js-notesPositionContainer"></div><div class="metabar u-clearfix js-metabar"><div class="metabar-inner u-marginAuto u-maxWidth1000 u-paddingLeft20 u-paddingRight20 js-metabarMiddle"><div class="metabar-block metabar-block--left u-floatLeft u-height65 u-xs-height56"><div class="u-alignMiddle u-inlineBlock u-verticalAlignTop u-height65 u-xs-height56 u-marginRight18"><div class="u-alignBlock"><a class="js-logCollection" href="https://hueniverse.com?source=logo-lo_b364a39284f5---ee73cfff03f"><span class="u-uiTextBold u-fontSize18 u-lineHeight18 u-xs-fontSize22 u-xs-lineHeight22 u-xs-noWrapWithEllipsis u-inlineBlock u-xs-maxWidth200 u-textColorDark">hueniverse</span></a></div></div><div class="u-alignMiddle u-inlineBlock u-verticalAlignTop u-height65 u-xs-height56 u-xs-hide"><div class="u-alignBlock"><div class="buttonSet u-lineHeightInherit u-marginLeft0"><div class="buttonSet-inner"><button class="button button--primary u-paddingLeft10 u-paddingRight10 u-height19 u-lineHeight13 u-verticalAlignMiddle u-fontSize12 u-uiTextMedium button--small u-noUserSelect button--withChrome u-accentColor--buttonNormal js-relationshipButton is-smallPill" data-action="sign-in-prompt" data-sign-in-action="toggle-follow-collection" data-requires-token="true" data-redirect="https://medium.com/_/subscribe/collection/hueniverse" data-collection-id="ee73cfff03f"><span class="button-label js-buttonLabel">Follow</span></button></div><a class="button button--chromeless is-touchIconBlackPulse u-baseColor--buttonNormal button--withIcon button--withSvgIcon" href="https://twitter.com/eranhammer" title="Visit “hueniverse” on Twitter" aria-label="Visit “hueniverse” on Twitter" rel="me" target="_blank"><span class="button-defaultState"><span class="svgIcon svgIcon--twitterFilled svgIcon--25px"><svg class="svgIcon-use" width="25" height="25" viewBox="0 0 25 25" ><path d="M21.725 5.338c-.744.47-1.605.804-2.513 1.006a3.978 3.978 0 0 0-2.942-1.293c-2.22 0-4.02 1.81-4.02 4.02 0 .32.034.63.07.94-3.31-.18-6.27-1.78-8.255-4.23a4.544 4.544 0 0 0-.574 2.01c.04 1.43.74 2.66 1.8 3.38-.63-.01-1.25-.19-1.79-.5v.08c0 1.93 1.38 3.56 3.23 3.95-.34.07-.7.12-1.07.14-.25-.02-.5-.04-.72-.07.49 1.58 1.97 2.74 3.74 2.8a8.49 8.49 0 0 1-5.02 1.72c-.3-.03-.62-.04-.93-.07A11.447 11.447 0 0 0 8.88 21c7.386 0 11.43-6.13 11.414-11.414.015-.21.01-.38 0-.578a7.604 7.604 0 0 0 2.01-2.08 7.27 7.27 0 0 1-2.297.645 3.856 3.856 0 0 0 1.72-2.23"/></svg></span></span></a></div></div></div></div><div class="metabar-block u-floatRight u-xs-absolute u-xs-textAlignRight u-xs-right0 u-xs-marginRight20 u-height65 u-xs-height56"><div class="u-alignMiddle u-inlineBlock u-verticalAlignTop u-height65 u-xs-height56"><div class="u-alignBlock"><div class="buttonSet u-lineHeightInherit"><a class="button button--primary button--chromeless u-accentColor--buttonNormal is-inSiteNavBar u-lineHeight30 u-height32" href="https://medium.com/m/signin?redirect=https%3A%2F%2Fhueniverse.com%2Foauth-2-0-and-the-road-to-hell-8eec45921529" data-action="sign-in-prompt" data-redirect="https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529" data-action-source="nav_signup">Sign in / Sign up</a></div></div></div></div></div></div><div class="metabar metabar--spacer js-metabarSpacer u-height65 u-xs-height56"></div><main role="main"><article class=" u-sizeViewHeightMin100 u-overflowHidden postArticle postArticle--full is-withAccentColors u-marginBottom40" lang="en"><header class="container u-maxWidth740"><div class="postMetaHeader u-paddingBottom10 row"><div class="col u-size12of12 js-postMetaLockup"><div class="postMetaLockup postMetaLockup--authorWithBio u-flex js-postMetaLockup"><div class="u-flex0"><a class="link avatar u-baseColor--link" href="https://hueniverse.com/@eranhammer?source=post_header_lockup" data-action="show-user-card" data-action-source="post_header_lockup" data-action-value="b4e3921706ee" data-action-type="hover" data-user-id="b4e3921706ee" data-collection-slug="hueniverse" dir="auto"><img src="https://cdn-images-1.medium.com/fit/c/40/40/0*3ZLq0yvVG4WO2TBk.jpg" class="avatar-image avatar-image--smaller" alt="Go to the profile of Eran Hammer"></a></div><div class="u-flex1 u-paddingLeft15 u-overflowHidden"><a class="link link link--darken link--darker u-baseColor--link" href="https://hueniverse.com/@eranhammer?source=post_header_lockup" data-action="show-user-card" data-action-source="post_header_lockup" data-action-value="b4e3921706ee" data-action-type="hover" data-user-id="b4e3921706ee" data-collection-slug="hueniverse" dir="auto">Eran Hammer</a><span class="followState js-followState buttonSet-inner" data-user-id="b4e3921706ee"><button class="button u-paddingLeft10 u-paddingRight10 u-height19 u-lineHeight13 u-verticalAlignMiddle u-fontSize12 u-uiTextMedium u-noUserSelect button--withChrome u-baseColor--buttonNormal button--withHover button--unblock js-unblockButton u-marginLeft10 u-marginTopNegative2 u-xs-hide" data-action="sign-in-prompt" data-sign-in-action="toggle-block-user" data-requires-token="true" data-action-source="post_header_lockup"><span class="button-label button-defaultState">Blocked</span><span class="button-label button-hoverState">Unblock</span></button><button class="button button--primary u-paddingLeft10 u-paddingRight10 u-height19 u-lineHeight13 u-verticalAlignMiddle u-fontSize12 u-uiTextMedium u-noUserSelect button--withChrome u-accentColor--buttonNormal button--follow js-followButton u-marginLeft10 u-marginTopNegative2 u-xs-hide" data-action="sign-in-prompt" data-sign-in-action="toggle-subscribe-user" data-requires-token="true" data-redirect="https://medium.com/_/subscribe/user/b4e3921706ee" data-action-source="post_header_lockup_follow"><span class="button-label button-defaultState js-buttonLabel">Follow</span><span class="button-label button-activeState">Following</span></button></span><div class="postMetaInline js-testPostMetaInlineSupplemental"><time datetime="2012-07-26T07:37:23.000Z">Jul 25, 2012</time><span class="middotDivider u-fontSize12"></span><span class="readingTime" title="8 min read"></span></div></div></div></div></div></header><div class="postArticle-content js-postField js-notesSource js-trackedPost" data-post-id="8eec45921529" data-source="post_page" data-collection-id="ee73cfff03f" data-tracking-context="postPage"><section name="44d6" class="section section--body section--first section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><h1 name="38e1" id="38e1" class="graf graf--h3 graf--leading graf--title">OAuth 2.0 and the Road to Hell</h1><p name="3792" id="3792" class="graf graf--p graf-after--h3"><strong class="markup--strong markup--p-strong">Update: three years later I wrote something new… introducing Oz.</strong></p><p name="95f4" id="95f4" class="graf graf--p graf-after--p">They say the road to hell is paved with good intentions. Well, that’s <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2" data-href="http://tools.ietf.org/html/draft-ietf-oauth-v2" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">OAuth 2.0</a>.</p><p name="3621" id="3621" class="graf graf--p graf-after--p">Last month I reached the painful conclusion that I can no longer be associated with the OAuth 2.0 standard. I resigned my role as lead author and editor, <strong class="markup--strong markup--p-strong">withdraw my name from the specification</strong>, and left the working group. Removing my name from a document I have painstakingly labored over for three years and over two dozen drafts was not easy. Deciding to move on from an effort I have led for over five years was agonizing.</p><p name="716f" id="716f" class="graf graf--p graf-after--p">There wasn’t a single problem or incident I can point to in order to explain such an extreme move. This is a case of death by a thousand cuts, and as the work was winding down, I’ve found myself reflecting more and more on what we actually accomplished. At the end, I reached the conclusion that OAuth 2.0 is a bad protocol. WS-* bad. It is bad enough that I no longer want to be associated with it. It is the biggest professional disappointment of my career.</p><p name="2696" id="2696" class="graf graf--p graf-after--p">All the hard fought compromises on the mailing list, in meetings, in special design committees, and in back channels resulted in a specification that fails to deliver its two main goals — security and interoperability. In fact, one of the compromises was to rename it from a protocol to a framework, and another to add a <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-1.8" data-href="http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-1.8" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">disclaimer that warns that the specification is unlike to produce interoperable implementations</a>.</p><p name="b7a8" id="b7a8" class="graf graf--p graf-after--p">When compared with <a href="http://tools.ietf.org/html/rfc5849" data-href="http://tools.ietf.org/html/rfc5849" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">OAuth 1.0</a>, the 2.0 specification is more complex, less interoperable, less useful, more incomplete, and most importantly, less secure.</p><p name="2b3b" id="2b3b" class="graf graf--p graf-after--p">To be clear, OAuth 2.0 at the hand of a developer with deep understanding of web security will likely result is a secure implementation. However, at the hands of most developers — as has been the experience from the past two years — 2.0 is likely to produce insecure implementations.</p><h4 name="e7e1" id="e7e1" class="graf graf--h4 graf-after--p">How did we get here?</h4><p name="3493" id="3493" class="graf graf--p graf-after--h4">At the core of the problem is the strong and unbridgeable conflict between the <strong class="markup--strong markup--p-strong">web</strong> and the <strong class="markup--strong markup--p-strong">enterprise</strong> worlds. The OAuth working group at the IETF started with strong web presence. But as the work dragged on (and on) past its first year, those web folks left along with every member of the original 1.0 community. The group that was left was largely all enterprise… and me.</p><p name="c287" id="c287" class="graf graf--p graf-after--p">The web community was looking for a protocol very much in-line with 1.0, with small improvement in areas that proved lacking: simplifying signature, adding a light identity layer, addressing native applications, adding more flows to accommodate new client types, and improving security. The enterprise community was looking for a framework they can use with minimal changes to their existing systems, and for some, a new source of revenues through customization. To understand the depth of the divide — in an early meeting the web folks wanted a flow optimized for in-browser clients while the enterprise folks wanted a flow using SAML assertions.</p><p name="8e78" id="8e78" class="graf graf--p graf-after--p">The resulting specification is a <strong class="markup--strong markup--p-strong">designed-by-committee</strong> patchwork of compromises that serves mostly the enterprise. To be accurate, it doesn’t actually give the enterprise all of what they asked for directly, but it does provide for practically unlimited extensibility. It is this extensibility and required flexibility that destroyed the protocol. <strong class="markup--strong markup--p-strong">With very little effort, pretty much anything can be called OAuth 2.0 compliant.</strong></p><h4 name="3d14" id="3d14" class="graf graf--h4 graf-after--p">Under the Hood</h4><p name="ddca" id="ddca" class="graf graf--p graf-after--h4">To understand the issues in 2.0, you need to understand the core architectural changes from 1.0:</p><ul class="postList"><li name="9999" id="9999" class="graf graf--li graf-after--p"><strong class="markup--strong markup--li-strong">Unbounded tokens</strong> — In 1.0, the client has to present two sets of credentials on each protected resource request, the token credentials and the client credentials. In 2.0, the client credentials are no longer used. This means that tokens are no longer bound to any particular client type or instance. This has introduced limits on the usefulness of access tokens as a form of authentication and increased the likelihood of security issues.</li><li name="12c2" id="12c2" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Bearer tokens</strong> — 2.0 got rid of all signatures and cryptography at the protocol level. Instead it relies solely on TLS. This means that <a href="http://hueniverse.com/2010/09/oauth-bearer-tokens-are-a-terrible-idea/" data-href="http://hueniverse.com/2010/09/oauth-bearer-tokens-are-a-terrible-idea/" class="markup--anchor markup--li-anchor" target="_blank">2.0 tokens are inherently less secure as specified</a>. Any improvement in token security requires additional specifications and as the current proposals <a href="http://openid.net/specs/draft-jones-json-web-token-07.html" data-href="http://openid.net/specs/draft-jones-json-web-token-07.html" class="markup--anchor markup--li-anchor" rel="noopener" target="_blank">demonstrate</a>, the group is solely focused on enterprise use cases.</li><li name="459e" id="459e" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Expiring tokens</strong> — 2.0 tokens can expire and must be refreshed. This is the most significant change for client developers from 1.0 as they now need to implement token state management. The reason for token expiration is to accommodate self-encoded tokens — encrypted tokens which can be authenticated by the server without a database look-up. Because such tokens are self-encoded, they cannot be revoked and therefore must be short-lived to reduce their exposure. Whatever is gained from the removal of the signature is lost twice in the introduction of the token state management requirement.</li><li name="230e" id="230e" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Grant types</strong> — In 2.0, authorization grants are exchanged for access tokens. Grant is an abstract concept representing the end-user approval. It can be a code received after the user clicks ‘Approve’ on an access request, or the user’s actual username and password. The original idea behind grants was to enable multiple flows. 1.0 provides a single flow which aims to accommodate multiple client types. 2.0 adds significant amount of specialization for different client type.</li></ul><h4 name="b0bc" id="b0bc" class="graf graf--h4 graf-after--li">Indecision Making</h4><p name="a8da" id="a8da" class="graf graf--p graf-after--h4">These changes are all manageable if put together in a well-defined protocol. But as has been the nature of this working group, no issue is too small to get stuck on or leave open for each implementation to decide. Here is a very short <strong class="markup--strong markup--p-strong">sample</strong> of the working group’s inability to agree:</p><ul class="postList"><li name="5a4c" id="5a4c" class="graf graf--li graf-after--p">No required token type</li><li name="7cae" id="7cae" class="graf graf--li graf-after--li">No agreement on the goals of an HMAC-enabled token type</li><li name="3f9b" id="3f9b" class="graf graf--li graf-after--li">No requirement to implement token expiration</li><li name="d8e7" id="d8e7" class="graf graf--li graf-after--li">No guidance on token string size, or any value for that matter</li><li name="6ec1" id="6ec1" class="graf graf--li graf-after--li">No strict requirement for registration</li><li name="989a" id="989a" class="graf graf--li graf-after--li">Loose client type definition</li><li name="cca4" id="cca4" class="graf graf--li graf-after--li">Lack of clear client security properties</li><li name="f073" id="f073" class="graf graf--li graf-after--li">No required grant types</li><li name="fbb5" id="fbb5" class="graf graf--li graf-after--li">No guidance on the suitability or applicability of grant types</li><li name="2e5a" id="2e5a" class="graf graf--li graf-after--li">No useful support for native applications (but lots of lip service)</li><li name="cbec" id="cbec" class="graf graf--li graf-after--li">No required client authentication method</li><li name="3428" id="3428" class="graf graf--li graf-after--li">No limits on extensions</li></ul><p name="914a" id="914a" class="graf graf--p graf-after--li">On the other hand, 2.0 defines 4 new registries for extensions, along with additional extension points via URIs. The result is a flood of proposed extensions. But the real issues is that the working group could not define the real security properties of the protocol. This is clearly reflected in the security consideration section which is largely an exercise of hand waving. It is barely useful to security experts as a bullet point of things to pay attention to.</p><p name="b824" id="b824" class="graf graf--p graf-after--p">In fact, the working group has also produced a 70 pages document describing the <a href="http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel" data-href="http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank">2.0 threat model</a> which does attempt to provide additional information but suffers from the same fundamental problem: there isn’t an actual protocol to analyze.</p><h4 name="65de" id="65de" class="graf graf--h4 graf-after--p">Reality</h4><p name="ac0c" id="ac0c" class="graf graf--p graf-after--h4">In the real world, Facebook is still running on draft 12 from a year and a half ago, with absolutely no reason to update their implementation. After all, an updated 2.0 client written to work with Facebook’s implementation is unlikely to be useful with any other provider and vice-versa. OAuth 2.0 offers little to none code re-usability.</p><p name="979b" id="979b" class="graf graf--p graf-after--p">What 2.0 offers is a <strong class="markup--strong markup--p-strong">blueprint</strong> for an authorization protocol. As defined, it is largely useless and must be profiles into a working solution — and that is the enterprise way.<strong class="markup--strong markup--p-strong"> The WS-* way</strong>. 2.0 provides a whole new frontier to sell consulting services and integration solutions.</p><p name="fc5c" id="fc5c" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">The web does not need yet another security framework.</strong> It needs simple, well-defined, and narrowly suited protocols that will lead to improved security and increased interoperability. OAuth 2.0 fails to accomplish anything meaningful over the protocol it seeks to replace.</p><h4 name="07ac" id="07ac" class="graf graf--h4 graf-after--p">To Upgrade or Not to Upgrade</h4><p name="52e8" id="52e8" class="graf graf--p graf-after--h4">Over the past few months, many asked me if they should upgrade to 2.0 or which version of the protocol I recommend they implement. I don’t have a simple answer.</p><p name="11cd" id="11cd" class="graf graf--p graf-after--p">If you are currently using 1.0 successfully, ignore 2.0. It offers no real value over 1.0 (I’m guessing your client developers have already figured out 1.0 signatures by now).</p><p name="8477" id="8477" class="graf graf--p graf-after--p">If you are new to this space, and consider yourself a security expert, use 2.0 after careful examination of its features. If you are not an expert, either use 1.0 or copy the 2.0 implementation of a provider you trust to get it right (Facebook’s API documents are a good place to start). 2.0 is better for large scale, but if you are running a major operation, you probably have some security experts on site to figure it all out for you.</p><h4 name="7a07" id="7a07" class="graf graf--h4 graf-after--p">Now What?</h4><p name="7d73" id="7d73" class="graf graf--p graf-after--h4">I’m hoping someone will take 2.0 and produce a 10 page profile that’s useful for the vast majority of web providers, ignoring the enterprise. A 2.1 that’s really 1.5. But that’s not going to happen at the IETF. That community is all about enterprise use cases and if you look at their other efforts like<a href="http://openid.net/connect/" data-href="http://openid.net/connect/" class="markup--anchor markup--p-anchor" rel="noopener" target="_blank"> OpenID Connect</a> (which too was a super simple proposal turned into almost a dozen complex specifications), <strong class="markup--strong markup--p-strong">they are not capable of simple</strong>.</p><p name="7afc" id="7afc" class="graf graf--p graf-after--p">I think the OAuth brand is in decline. This framework will live for a while, and given the lack of alternatives, it will gain widespread adoption. But we are also <strong class="markup--strong markup--p-strong">likely to see major security failures in the next couple of years</strong> and the slow but steady devaluation of the brand. It will be another hated protocol you are stuck with.</p><p name="e2ca" id="e2ca" class="graf graf--p graf-after--p">At the same time, I am expecting multiple new communities to come up with something else that is more in the spirit of 1.0 than 2.0, and where one use case is covered extremely well. OAuth 1.0 was all about small web startups looking to solve a well-defined problem they needed to solve fast. I honestly don’t know what use cases OAuth 2.0 is trying to solve any more.</p><h4 name="1710" id="1710" class="graf graf--h4 graf-after--p">Final Note</h4><p name="40d7" id="40d7" class="graf graf--p graf-after--h4">This is a sad conclusion to a once promising community. OAuth was the poster child of small, quick, and useful standards, produced outside standards bodies without all the process and legal overhead.</p><p name="acb9" id="acb9" class="graf graf--p graf-after--p">Our standards making process is broken beyond repair. This outcome is the direct result of the nature of the IETF, and the particular personalities overseeing this work. To be clear, these are not bad or incompetent individuals. On the contrary — they are all very capable, bright, and otherwise pleasant. But most of them show up to serve their corporate overlords, and it’s practically impossible for the rest of us to compete.</p><p name="25c2" id="25c2" class="graf graf--p graf-after--p">Bringing OAuth to the IETF was a huge mistake. <a href="http://hueniverse.com/2009/11/wrap-and-the-demise-of-the-oauth-community/" data-href="http://hueniverse.com/2009/11/wrap-and-the-demise-of-the-oauth-community/" class="markup--anchor markup--p-anchor" target="_blank">Not that the alternative (WRAP) would have been a better outcome</a>, but at least it would have taken <strong class="markup--strong markup--p-strong">three less years</strong> to figure that out. I stuck around as long as I could stand it, to fight for what I thought was best for the web. I had nothing personally to gain from the decisions being made. At the end, one voice in opposition can slow things down, but can’t make a difference.</p><p name="74e1" id="74e1" class="graf graf--p graf-after--p">I failed.</p><p name="c911" id="c911" class="graf graf--p graf-after--p">We failed.</p><figure name="2b75" id="2b75" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 400px; max-height: 177px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 44.3%;"></div><img class="graf-image" data-image-id="0*QX942pbCRaY7jDYU.jpg" data-width="400" data-height="177" data-external-src="http://hueniversedotcom.files.wordpress.com/2012/07/oauthdead.jpg" src="https://cdn-images-1.medium.com/max/800/0*QX942pbCRaY7jDYU.jpg"></div></figure><p name="e196" id="e196" class="graf graf--p graf-after--figure graf--trailing"><a href="http://hueniverse.com/2012/07/on-leaving-oauth/" data-href="http://hueniverse.com/2012/07/on-leaving-oauth/" class="markup--anchor markup--p-anchor" target="_blank">Some more thoughts…</a></p></div></div></section></div><footer class="u-paddingTop10"><div class="container u-maxWidth740"><div class="row"><div class="col u-size12of12"></div></div><div class="row"><div class="col u-size12of12 js-postTags"><div class="u-paddingBottom10"><ul class="tags tags--postTags tags--borderless"><li><a class="link u-baseColor--link" href="https://hueniverse.com/tagged/oauth?source=post" data-action-source="post" data-collection-slug="hueniverse">Oauth</a></li><li><a class="link u-baseColor--link" href="https://hueniverse.com/tagged/open-web?source=post" data-action-source="post" data-collection-slug="hueniverse">Open Web</a></li></ul></div></div></div><div class="row js-postActionsFooter"><div class="postActions col u-size12of12"><div class="u-floatLeft buttonSet buttonSet--withLabels"><div class="buttonSet-inner"><div class="js-actionRecommend" data-post-id="8eec45921529" data-is-icon-29px="true" data-has-recommend-list="true" data-source="post_actions_footer"><button class="button button--primary button--large button--chromeless is-touchIconFadeInPulse u-accentColor--buttonNormal button--withIcon button--withSvgIcon u-accentColor--iconLight js-actionRecommendButton" title="Recommend to share this article with your followers and let the author know you liked it" aria-label="Recommend to share this article with your followers and let the author know you liked it" data-action="sign-in-prompt" data-sign-in-action="upvote" data-requires-token="true" data-redirect="https://medium.com/_/vote/p/8eec45921529" data-action-source="post_actions_footer"><span class="button-defaultState"><span class="svgIcon svgIcon--heart svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M16.215 23.716c-.348.288-.984.826-1.376 1.158a.526.526 0 0 1-.68 0c-.36-.307-.92-.78-1.22-1.03C9.22 20.734 3 15.527 3 10.734 3 7.02 5.916 4 9.5 4c1.948 0 3.77.898 5 2.434C15.73 4.898 17.552 4 19.5 4c3.584 0 6.5 3.02 6.5 6.734 0 4.9-6.125 9.96-9.785 12.982zM19.5 5.2c-1.774 0-3.423.923-4.41 2.468a.699.699 0 0 1-.59.323.706.706 0 0 1-.59-.32c-.988-1.54-2.637-2.47-4.41-2.47-2.922 0-5.3 2.49-5.3 5.54 0 4.23 6.19 9.41 9.517 12.19.217.18.566.48.783.66l.952-.79c3.496-2.88 9.348-7.72 9.348-12.05 0-3.05-2.378-5.53-5.3-5.53z"/></svg></span></span><span class="button-activeState"><span class="svgIcon svgIcon--heartFilled svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M19.5 4c-1.948 0-3.77.898-5 2.434C13.27 4.898 11.448 4 9.5 4 5.916 4 3 7.02 3 10.734c0 4.793 6.227 10 9.95 13.11.296.25.853.723 1.212 1.03.196.166.48.166.677 0 .39-.332 1.02-.87 1.37-1.158 3.66-3.022 9.79-8.08 9.79-12.982C26 7.02 23.08 4 19.5 4z" fill-rule="evenodd"/></svg></span></span></button><button class="button button--chromeless u-baseColor--buttonNormal" data-action="show-recommends" data-action-value="8eec45921529">3</button></div></div><div class="buttonSet-inner"><button class="button button--large button--dark button--chromeless is-touchIconBlackPulse u-baseColor--buttonDark button--withIcon button--withSvgIcon" data-action="scroll-to-responses" data-action-source="post_actions_footer"><span class="svgIcon svgIcon--response svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M21.27 20.058c1.89-1.826 2.754-4.17 2.754-6.674C24.024 8.21 19.67 4 14.1 4 8.53 4 4 8.21 4 13.384c0 5.175 4.53 9.385 10.1 9.385 1.007 0 2-.14 2.95-.41.285.25.592.49.918.7 1.306.87 2.716 1.31 4.19 1.31.276-.01.494-.14.6-.36a.625.625 0 0 0-.052-.65c-.61-.84-1.042-1.71-1.282-2.58a5.417 5.417 0 0 1-.154-.75zm-3.85 1.324l-.083-.28-.388.12a9.72 9.72 0 0 1-2.85.424c-4.96 0-8.99-3.706-8.99-8.262 0-4.556 4.03-8.263 8.99-8.263 4.95 0 8.77 3.71 8.77 8.27 0 2.25-.75 4.35-2.5 5.92l-.24.21v.32c0 .07 0 .19.02.37.03.29.1.6.19.92.19.7.49 1.4.89 2.08-.93-.14-1.83-.49-2.67-1.06-.34-.22-.88-.48-1.16-.74z"/></svg></span></button><button class="button button--chromeless u-baseColor--buttonNormal" data-action="scroll-to-responses">1</button></div></div><div class="u-floatRight buttonSet buttonSet--narrow"><button class="button button--large button--dark button--chromeless is-touchIconBlackPulse u-baseColor--buttonDark button--withIcon button--withSvgIcon" title="Share on Twitter" aria-label="Share on Twitter" data-action="share-on-twitter" data-action-source="post_actions_footer"><span class="svgIcon svgIcon--twitter svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M21.967 11.8c.018 5.93-4.607 11.18-11.177 11.18-2.172 0-4.25-.62-6.047-1.76l-.268.422-.038.5.186.013.168.012c.3.02.44.032.6.046 2.06-.026 3.95-.686 5.49-1.86l1.12-.85-1.4-.048c-1.57-.055-2.92-1.08-3.36-2.51l-.48.146-.05.5c.22.03.48.05.75.08.48-.02.87-.07 1.25-.15l2.33-.49-2.32-.49c-1.68-.35-2.91-1.83-2.91-3.55 0-.05 0-.01-.01.03l-.49-.1-.25.44c.63.36 1.35.57 2.07.58l1.7.04L7.4 13c-.978-.662-1.59-1.79-1.618-3.047a4.08 4.08 0 0 1 .524-1.8l-.825.07a12.188 12.188 0 0 0 8.81 4.515l.59.033-.06-.59v-.02c-.05-.43-.06-.63-.06-.87a3.617 3.617 0 0 1 6.27-2.45l.2.21.28-.06c1.01-.22 1.94-.59 2.73-1.09l-.75-.56c-.1.36-.04.89.12 1.36.23.68.58 1.13 1.17.85l-.21-.45-.42-.27c-.52.8-1.17 1.48-1.92 2L22 11l.016.28c.013.2.014.35 0 .52v.04zm.998.038c.018-.22.017-.417 0-.66l-.498.034.284.41a8.183 8.183 0 0 0 2.2-2.267l.97-1.48-1.6.755c.17-.08.3-.02.34.03a.914.914 0 0 1-.13-.292c-.1-.297-.13-.64-.1-.766l.36-1.254-1.1.695c-.69.438-1.51.764-2.41.963l.48.15a4.574 4.574 0 0 0-3.38-1.484 4.616 4.616 0 0 0-4.61 4.613c0 .29.02.51.08.984l.01.02.5-.06.03-.5c-3.17-.18-6.1-1.7-8.08-4.15l-.48-.56-.36.64c-.39.69-.62 1.48-.65 2.28.04 1.61.81 3.04 2.06 3.88l.3-.92c-.55-.02-1.11-.17-1.6-.45l-.59-.34-.14.67c-.02.08-.02.16 0 .24-.01 2.12 1.55 4.01 3.69 4.46l.1-.49-.1-.49c-.33.07-.67.12-1.03.14-.18-.02-.43-.05-.64-.07l-.76-.09.23.73c.57 1.84 2.29 3.14 4.28 3.21l-.28-.89a8.252 8.252 0 0 1-4.85 1.66c-.12-.01-.26-.02-.56-.05l-.17-.01-.18-.01L2.53 21l1.694 1.07a12.233 12.233 0 0 0 6.58 1.917c7.156 0 12.2-5.73 12.18-12.18l-.002.04z"/></svg></span></button><button class="button button--large button--dark button--chromeless is-touchIconBlackPulse u-baseColor--buttonDark button--withIcon button--withSvgIcon" title="Share on Facebook" aria-label="Share on Facebook" data-action="share-on-facebook" data-action-source="post_actions_footer"><span class="svgIcon svgIcon--facebook svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M16.39 23.61v-5.808h1.846a.55.55 0 0 0 .546-.48l.36-2.797a.551.551 0 0 0-.547-.62H16.39V12.67c0-.67.12-.813.828-.813h1.474a.55.55 0 0 0 .55-.55V8.803a.55.55 0 0 0-.477-.545c-.436-.06-1.36-.116-2.22-.116-2.5 0-4.13 1.62-4.13 4.248v1.513H10.56a.551.551 0 0 0-.55.55v2.797c0 .304.248.55.55.55h1.855v5.76c-4.172-.96-7.215-4.7-7.215-9.1 0-5.17 4.17-9.36 9.31-9.36 5.14 0 9.31 4.19 9.31 9.36 0 4.48-3.155 8.27-7.43 9.15M14.51 4C8.76 4 4.1 8.684 4.1 14.46c0 5.162 3.75 9.523 8.778 10.32a.55.55 0 0 0 .637-.543v-6.985a.551.551 0 0 0-.55-.55H11.11v-1.697h1.855a.55.55 0 0 0 .55-.55v-2.063c0-2.02 1.136-3.148 3.03-3.148.567 0 1.156.027 1.597.06v1.453h-.924c-1.363 0-1.93.675-1.93 1.912v1.78c0 .3.247.55.55.55h2.132l-.218 1.69H15.84c-.305 0-.55.24-.55.55v7.02c0 .33.293.59.623.54 5.135-.7 9.007-5.11 9.007-10.36C24.92 8.68 20.26 4 14.51 4"/></svg></span></button></div></div></div></div><div class="js-postPromotionWrapper postPromotionWrapper" data-location-id="footer_above_post_attribution"></div><div class="container u-maxWidth740 js-postAttributionFooterContainer u-paddingTop20 u-paddingBottom20 u-marginTop10 u-borderTopLightest u-xs-paddingTop10 u-xs-paddingBottom10"><div class="row js-postFooterInfo"><div class="col u-size6of12 u-xs-size12of12"><li class="u-block u-paddingBottom18 js-cardUser"><div class="u-marginLeft20 u-floatRight"><span class="followState js-followState buttonSet-inner" data-user-id="b4e3921706ee"><button class="button button--small u-noUserSelect button--withChrome u-baseColor--buttonNormal button--withHover button--unblock js-unblockButton" data-action="sign-in-prompt" data-sign-in-action="toggle-block-user" data-requires-token="true" data-action-source="footer_card"><span class="button-label button-defaultState">Blocked</span><span class="button-label button-hoverState">Unblock</span></button><button class="button button--primary button--small u-noUserSelect button--withChrome u-accentColor--buttonNormal button--follow js-followButton" data-action="sign-in-prompt" data-sign-in-action="toggle-subscribe-user" data-requires-token="true" data-redirect="https://medium.com/_/subscribe/user/b4e3921706ee" data-action-source="footer_card_follow"><span class="button-label button-defaultState js-buttonLabel">Follow</span><span class="button-label button-activeState">Following</span></button></span></div><div class="u-tableCell "><a class="link avatar u-baseColor--link" href="https://hueniverse.com/@eranhammer?source=footer_card" title="Go to the profile of Eran Hammer" aria-label="Go to the profile of Eran Hammer" data-action-source="footer_card" data-user-id="b4e3921706ee" data-collection-slug="hueniverse" dir="auto"><img src="https://cdn-images-1.medium.com/fit/c/60/60/0*3ZLq0yvVG4WO2TBk.jpg" class="avatar-image avatar-image--small" alt="Go to the profile of Eran Hammer"></a></div><div class="u-tableCell u-verticalAlignMiddle u-breakWord u-paddingLeft15"><h3 class="u-fontSize18 u-lineHeightTighter u-marginBottom4"><a class="link link--primary u-accentColor--hoverTextNormal" href="https://hueniverse.com/@eranhammer" property="cc:attributionName" title="Go to the profile of Eran Hammer" aria-label="Go to the profile of Eran Hammer" rel="author cc:attributionUrl" data-user-id="b4e3921706ee" data-collection-slug="hueniverse" dir="auto">Eran Hammer</a></h3></div></li></div><div class="col u-size6of12 u-xs-size12of12 u-xs-marginTop30"><li class="u-block u-paddingBottom18 js-cardCollection"><div class="u-marginLeft20 u-floatRight"><button class="button button--primary button--small u-noUserSelect button--withChrome u-accentColor--buttonNormal js-relationshipButton" data-action="sign-in-prompt" data-sign-in-action="toggle-follow-collection" data-requires-token="true" data-redirect="https://medium.com/_/subscribe/collection/hueniverse" data-collection-id="ee73cfff03f"><span class="button-label js-buttonLabel">Follow</span></button></div><div class="u-tableCell "><a class="link avatar avatar--roundedRectangle u-baseColor--link" href="https://hueniverse.com?source=footer_card" title="Go to hueniverse" aria-label="Go to hueniverse" data-action-source="footer_card" data-collection-slug="hueniverse"><img src="https://cdn-images-1.medium.com/fit/c/60/60/1*FucaTWCRPOZ6XdfDCe3c4Q.png" class="avatar-image u-size60x60" alt="hueniverse"></a></div><div class="u-tableCell u-verticalAlignMiddle u-breakWord u-paddingLeft15"><h3 class="u-fontSize18 u-lineHeightTighter u-marginBottom4"><a class="link link--primary u-accentColor--hoverTextNormal" href="https://hueniverse.com?source=footer_card" rel="collection" data-action-source="footer_card" data-collection-slug="hueniverse">hueniverse</a></h3><p class="u-fontSize14 u-lineHeightBaseSans u-textColorDark u-marginBottom4">The technical musings of Eran Hammer</p><div class="buttonSet"></div></div></li></div></div></div><div class="js-postFooterPlacements"></div><div class="u-padding0 u-clearfix u-backgroundGrayLightest u-print-hide supplementalPostContent js-responsesWrapper"></div><div class="supplementalPostContent js-readNext"></div><div class="supplementalPostContent js-heroPromo"></div></footer></article></main><div class="u-marginAuto u-maxWidth1000"><div class="js-postShareWidget u-foreground u-sm-hide u-transition--fadeOut300 u-fixed"><ul><li class="u-uiTextSemibold u-textAlignCenter u-textColorNormal u-fontSize12 u-textUppercase">Share</li><li class="u-textAlignCenter"><div class="js-actionRecommend" data-post-id="8eec45921529" data-is-icon-29px="true" data-is-vertical="true" data-has-recommend-list="true" data-source="post_share_widget"><button class="button button--primary button--large button--chromeless is-touchIconFadeInPulse u-accentColor--buttonNormal button--withIcon button--withSvgIcon u-accentColor--iconLight js-actionRecommendButton" title="Recommend to share this article with your followers and let the author know you liked it" aria-label="Recommend to share this article with your followers and let the author know you liked it" data-action="sign-in-prompt" data-sign-in-action="upvote" data-requires-token="true" data-redirect="https://medium.com/_/vote/p/8eec45921529" data-action-source="post_share_widget"><span class="button-defaultState"><span class="svgIcon svgIcon--heart svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M16.215 23.716c-.348.288-.984.826-1.376 1.158a.526.526 0 0 1-.68 0c-.36-.307-.92-.78-1.22-1.03C9.22 20.734 3 15.527 3 10.734 3 7.02 5.916 4 9.5 4c1.948 0 3.77.898 5 2.434C15.73 4.898 17.552 4 19.5 4c3.584 0 6.5 3.02 6.5 6.734 0 4.9-6.125 9.96-9.785 12.982zM19.5 5.2c-1.774 0-3.423.923-4.41 2.468a.699.699 0 0 1-.59.323.706.706 0 0 1-.59-.32c-.988-1.54-2.637-2.47-4.41-2.47-2.922 0-5.3 2.49-5.3 5.54 0 4.23 6.19 9.41 9.517 12.19.217.18.566.48.783.66l.952-.79c3.496-2.88 9.348-7.72 9.348-12.05 0-3.05-2.378-5.53-5.3-5.53z"/></svg></span></span><span class="button-activeState"><span class="svgIcon svgIcon--heartFilled svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M19.5 4c-1.948 0-3.77.898-5 2.434C13.27 4.898 11.448 4 9.5 4 5.916 4 3 7.02 3 10.734c0 4.793 6.227 10 9.95 13.11.296.25.853.723 1.212 1.03.196.166.48.166.677 0 .39-.332 1.02-.87 1.37-1.158 3.66-3.022 9.79-8.08 9.79-12.982C26 7.02 23.08 4 19.5 4z" fill-rule="evenodd"/></svg></span></span></button><button class="button button--chromeless u-baseColor--buttonNormal u-block u-marginAuto u-marginTopNegative5" data-action="show-recommends" data-action-value="8eec45921529">3</button></div></li><li class="u-textAlignCenter"><button class="button button--large button--dark button--chromeless is-touchIconBlackPulse u-baseColor--buttonDark button--withIcon button--withSvgIcon" title="Share on Twitter" aria-label="Share on Twitter" data-action="share-on-twitter" data-action-source="post_share_widget"><span class="svgIcon svgIcon--twitter svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M21.967 11.8c.018 5.93-4.607 11.18-11.177 11.18-2.172 0-4.25-.62-6.047-1.76l-.268.422-.038.5.186.013.168.012c.3.02.44.032.6.046 2.06-.026 3.95-.686 5.49-1.86l1.12-.85-1.4-.048c-1.57-.055-2.92-1.08-3.36-2.51l-.48.146-.05.5c.22.03.48.05.75.08.48-.02.87-.07 1.25-.15l2.33-.49-2.32-.49c-1.68-.35-2.91-1.83-2.91-3.55 0-.05 0-.01-.01.03l-.49-.1-.25.44c.63.36 1.35.57 2.07.58l1.7.04L7.4 13c-.978-.662-1.59-1.79-1.618-3.047a4.08 4.08 0 0 1 .524-1.8l-.825.07a12.188 12.188 0 0 0 8.81 4.515l.59.033-.06-.59v-.02c-.05-.43-.06-.63-.06-.87a3.617 3.617 0 0 1 6.27-2.45l.2.21.28-.06c1.01-.22 1.94-.59 2.73-1.09l-.75-.56c-.1.36-.04.89.12 1.36.23.68.58 1.13 1.17.85l-.21-.45-.42-.27c-.52.8-1.17 1.48-1.92 2L22 11l.016.28c.013.2.014.35 0 .52v.04zm.998.038c.018-.22.017-.417 0-.66l-.498.034.284.41a8.183 8.183 0 0 0 2.2-2.267l.97-1.48-1.6.755c.17-.08.3-.02.34.03a.914.914 0 0 1-.13-.292c-.1-.297-.13-.64-.1-.766l.36-1.254-1.1.695c-.69.438-1.51.764-2.41.963l.48.15a4.574 4.574 0 0 0-3.38-1.484 4.616 4.616 0 0 0-4.61 4.613c0 .29.02.51.08.984l.01.02.5-.06.03-.5c-3.17-.18-6.1-1.7-8.08-4.15l-.48-.56-.36.64c-.39.69-.62 1.48-.65 2.28.04 1.61.81 3.04 2.06 3.88l.3-.92c-.55-.02-1.11-.17-1.6-.45l-.59-.34-.14.67c-.02.08-.02.16 0 .24-.01 2.12 1.55 4.01 3.69 4.46l.1-.49-.1-.49c-.33.07-.67.12-1.03.14-.18-.02-.43-.05-.64-.07l-.76-.09.23.73c.57 1.84 2.29 3.14 4.28 3.21l-.28-.89a8.252 8.252 0 0 1-4.85 1.66c-.12-.01-.26-.02-.56-.05l-.17-.01-.18-.01L2.53 21l1.694 1.07a12.233 12.233 0 0 0 6.58 1.917c7.156 0 12.2-5.73 12.18-12.18l-.002.04z"/></svg></span></button></li><li class="u-textAlignCenter"><button class="button button--large button--dark button--chromeless is-touchIconBlackPulse u-baseColor--buttonDark button--withIcon button--withSvgIcon" title="Share on Facebook" aria-label="Share on Facebook" data-action="share-on-facebook" data-action-source="post_share_widget"><span class="svgIcon svgIcon--facebook svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M16.39 23.61v-5.808h1.846a.55.55 0 0 0 .546-.48l.36-2.797a.551.551 0 0 0-.547-.62H16.39V12.67c0-.67.12-.813.828-.813h1.474a.55.55 0 0 0 .55-.55V8.803a.55.55 0 0 0-.477-.545c-.436-.06-1.36-.116-2.22-.116-2.5 0-4.13 1.62-4.13 4.248v1.513H10.56a.551.551 0 0 0-.55.55v2.797c0 .304.248.55.55.55h1.855v5.76c-4.172-.96-7.215-4.7-7.215-9.1 0-5.17 4.17-9.36 9.31-9.36 5.14 0 9.31 4.19 9.31 9.36 0 4.48-3.155 8.27-7.43 9.15M14.51 4C8.76 4 4.1 8.684 4.1 14.46c0 5.162 3.75 9.523 8.778 10.32a.55.55 0 0 0 .637-.543v-6.985a.551.551 0 0 0-.55-.55H11.11v-1.697h1.855a.55.55 0 0 0 .55-.55v-2.063c0-2.02 1.136-3.148 3.03-3.148.567 0 1.156.027 1.597.06v1.453h-.924c-1.363 0-1.93.675-1.93 1.912v1.78c0 .3.247.55.55.55h2.132l-.218 1.69H15.84c-.305 0-.55.24-.55.55v7.02c0 .33.293.59.623.54 5.135-.7 9.007-5.11 9.007-10.36C24.92 8.68 20.26 4 14.51 4"/></svg></span></button></li><li class="u-textAlignCenter"><button class="button button--large button--dark button--chromeless is-touchIconFadeInPulse u-baseColor--buttonDark button--withIcon button--withSvgIcon button--bookmark js-bookmarkButton" title="Bookmark this story to read later" aria-label="Bookmark this story to read later" data-action="sign-in-prompt" data-sign-in-action="add-to-bookmarks" data-requires-token="true" data-redirect="https://medium.com/_/bookmark/p/8eec45921529"><span class="button-defaultState"><span class="svgIcon svgIcon--bookmark svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M19.385 4h-9.77A2.623 2.623 0 0 0 7 6.615V23.01a1.022 1.022 0 0 0 1.595.847l5.905-4.004 5.905 4.004A1.022 1.022 0 0 0 22 23.011V6.62A2.625 2.625 0 0 0 19.385 4zM21 23l-5.91-3.955-.148-.107a.751.751 0 0 0-.884 0l-.147.107L8 23V6.615C8 5.725 8.725 5 9.615 5h9.77C20.275 5 21 5.725 21 6.615V23z" fill-rule="evenodd"/></svg></span></span><span class="button-activeState"><span class="svgIcon svgIcon--bookmarkFilled svgIcon--29px"><svg class="svgIcon-use" width="29" height="29" viewBox="0 0 29 29" ><path d="M19.385 4h-9.77A2.623 2.623 0 0 0 7 6.615V23.01a1.022 1.022 0 0 0 1.595.847l5.905-4.004 5.905 4.004A1.022 1.022 0 0 0 22 23.011V6.62A2.625 2.625 0 0 0 19.385 4z" fill-rule="evenodd"/></svg></span></span></button></li></ul></div></div><div class="u-fixed u-bottom0 u-sizeFullWidth u-backgroundWhite u-boxShadowTop u-borderBox u-paddingTop10 u-paddingBottom10 u-zIndexMetabar u-xs-paddingLeft10 u-xs-paddingRight10 js-stickyFooter"><div class="u-maxWidth700 u-marginAuto u-flexCenter"><div class="u-fontSize16 u-flex1 u-flexCenter"><div class="u-flex0 u-inlineBlock u-paddingRight20 u-xs-paddingRight10"><a class="link avatar avatar--roundedRectangle u-baseColor--link" href="https://hueniverse.com" title="Go to hueniverse" aria-label="Go to hueniverse" data-collection-slug="hueniverse"><img src="https://cdn-images-1.medium.com/fit/c/40/40/1*FucaTWCRPOZ6XdfDCe3c4Q.png" class="avatar-image avatar-image--smaller" alt="hueniverse"></a></div><div class="u-flex1 u-inlineBlock"><div class="u-xs-hide">Never miss a story from<strong> hueniverse</strong>, when you sign up for Medium. <a class="link link--accent u-accentColor--textNormal u-accentColor--textDarken u-baseColor--link" href="https://medium.com/@Medium/personalize-your-medium-experience-with-users-publications-tags-26a41ab1ee0c#.hx4zuv3mg" data-action-source="sticky_footer">Learn more</a></div><div class="u-xs-show">Never miss a story from<strong> hueniverse</strong></div></div></div><div class="u-marginLeft50 u-xs-marginAuto"><button class="button button--primary button--dark is-active u-noUserSelect button--withChrome u-accentColor--buttonDark u-uiTextSemibold u-textUppercase u-fontSize12 button--followCollection js-followCollectionButton" data-action="sign-in-prompt" data-sign-in-action="toggle-subscribe-collection" data-requires-token="true" data-redirect="https://medium.com/_/subscribe/collection/hueniverse" data-action-source="sticky_footer_collection_follow"><span class="button-label button-defaultState js-buttonLabel">Get updates</span><span class="button-label button-activeState">Get updates</span></button></div></div></div><style class="js-collectionStyle">
.u-accentColor--borderLight {border-color: #02B875 !important;}
.u-accentColor--borderNormal {border-color: #02B875 !important;}
.u-accentColor--borderDark {border-color: #1C9963 !important;}
.u-accentColor--iconLight .svgIcon,.u-accentColor--iconLight.svgIcon {fill: #02B875 !important;}
.u-accentColor--iconNormal .svgIcon,.u-accentColor--iconNormal.svgIcon {fill: #02B875 !important;}
.u-accentColor--iconDark .svgIcon,.u-accentColor--iconDark.svgIcon {fill: #1C9963 !important;}
.u-accentColor--textNormal {color: #1C9963 !important;}
.u-accentColor--hoverTextNormal:hover {color: #1C9963 !important;}
.u-accentColor--textNormal.u-accentColor--textDarken:hover {color: #1C9963 !important;}
.u-accentColor--textDark {color: #1C9963 !important;}
.u-accentColor--backgroundLight {background-color: #02B875 !important;}
.u-accentColor--backgroundNormal {background-color: #02B875 !important;}
.u-accentColor--backgroundDark {background-color: #1C9963 !important;}
.u-accentColor--buttonDark {border-color: #1C9963 !important; color: #1C9963 !important;}
.u-accentColor--buttonDark:hover {border-color: #1C9963 !important;}
.u-accentColor--buttonDark .icon:before,.u-accentColor--buttonDark .svgIcon{color: #1C9963 !important; fill: #1C9963 !important;}
.u-accentColor--buttonNormal {border-color: #02B875 !important; color: #1C9963 !important;}
.u-accentColor--buttonNormal:hover {border-color: #1C9963 !important;}
.u-accentColor--buttonNormal .icon:before,.u-accentColor--buttonNormal .svgIcon{color: #02B875 !important; fill: #02B875 !important;}
.u-accentColor--buttonNormal.button--filled .icon:before,.u-accentColor--buttonNormal.button--filled .svgIcon{color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-accentColor--buttonDark.button--filled,.u-accentColor--buttonDark.button--withChrome.is-active,.u-accentColor--fillWhenActive.is-active {background-color: #1C9963 !important; border-color: #1C9963 !important; color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-accentColor--buttonNormal.button--filled,.u-accentColor--buttonNormal.button--withChrome.is-active {background-color: #02B875 !important; border-color: #02B875 !important; color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.postArticle.is-withAccentColors .markup--user,.postArticle.is-withAccentColors .markup--query {color: #1C9963 !important;}
.u-accentColor--highlightFaint {background-color: rgba(233, 253, 240, 1) !important;}
.u-accentColor--highlightStrong.is-active .svgIcon {fill: rgba(125, 255, 179, 1) !important;}
.postArticle.is-withAccentColors .markup--quote.is-other {background-color: rgba(233, 253, 240, 1) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .markup--quote.is-other {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(233, 253, 240, 1), rgba(233, 253, 240, 1));}
.postArticle.is-withAccentColors .markup--quote.is-me {background-color: rgba(173, 255, 207, 1) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .markup--quote.is-me {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(173, 255, 207, 1), rgba(173, 255, 207, 1));}
.postArticle.is-withAccentColors .markup--quote.is-targeted {background-color: rgba(125, 255, 179, 1) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .markup--quote.is-targeted {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(125, 255, 179, 1), rgba(125, 255, 179, 1));}
.postArticle.is-withAccentColors .markup--quote.is-selected {background-color: rgba(125, 255, 179, 1) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .markup--quote.is-selected {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(125, 255, 179, 1), rgba(125, 255, 179, 1));}
.postArticle.is-withAccentColors .markup--highlight {background-color: rgba(125, 255, 179, 1) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .markup--highlight {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(125, 255, 179, 1), rgba(125, 255, 179, 1));}</style><style class="js-collectionStyleConstant">.u-imageBgColor {background-color: rgba(0, 0, 0, 0.24705882352941178);}
.u-imageSpectrum .u-baseColor--borderLight {border-color: rgba(255, 255, 255, 0.6980392156862745) !important;}
.u-imageSpectrum .u-baseColor--borderNormal {border-color: rgba(255, 255, 255, 0.8980392156862745) !important;}
.u-imageSpectrum .u-baseColor--borderDark {border-color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--iconLight .svgIcon,.u-imageSpectrum .u-baseColor--iconLight.svgIcon {fill: rgba(255, 255, 255, 0.8) !important;}
.u-imageSpectrum .u-baseColor--iconNormal .svgIcon,.u-imageSpectrum .u-baseColor--iconNormal.svgIcon {fill: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--iconDark .svgIcon,.u-imageSpectrum .u-baseColor--iconDark.svgIcon {fill: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--textNormal {color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--textNormal.u-baseColor--textDarken:hover {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--textDark {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--backgroundLight {background-color: rgba(255, 255, 255, 0.8980392156862745) !important;}
.u-imageSpectrum .u-baseColor--backgroundNormal {background-color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--backgroundDark {background-color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--buttonLight {border-color: rgba(255, 255, 255, 0.6980392156862745) !important; color: rgba(255, 255, 255, 0.8) !important;}
.u-imageSpectrum .u-baseColor--buttonLight:hover {border-color: rgba(255, 255, 255, 0.6980392156862745) !important;}
.u-imageSpectrum .u-baseColor--buttonLight .icon:before,.u-imageSpectrum .u-baseColor--buttonLight .svgIcon {color: rgba(255, 255, 255, 0.8) !important; fill: rgba(255, 255, 255, 0.8) !important;}
.u-imageSpectrum .u-baseColor--buttonDark {border-color: rgba(255, 255, 255, 0.9490196078431372) !important; color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--buttonDark:hover {border-color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--buttonDark .icon:before,.u-imageSpectrum .u-baseColor--buttonDark .svgIcon {color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--buttonNormal {border-color: rgba(255, 255, 255, 0.8980392156862745) !important; color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--buttonNormal:hover {border-color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--buttonNormal .icon:before,.u-imageSpectrum .u-baseColor--buttonNormal .svgIcon {color: rgba(255, 255, 255, 0.9490196078431372) !important; fill: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--buttonDark.button--filled,.u-imageSpectrum .u-baseColor--buttonDark.button--withChrome.is-active {background-color: rgba(255, 255, 255, 1) !important; border-color: rgba(255, 255, 255, 1) !important; color: rgba(0, 0, 0, 0.24705882352941178) !important; fill: rgba(0, 0, 0, 0.24705882352941178) !important;}
.u-imageSpectrum .u-baseColor--buttonNormal.button--filled,.u-imageSpectrum .u-baseColor--buttonNormal.button--withChrome.is-active {background-color: rgba(255, 255, 255, 0.9490196078431372) !important; border-color: rgba(255, 255, 255, 0.9490196078431372) !important; color: rgba(0, 0, 0, 0.24705882352941178) !important; fill: rgba(0, 0, 0, 0.24705882352941178) !important;}
.u-imageSpectrum .u-baseColor--link {color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-baseColor--link.link--darkenOnHover:hover {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--link.link--darken:hover,.u-imageSpectrum .u-baseColor--link.link--darken:focus,.u-imageSpectrum .u-baseColor--link.link--darken:active {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--link.link--dark {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--link.link--dark.link--darken:hover,.u-imageSpectrum .u-baseColor--link.link--dark.link--darken:focus,.u-imageSpectrum .u-baseColor--link.link--dark.link--darken:active {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--link.link--darker {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-baseColor--placeholderNormal ::-webkit-input-placeholder {color: rgba(255, 255, 255, 0.8);}
.u-imageSpectrum .u-baseColor--placeholderNormal ::-moz-placeholder {color: rgba(255, 255, 255, 0.8);}
.u-imageSpectrum .u-baseColor--placeholderNormal :-ms-input-placeholder {color: rgba(255, 255, 255, 0.8);}
.u-imageSpectrum .svgIcon--logoNew path:nth-child(1) {stroke: none !important; fill: rgba(255, 255, 255, 0.4) !important;}
.u-imageSpectrum .svgIcon--logoNew path:nth-child(2) {stroke: none !important; fill: rgba(255, 255, 255, 0.4980392156862745) !important;}
.u-imageSpectrum .svgIcon--logoNew path:nth-child(3) {stroke: none !important; fill: rgba(255, 255, 255, 0.6980392156862745) !important;}
.u-imageSpectrum .svgIcon--logoNew path:nth-child(4) {stroke: none !important; fill: rgba(255, 255, 255, 0.8980392156862745) !important;}
.u-imageSpectrum .u-accentColor--borderLight {border-color: rgba(255, 255, 255, 0.6980392156862745) !important;}
.u-imageSpectrum .u-accentColor--borderNormal {border-color: rgba(255, 255, 255, 0.8980392156862745) !important;}
.u-imageSpectrum .u-accentColor--borderDark {border-color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--iconLight .svgIcon,.u-imageSpectrum .u-accentColor--iconLight.svgIcon {fill: rgba(255, 255, 255, 0.8) !important;}
.u-imageSpectrum .u-accentColor--iconNormal .svgIcon,.u-imageSpectrum .u-accentColor--iconNormal.svgIcon {fill: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--iconDark .svgIcon,.u-imageSpectrum .u-accentColor--iconDark.svgIcon {fill: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--textNormal {color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--hoverTextNormal:hover {color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--textNormal.u-accentColor--textDarken:hover {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--textDark {color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--backgroundLight {background-color: rgba(255, 255, 255, 0.8980392156862745) !important;}
.u-imageSpectrum .u-accentColor--backgroundNormal {background-color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--backgroundDark {background-color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--buttonDark {border-color: rgba(255, 255, 255, 0.9490196078431372) !important; color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--buttonDark:hover {border-color: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--buttonDark .icon:before,.u-imageSpectrum .u-accentColor--buttonDark .svgIcon{color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-imageSpectrum .u-accentColor--buttonNormal {border-color: rgba(255, 255, 255, 0.8980392156862745) !important; color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--buttonNormal:hover {border-color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--buttonNormal .icon:before,.u-imageSpectrum .u-accentColor--buttonNormal .svgIcon{color: rgba(255, 255, 255, 0.9490196078431372) !important; fill: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--buttonNormal.button--filled .icon:before,.u-imageSpectrum .u-accentColor--buttonNormal.button--filled .svgIcon{color: rgba(0, 0, 0, 0.24705882352941178) !important; fill: rgba(0, 0, 0, 0.24705882352941178) !important;}
.u-imageSpectrum .u-accentColor--buttonDark.button--filled,.u-imageSpectrum .u-accentColor--buttonDark.button--withChrome.is-active,.u-imageSpectrum .u-accentColor--fillWhenActive.is-active {background-color: rgba(255, 255, 255, 1) !important; border-color: rgba(255, 255, 255, 1) !important; color: rgba(0, 0, 0, 0.24705882352941178) !important; fill: rgba(0, 0, 0, 0.24705882352941178) !important;}
.u-imageSpectrum .u-accentColor--buttonNormal.button--filled,.u-imageSpectrum .u-accentColor--buttonNormal.button--withChrome.is-active {background-color: rgba(255, 255, 255, 0.9490196078431372) !important; border-color: rgba(255, 255, 255, 0.9490196078431372) !important; color: rgba(0, 0, 0, 0.24705882352941178) !important; fill: rgba(0, 0, 0, 0.24705882352941178) !important;}
.u-imageSpectrum .postArticle.is-withAccentColors .markup--user,.u-imageSpectrum .postArticle.is-withAccentColors .markup--query {color: rgba(255, 255, 255, 0.9490196078431372) !important;}
.u-imageSpectrum .u-accentColor--highlightFaint {background-color: rgba(255, 255, 255, 0.2) !important;}
.u-imageSpectrum .u-accentColor--highlightStrong.is-active .svgIcon {fill: rgba(255, 255, 255, 0.6) !important;}
.postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-other {background-color: rgba(255, 255, 255, 0.2) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-other {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2));}
.postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-me {background-color: rgba(255, 255, 255, 0.4) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-me {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.4));}
.postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-targeted {background-color: rgba(255, 255, 255, 0.6) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-targeted {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.6));}
.postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-selected {background-color: rgba(255, 255, 255, 0.6) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .u-imageSpectrum .markup--quote.is-selected {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.6));}
.postArticle.is-withAccentColors .u-imageSpectrum .markup--highlight {background-color: rgba(255, 255, 255, 0.6) !important;}
body.is-withMagicUnderlines .postArticle.is-withAccentColors .u-imageSpectrum .markup--highlight {background-color: transparent !important; background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.6));}.u-resetSpectrum .u-tintBgColor {background-color: rgba(255, 255, 255, 1) !important;}.u-resetSpectrum .u-tintBgColor .u-fadeLeft:before {background-image: linear-gradient(to right, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%) !important;}.u-resetSpectrum .u-tintBgColor .u-fadeRight:after {background-image: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%) !important;}
.u-resetSpectrum .u-baseColor--borderLight {border-color: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .u-baseColor--borderNormal {border-color: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-baseColor--borderDark {border-color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--iconLight .svgIcon,.u-resetSpectrum .u-baseColor--iconLight.svgIcon {fill: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .u-baseColor--iconNormal .svgIcon,.u-resetSpectrum .u-baseColor--iconNormal.svgIcon {fill: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-baseColor--iconDark .svgIcon,.u-resetSpectrum .u-baseColor--iconDark.svgIcon {fill: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--textNormal {color: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-baseColor--textNormal.u-baseColor--textDarken:hover {color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--textDark {color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--backgroundLight {background-color: rgba(0, 0, 0, 0.09803921568627451) !important;}
.u-resetSpectrum .u-baseColor--backgroundNormal {background-color: rgba(0, 0, 0, 0.2) !important;}
.u-resetSpectrum .u-baseColor--backgroundDark {background-color: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .u-baseColor--buttonLight {border-color: rgba(0, 0, 0, 0.2980392156862745) !important; color: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .u-baseColor--buttonLight:hover {border-color: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .u-baseColor--buttonLight .icon:before,.u-resetSpectrum .u-baseColor--buttonLight .svgIcon {color: rgba(0, 0, 0, 0.2980392156862745) !important; fill: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .u-baseColor--buttonDark {border-color: rgba(0, 0, 0, 0.6) !important; color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--buttonDark:hover {border-color: rgba(0, 0, 0, 0.8) !important;}
.u-resetSpectrum .u-baseColor--buttonDark .icon:before,.u-resetSpectrum .u-baseColor--buttonDark .svgIcon {color: rgba(0, 0, 0, 0.6) !important; fill: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--buttonNormal {border-color: rgba(0, 0, 0, 0.4980392156862745) !important; color: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-baseColor--buttonNormal:hover {border-color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--buttonNormal .icon:before,.u-resetSpectrum .u-baseColor--buttonNormal .svgIcon {color: rgba(0, 0, 0, 0.4980392156862745) !important; fill: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-baseColor--buttonDark.button--filled,.u-resetSpectrum .u-baseColor--buttonDark.button--withChrome.is-active {background-color: rgba(0, 0, 0, 0.2980392156862745) !important; border-color: rgba(0, 0, 0, 0.2980392156862745) !important; color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-resetSpectrum .u-baseColor--buttonNormal.button--filled,.u-resetSpectrum .u-baseColor--buttonNormal.button--withChrome.is-active {background-color: rgba(0, 0, 0, 0.2) !important; border-color: rgba(0, 0, 0, 0.2) !important; color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-resetSpectrum .u-baseColor--link {color: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-baseColor--link.link--darkenOnHover:hover {color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--link.link--darken:hover,.u-resetSpectrum .u-baseColor--link.link--darken:focus,.u-resetSpectrum .u-baseColor--link.link--darken:active {color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--link.link--dark {color: rgba(0, 0, 0, 0.6) !important;}
.u-resetSpectrum .u-baseColor--link.link--dark.link--darken:hover,.u-resetSpectrum .u-baseColor--link.link--dark.link--darken:focus,.u-resetSpectrum .u-baseColor--link.link--dark.link--darken:active {color: rgba(0, 0, 0, 0.8) !important;}
.u-resetSpectrum .u-baseColor--link.link--darker {color: rgba(0, 0, 0, 0.8) !important;}
.u-resetSpectrum .u-baseColor--placeholderNormal ::-webkit-input-placeholder {color: rgba(0, 0, 0, 0.2980392156862745);}
.u-resetSpectrum .u-baseColor--placeholderNormal ::-moz-placeholder {color: rgba(0, 0, 0, 0.2980392156862745);}
.u-resetSpectrum .u-baseColor--placeholderNormal :-ms-input-placeholder {color: rgba(0, 0, 0, 0.2980392156862745);}
.u-resetSpectrum .svgIcon--logoNew path:nth-child(1) {stroke: none !important; fill: rgba(0, 0, 0, 0.2) !important;}
.u-resetSpectrum .svgIcon--logoNew path:nth-child(2) {stroke: none !important; fill: rgba(0, 0, 0, 0.2980392156862745) !important;}
.u-resetSpectrum .svgIcon--logoNew path:nth-child(3) {stroke: none !important; fill: rgba(0, 0, 0, 0.4) !important;}
.u-resetSpectrum .svgIcon--logoNew path:nth-child(4) {stroke: none !important; fill: rgba(0, 0, 0, 0.4980392156862745) !important;}
.u-resetSpectrum .u-accentColor--borderLight {border-color: rgba(2, 184, 117, 1) !important;}
.u-resetSpectrum .u-accentColor--borderNormal {border-color: rgba(2, 184, 117, 1) !important;}
.u-resetSpectrum .u-accentColor--borderDark {border-color: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--iconLight .svgIcon,.u-resetSpectrum .u-accentColor--iconLight.svgIcon {fill: rgba(2, 184, 117, 1) !important;}
.u-resetSpectrum .u-accentColor--iconNormal .svgIcon,.u-resetSpectrum .u-accentColor--iconNormal.svgIcon {fill: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--iconDark .svgIcon,.u-resetSpectrum .u-accentColor--iconDark.svgIcon {fill: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--textNormal {color: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--hoverTextNormal:hover {color: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--textNormal.u-accentColor--textDarken:hover {color: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--textDark {color: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--backgroundLight {background-color: rgba(2, 184, 117, 1) !important;}
.u-resetSpectrum .u-accentColor--backgroundNormal {background-color: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--backgroundDark {background-color: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonDark {border-color: rgba(0, 171, 107, 1) !important; color: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonDark:hover {border-color: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonDark .icon:before,.u-resetSpectrum .u-accentColor--buttonDark .svgIcon{color: rgba(28, 153, 99, 1) !important; fill: rgba(28, 153, 99, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonNormal {border-color: rgba(2, 184, 117, 1) !important; color: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonNormal:hover {border-color: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonNormal .icon:before,.u-resetSpectrum .u-accentColor--buttonNormal .svgIcon{color: rgba(0, 171, 107, 1) !important; fill: rgba(0, 171, 107, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonNormal.button--filled .icon:before,.u-resetSpectrum .u-accentColor--buttonNormal.button--filled .svgIcon{color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonDark.button--filled,.u-resetSpectrum .u-accentColor--buttonDark.button--withChrome.is-active,.u-resetSpectrum .u-accentColor--fillWhenActive.is-active {background-color: rgba(28, 153, 99, 1) !important; border-color: rgba(28, 153, 99, 1) !important; color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-resetSpectrum .u-accentColor--buttonNormal.button--filled,.u-resetSpectrum .u-accentColor--buttonNormal.button--withChrome.is-active {background-color: rgba(0, 171, 107, 1) !important; border-color: rgba(0, 171, 107, 1) !important; color: rgba(255, 255, 255, 1) !important; fill: rgba(255, 255, 255, 1) !important;}
.u-resetSpectrum .postArticle.is-withAccentColors .markup--user,.u-resetSpectrum .postArticle.is-withAccentColors .markup--query {color: rgba(0, 171, 107, 1) !important;}</style></div></div></div><div class="loadingBar"></div><script>// <![CDATA[
window["obvInit"] = function (opt_embedded) {window["obvInit"]["embedded"] = opt_embedded; window["obvInit"]["ready"] = true;}
// ]]></script><script>// <![CDATA[
var GLOBALS = {"audioUrl":"https://d1fcbxp97j4nb2.cloudfront.net","baseUrl":"https://hueniverse.com","buildLabel":"28895-2c69272","currentUser":{"userId":"lo_b364a39284f5","isVerified":false,"subscriberEmail":""},"currentUserHasUnverifiedEmail":false,"isAuthenticated":false,"isCurrentUserVerified":false,"mediumTwitterScreenName":"medium","miroUrl":"https://cdn-images-1.medium.com","moduleUrls":{"base":"https://cdn-static-1.medium.com/_/fp/gen-js/main-base.bundle.yxPeZhVYnwLguydCcxBccA.js","notes":"https://cdn-static-1.medium.com/_/fp/gen-js/main-notes.bundle.cnLfanAxZtS9NjQ_CpLQJQ.js","posters":"https://cdn-static-1.medium.com/_/fp/gen-js/main-posters.bundle.Msytn-e6-1x84ITwGuFtGQ.js","common-async":"https://cdn-static-1.medium.com/_/fp/gen-js/main-common-async.bundle.v5vaLedvqMl-3yOO4L938w.js","stats":"https://cdn-static-1.medium.com/_/fp/gen-js/main-stats.bundle.S2mXTGyY9ydaasNRIJxyFA.js","home-screens":"https://cdn-static-1.medium.com/_/fp/gen-js/main-home-screens.bundle.2DgeIGX6Tz7I-vg3MOG6ng.js","misc-screens":"https://cdn-static-1.medium.com/_/fp/gen-js/main-misc-screens.bundle.2EqTGFrWPuQC3-V9kred8A.js"},"previewConfig":{"weightThreshold":1,"weightImageParagraph":0.51,"weightIframeParagraph":0.8,"weightTextParagraph":0.08,"weightEmptyParagraph":0,"weightP":0.003,"weightH":0.005,"weightBq":0.003,"minPTextLength":60,"truncateBoundaryChars":20,"detectTitle":true,"detectTitleLevThreshold":0.15},"productName":"Medium","supportsEdit":false,"termsUrl":"//medium.com/policy/9db0094a1e0f","textshotHost":"textshot.medium.com","transactionId":"1494365808166:1fd9e3737d29","useragent":{"browser":"curl","family":"","os":"","version":7.54,"supportsDesktopEdit":false,"supportsInteract":false,"supportsView":true,"isMobile":false,"isTablet":false,"isNative":false,"supportsFileAPI":false,"isTier1":false,"clientVersion":"","unknownParagraphsBad":false,"clientChannel":"","supportsRealScrollEvents":false,"supportsVhUnits":false,"ruinsViewportSections":false,"supportsHtml5Video":false,"supportsMagicUnderlines":false,"isWebView":false,"isFacebookWebView":false,"supportsProgressiveMedia":false,"supportsPromotedPosts":true,"isBot":false,"isNativeIphone":false,"supportsCssVariables":false,"supportsScrollableMetabar":false},"variants":{"allow_access":true,"allow_signup":true,"allow_test_auth":"disallow","signin_services":"twitter,facebook,google,email,google-fastidv","signup_services":"twitter,facebook,google,email,google-fastidv","android_rating_prompt_recommend_threshold":5,"google_sign_in_android":true,"enable_onboarding":true,"ios_custom_miro_url":"https://cdn-images-1.medium.com","reengagement_notification_duration":3,"enable_adsnative_integration":true,"browsable_stream_config_bucket":"curated-topics","ios_small_post_preview_truncation_length":5.5,"ios_large_post_preview_truncation_length":5.5,"disable_ios_catalog_badging":true,"enable_series_creation":true,"enable_your_series_pages":true,"enable_productionized_series":true,"enable_dedicated_series_tab_api_ios":true,"enable_clap_milestone_notifications":true,"enable_series_stats_page":true,"enable_prepublish_share_settings":true,"enable_direct_auth_connect":true,"enable_post_import":true,"enable_sponsored_post_labelling":true,"enable_logged_in_follow_on_collection_post":true,"promoted_story_placement_locations":"POST_PAGE_FOOTER","show_topics":true,"enable_search_collection_by_tag_recency_filter":true,"search_collection_by_tag_filter_min_votes":10,"enable_sms_app_promo":true,"enable_export_members":true,"enable_series_card_background_creation":true,"enable_loyal_writers_onboarding":true,"enable_onboarding_hybrid_users":true,"enable_ios_onboarding_notifications":true,"enable_new_stats_source":true,"can_see_subscription_branding":true,"enable_subscriptions_landing_page":true,"enable_partner_program_landing_page":true,"enable_hide_broken_links":true,"enable_pay_for_custom_domain":true,"enable_promos_from_dynamo":true,"enable_promos_in_placement":true,"double_write_post_from_followed_tag_items":true,"enable_series_promo_in_email":true,"enable_sms":true,"enable_series_in_user_profiles":true,"enable_new_logged_out_bento_operation":true,"enable_featured_image_selector":true,"num_of_tags_suggested_on_publish":3,"enable_postview_stats_new_source":true},"xsrfToken":"","iosAppId":"828256236","supportEmail":"yourfriends@medium.com","teamName":"Team Medium","fp":{"/icons/favicon.svg":"https://cdn-static-1.medium.com/_/fp/icons/favicon.KjTfUJo7yJH_fCoUzzH3cg.svg","/icons/favicon-dev-editor.ico":"https://cdn-static-1.medium.com/_/fp/icons/favicon-dev-editor.YKKRxBO8EMvIqhyCwIiJeQ.ico","/icons/favicon-hatch-editor.ico":"https://cdn-static-1.medium.com/_/fp/icons/favicon-hatch-editor.BuEyHIqlyh2s_XEk4Rl32Q.ico","/icons/favicon-medium-editor.ico":"https://cdn-static-1.medium.com/_/fp/icons/favicon-medium-editor.PiakrZWB7Yb80quUVQWM6g.ico"},"authBaseUrl":"https://medium.com","imageUploadSizeMb":25,"isAuthDomainRequest":false,"domainCollectionSlug":"hueniverse","algoliaApiEndpoint":"https://MQ57UUUQZ2-dsn.algolia.net","algoliaAppId":"MQ57UUUQZ2","algoliaSearchOnlyApiKey":"394474ced050e3911ae2249ecc774921","iosAppStoreUrl":"https://itunes.apple.com/app/medium-everyones-stories/id828256236?pt=698524&mt=8","iosAppLinkBaseUrl":"medium:","algoliaIndexPrefix":"medium_","androidPlayStoreUrl":"https://play.google.com/store/apps/details?id=com.medium.reader","googleClientId":"216296035834-k1k6qe060s2tp2a2jam4ljdcms00sttg.apps.googleusercontent.com","androidPackage":"com.medium.reader","androidPlayStoreMarketScheme":"market://details?id=com.medium.reader","googleAuthUri":"https://accounts.google.com/o/oauth2/auth","androidScheme":"medium","layoutData":{"useDynamicScripts":false,"googleAnalyticsTrackingCode":"UA-24232453-2","jsShivUrl":"https://cdn-static-1.medium.com/_/fp/js/shiv.RI2ePTZ5gFmMgLzG5bEVAA.js","useDynamicCss":false,"faviconUrl":"https://cdn-static-1.medium.com/_/fp/icons/favicon-medium.TAS6uQ-Y7kcKgi0xjcYHXw.ico","faviconImageId":"1*W0nmth_X8nFKjn6BZ388UQ.png","fontSets":[{"id":1,"url":"https://cdn-static-1.medium.com/_/fp/css/fonts-base.by5Oi_VbnwEIvhnWIsuUjA.css"},{"id":4,"url":"https://cdn-static-1.medium.com/_/fp/css/fonts-lazy-base.g08Jj5TZPAiuPWj5YNUsSg.css"},{"id":6,"url":"https://cdn-static-1.medium.com/_/fp/css/fonts-latin-base.141WxxXgxGxNcfeza73H7Q.css"},{"id":7,"url":"https://cdn-static-1.medium.com/_/fp/css/fonts-lazy-latin-base.jMU532QDmysQMOINr-cr2A.css"}],"editorFaviconUrl":"https://cdn-static-1.medium.com/_/fp/icons/favicon-medium-editor.PiakrZWB7Yb80quUVQWM6g.ico"},"authBaseUrlRev":"moc.muidem//:sptth","isDnt":false,"stripePublishableKey":"pk_live_7FReX44VnNIInZwrIIx6ghjl","archiveUploadSizeMb":100,"paymentData":{"currencies":{"1":{"label":"US Dollar","external":"usd"}},"countries":{"1":{"label":"United States of America","external":"US"}},"accountTypes":{"1":{"label":"Individual","external":"individual"},"2":{"label":"Company","external":"company"}}},"previewConfig2":{"weightThreshold":1,"weightImageParagraph":0.05,"raiseImage":true,"enforceHeaderHierarchy":true,"isImageInsetRight":true},"isAmp":false,"iosScheme":"medium","isSwBoot":false,"lightstep":{"accessToken":"ce5be895bef60919541332990ac9fef2","carrier":"{\"ot-tracer-spanid\":\"5b8c4fe872774bce\",\"ot-tracer-traceid\":\"1773b2e94aa0095a\",\"ot-tracer-sampled\":\"true\"}","host":"collector-medium.lightstep.com"},"facebook":{"key":"542599432471018","secret":"c14df7146e9052a1131f3c900c1f0644","token":"542599432471018|1JqjIwxSfY9jOt_KwjWEl1R7T6I","namespace":"medium-com","scope":{"default":["public_profile","email","user_friends"],"connect":["public_profile","email","user_friends"],"login":["public_profile","email","user_friends"],"share":["public_profile","email","user_friends","publish_actions"]},"smartPublishWhitelistedPublications":["bcc38c8f6edf","f3726e2a5878","828a270689e","81c7d351c056","f30e42fd7ff8","8bf1d7d3081b","d16afa0ae7c","d8f3f6ad9c31","e74de0cedea9","15f753907972","c8c6a6b01ebd","3412b9729488","2ce4bbcf83bb","544c7006046e","7bfcdbc6b30a","a268fd916824","458a773bccd2"],"instantArticles":{"published":true,"developmentMode":false}},"mailingListArchiveUploadSizeMb":2,"availableMembershipPlans":[],"editorsPicksTopicId":"3985d2a191c5","popularOnMediumTopicId":"9d34e48ecf94","memberContentTopicId":"13d7efd82fb2","isDoNotAuth":false,"goldfinchUrl":"https://goldfinch.medium.com","buggleUrl":"https://buggle.medium.com","buggleAudioUrl":"https://s3.amazonaws.com/medium-assets-audio"}
// ]]></script><script charset="UTF-8" src="https://cdn-static-1.medium.com/_/fp/gen-js/main-base.bundle.yxPeZhVYnwLguydCcxBccA.js" async></script><script>// <![CDATA[
window["obvInit"]({"value":{"id":"8eec45921529","versionId":"988fa2895b26","creatorId":"b4e3921706ee","creator":{"userId":"b4e3921706ee","name":"Eran Hammer","username":"eranhammer","createdAt":1345095435598,"lastPostCreatedAt":1490305704020,"imageId":"0*3ZLq0yvVG4WO2TBk.jpg","backgroundImageId":"","bio":"","twitterScreenName":"eranhammer","socialStats":{"userId":"b4e3921706ee","usersFollowedCount":46,"usersFollowedByCount":3636,"type":"SocialStats"},"social":{"userId":"lo_b364a39284f5","targetUserId":"b4e3921706ee","type":"Social"},"facebookAccountId":"","allowNotes":1,"type":"User"},"homeCollection":{"id":"ee73cfff03f","name":"hueniverse","slug":"hueniverse","tags":[],"creatorId":"b4e3921706ee","description":"The technical musings of Eran Hammer","shortDescription":"The technical musings of Eran Hammer","image":{"imageId":"1*FucaTWCRPOZ6XdfDCe3c4Q.png","filter":"","backgroundSize":"","originalWidth":371,"originalHeight":371,"strategy":"resample","height":0,"width":0},"metadata":{"followerCount":28,"activeAt":1490305770641},"virtuals":{"permissions":{"canPublish":false,"canPublishAll":false,"canRepublish":false,"canRemove":false,"canManageAll":false,"canSubmit":false,"canEditPosts":false,"canAddWriters":false,"canViewStats":false,"canSendNewsletter":false,"canViewLockedPosts":false,"canViewCloaked":false,"canEditOwnPosts":false,"canBeAssignedAuthor":false},"isSubscribed":false,"isNewsletterSubscribed":false,"memberOfMembershipPlanId":""},"logo":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"twitterUsername":"eranhammer","publicEmail":"eran@hammer.io","domain":"hueniverse.com","sections":[{"type":2,"collectionHeaderMetadata":{"title":"hueniverse","description":"","backgroundImage":{},"logoImage":{},"alignment":2,"layout":6}},{"type":1,"postListMetadata":{"source":1,"layout":6,"number":10,"postIds":[]}}],"favicon":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"colorPalette":{"defaultBackgroundSpectrum":{"colorPoints":[{"color":"#FF02B875","point":0},{"color":"#FF00AB6B","point":0.1},{"color":"#FF1C9963","point":0.2},{"color":"#FF092E20","point":1}],"backgroundColor":"#FFFFFFFF"},"highlightSpectrum":{"colorPoints":[{"color":"#FFFFFFFF","point":0},{"color":"#FFE9FDF0","point":0.1},{"color":"#FFE2FAEE","point":0.2},{"color":"#FFADFFCF","point":0.6},{"color":"#FF7DFFB3","point":1}],"backgroundColor":"#FFFFFFFF"}},"navItems":[],"colorBehavior":1,"instantArticlesState":0,"acceleratedMobilePagesState":0,"ampLogo":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"header":{"title":"hueniverse","description":"","backgroundImage":{},"logoImage":{},"alignment":2,"layout":6},"paidForDomainAt":1490229509426,"type":"Collection"},"homeCollectionId":"ee73cfff03f","title":"OAuth 2.0 and the Road to Hell","detectedLanguage":"en","latestVersion":"988fa2895b26","latestPublishedVersion":"988fa2895b26","hasUnpublishedEdits":false,"latestRev":2,"createdAt":1490229180753,"updatedAt":1493027637587,"acceptedAt":0,"firstPublishedAt":1343288243000,"latestPublishedAt":1490229349984,"vote":false,"experimentalCss":"","displayAuthor":"","content":{"bodyModel":{"paragraphs":[{"name":"38e1","type":3,"text":"OAuth 2.0 and the Road to Hell","markups":[]},{"name":"3792","type":1,"text":"Update: three years later I wrote something new… introducing Oz.","markups":[{"type":1,"start":0,"end":64}]},{"name":"95f4","type":1,"text":"They say the road to hell is paved with good intentions. Well, that’s OAuth 2.0.","markups":[{"type":3,"start":70,"end":79,"href":"http://tools.ietf.org/html/draft-ietf-oauth-v2","title":"","rel":"","anchorType":0}]},{"name":"3621","type":1,"text":"Last month I reached the painful conclusion that I can no longer be associated with the OAuth 2.0 standard. I resigned my role as lead author and editor, withdraw my name from the specification, and left the working group. Removing my name from a document I have painstakingly labored over for three years and over two dozen drafts was not easy. Deciding to move on from an effort I have led for over five years was agonizing.","markups":[{"type":1,"start":154,"end":193}]},{"name":"716f","type":1,"text":"There wasn’t a single problem or incident I can point to in order to explain such an extreme move. This is a case of death by a thousand cuts, and as the work was winding down, I’ve found myself reflecting more and more on what we actually accomplished. At the end, I reached the conclusion that OAuth 2.0 is a bad protocol. WS-* bad. It is bad enough that I no longer want to be associated with it. It is the biggest professional disappointment of my career.","markups":[]},{"name":"2696","type":1,"text":"All the hard fought compromises on the mailing list, in meetings, in special design committees, and in back channels resulted in a specification that fails to deliver its two main goals — security and interoperability. In fact, one of the compromises was to rename it from a protocol to a framework, and another to add a disclaimer that warns that the specification is unlike to produce interoperable implementations.","markups":[{"type":3,"start":321,"end":416,"href":"http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-1.8","title":"","rel":"","anchorType":0}]},{"name":"b7a8","type":1,"text":"When compared with OAuth 1.0, the 2.0 specification is more complex, less interoperable, less useful, more incomplete, and most importantly, less secure.","markups":[{"type":3,"start":19,"end":28,"href":"http://tools.ietf.org/html/rfc5849","title":"","rel":"","anchorType":0}]},{"name":"2b3b","type":1,"text":"To be clear, OAuth 2.0 at the hand of a developer with deep understanding of web security will likely result is a secure implementation. However, at the hands of most developers — as has been the experience from the past two years — 2.0 is likely to produce insecure implementations.","markups":[]},{"name":"e7e1","type":13,"text":"How did we get here?","markups":[]},{"name":"3493","type":1,"text":"At the core of the problem is the strong and unbridgeable conflict between the web and the enterprise worlds. The OAuth working group at the IETF started with strong web presence. But as the work dragged on (and on) past its first year, those web folks left along with every member of the original 1.0 community. The group that was left was largely all enterprise… and me.","markups":[{"type":1,"start":79,"end":82},{"type":1,"start":91,"end":101}]},{"name":"c287","type":1,"text":"The web community was looking for a protocol very much in-line with 1.0, with small improvement in areas that proved lacking: simplifying signature, adding a light identity layer, addressing native applications, adding more flows to accommodate new client types, and improving security. The enterprise community was looking for a framework they can use with minimal changes to their existing systems, and for some, a new source of revenues through customization. To understand the depth of the divide — in an early meeting the web folks wanted a flow optimized for in-browser clients while the enterprise folks wanted a flow using SAML assertions.","markups":[]},{"name":"8e78","type":1,"text":"The resulting specification is a designed-by-committee patchwork of compromises that serves mostly the enterprise. To be accurate, it doesn’t actually give the enterprise all of what they asked for directly, but it does provide for practically unlimited extensibility. It is this extensibility and required flexibility that destroyed the protocol. With very little effort, pretty much anything can be called OAuth 2.0 compliant.","markups":[{"type":1,"start":33,"end":54},{"type":1,"start":348,"end":428}]},{"name":"3d14","type":13,"text":"Under the Hood","markups":[]},{"name":"ddca","type":1,"text":"To understand the issues in 2.0, you need to understand the core architectural changes from 1.0:","markups":[]},{"name":"9999","type":9,"text":"Unbounded tokens — In 1.0, the client has to present two sets of credentials on each protected resource request, the token credentials and the client credentials. In 2.0, the client credentials are no longer used. This means that tokens are no longer bound to any particular client type or instance. This has introduced limits on the usefulness of access tokens as a form of authentication and increased the likelihood of security issues.","markups":[{"type":1,"start":0,"end":16}]},{"name":"12c2","type":9,"text":"Bearer tokens — 2.0 got rid of all signatures and cryptography at the protocol level. Instead it relies solely on TLS. This means that 2.0 tokens are inherently less secure as specified. Any improvement in token security requires additional specifications and as the current proposals demonstrate, the group is solely focused on enterprise use cases.","markups":[{"type":3,"start":135,"end":185,"href":"http://hueniverse.com/2010/09/oauth-bearer-tokens-are-a-terrible-idea/","title":"","rel":"","anchorType":0},{"type":3,"start":285,"end":296,"href":"http://openid.net/specs/draft-jones-json-web-token-07.html","title":"","rel":"","anchorType":0},{"type":1,"start":0,"end":13}]},{"name":"459e","type":9,"text":"Expiring tokens — 2.0 tokens can expire and must be refreshed. This is the most significant change for client developers from 1.0 as they now need to implement token state management. The reason for token expiration is to accommodate self-encoded tokens — encrypted tokens which can be authenticated by the server without a database look-up. Because such tokens are self-encoded, they cannot be revoked and therefore must be short-lived to reduce their exposure. Whatever is gained from the removal of the signature is lost twice in the introduction of the token state management requirement.","markups":[{"type":1,"start":0,"end":15}]},{"name":"230e","type":9,"text":"Grant types — In 2.0, authorization grants are exchanged for access tokens. Grant is an abstract concept representing the end-user approval. It can be a code received after the user clicks ‘Approve’ on an access request, or the user’s actual username and password. The original idea behind grants was to enable multiple flows. 1.0 provides a single flow which aims to accommodate multiple client types. 2.0 adds significant amount of specialization for different client type.","markups":[{"type":1,"start":0,"end":11}]},{"name":"b0bc","type":13,"text":"Indecision Making","markups":[]},{"name":"a8da","type":1,"text":"These changes are all manageable if put together in a well-defined protocol. But as has been the nature of this working group, no issue is too small to get stuck on or leave open for each implementation to decide. Here is a very short sample of the working group’s inability to agree:","markups":[{"type":1,"start":235,"end":241}]},{"name":"5a4c","type":9,"text":"No required token type","markups":[]},{"name":"7cae","type":9,"text":"No agreement on the goals of an HMAC-enabled token type","markups":[]},{"name":"3f9b","type":9,"text":"No requirement to implement token expiration","markups":[]},{"name":"d8e7","type":9,"text":"No guidance on token string size, or any value for that matter","markups":[]},{"name":"6ec1","type":9,"text":"No strict requirement for registration","markups":[]},{"name":"989a","type":9,"text":"Loose client type definition","markups":[]},{"name":"cca4","type":9,"text":"Lack of clear client security properties","markups":[]},{"name":"f073","type":9,"text":"No required grant types","markups":[]},{"name":"fbb5","type":9,"text":"No guidance on the suitability or applicability of grant types","markups":[]},{"name":"2e5a","type":9,"text":"No useful support for native applications (but lots of lip service)","markups":[]},{"name":"cbec","type":9,"text":"No required client authentication method","markups":[]},{"name":"3428","type":9,"text":"No limits on extensions","markups":[]},{"name":"914a","type":1,"text":"On the other hand, 2.0 defines 4 new registries for extensions, along with additional extension points via URIs. The result is a flood of proposed extensions. But the real issues is that the working group could not define the real security properties of the protocol. This is clearly reflected in the security consideration section which is largely an exercise of hand waving. It is barely useful to security experts as a bullet point of things to pay attention to.","markups":[]},{"name":"b824","type":1,"text":"In fact, the working group has also produced a 70 pages document describing the 2.0 threat model which does attempt to provide additional information but suffers from the same fundamental problem: there isn’t an actual protocol to analyze.","markups":[{"type":3,"start":80,"end":96,"href":"http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel","title":"","rel":"","anchorType":0}]},{"name":"65de","type":13,"text":"Reality","markups":[]},{"name":"ac0c","type":1,"text":"In the real world, Facebook is still running on draft 12 from a year and a half ago, with absolutely no reason to update their implementation. After all, an updated 2.0 client written to work with Facebook’s implementation is unlikely to be useful with any other provider and vice-versa. OAuth 2.0 offers little to none code re-usability.","markups":[]},{"name":"979b","type":1,"text":"What 2.0 offers is a blueprint for an authorization protocol. As defined, it is largely useless and must be profiles into a working solution — and that is the enterprise way. The WS-* way. 2.0 provides a whole new frontier to sell consulting services and integration solutions.","markups":[{"type":1,"start":21,"end":30},{"type":1,"start":174,"end":187}]},{"name":"fc5c","type":1,"text":"The web does not need yet another security framework. It needs simple, well-defined, and narrowly suited protocols that will lead to improved security and increased interoperability. OAuth 2.0 fails to accomplish anything meaningful over the protocol it seeks to replace.","markups":[{"type":1,"start":0,"end":53}]},{"name":"07ac","type":13,"text":"To Upgrade or Not to Upgrade","markups":[]},{"name":"52e8","type":1,"text":"Over the past few months, many asked me if they should upgrade to 2.0 or which version of the protocol I recommend they implement. I don’t have a simple answer.","markups":[]},{"name":"11cd","type":1,"text":"If you are currently using 1.0 successfully, ignore 2.0. It offers no real value over 1.0 (I’m guessing your client developers have already figured out 1.0 signatures by now).","markups":[]},{"name":"8477","type":1,"text":"If you are new to this space, and consider yourself a security expert, use 2.0 after careful examination of its features. If you are not an expert, either use 1.0 or copy the 2.0 implementation of a provider you trust to get it right (Facebook’s API documents are a good place to start). 2.0 is better for large scale, but if you are running a major operation, you probably have some security experts on site to figure it all out for you.","markups":[]},{"name":"7a07","type":13,"text":"Now What?","markups":[]},{"name":"7d73","type":1,"text":"I’m hoping someone will take 2.0 and produce a 10 page profile that’s useful for the vast majority of web providers, ignoring the enterprise. A 2.1 that’s really 1.5. But that’s not going to happen at the IETF. That community is all about enterprise use cases and if you look at their other efforts like OpenID Connect (which too was a super simple proposal turned into almost a dozen complex specifications), they are not capable of simple.","markups":[{"type":3,"start":303,"end":318,"href":"http://openid.net/connect/","title":"","rel":"","anchorType":0},{"type":1,"start":410,"end":440}]},{"name":"7afc","type":1,"text":"I think the OAuth brand is in decline. This framework will live for a while, and given the lack of alternatives, it will gain widespread adoption. But we are also likely to see major security failures in the next couple of years and the slow but steady devaluation of the brand. It will be another hated protocol you are stuck with.","markups":[{"type":1,"start":163,"end":228}]},{"name":"e2ca","type":1,"text":"At the same time, I am expecting multiple new communities to come up with something else that is more in the spirit of 1.0 than 2.0, and where one use case is covered extremely well. OAuth 1.0 was all about small web startups looking to solve a well-defined problem they needed to solve fast. I honestly don’t know what use cases OAuth 2.0 is trying to solve any more.","markups":[]},{"name":"1710","type":13,"text":"Final Note","markups":[]},{"name":"40d7","type":1,"text":"This is a sad conclusion to a once promising community. OAuth was the poster child of small, quick, and useful standards, produced outside standards bodies without all the process and legal overhead.","markups":[]},{"name":"acb9","type":1,"text":"Our standards making process is broken beyond repair. This outcome is the direct result of the nature of the IETF, and the particular personalities overseeing this work. To be clear, these are not bad or incompetent individuals. On the contrary — they are all very capable, bright, and otherwise pleasant. But most of them show up to serve their corporate overlords, and it’s practically impossible for the rest of us to compete.","markups":[]},{"name":"25c2","type":1,"text":"Bringing OAuth to the IETF was a huge mistake. Not that the alternative (WRAP) would have been a better outcome, but at least it would have taken three less years to figure that out. I stuck around as long as I could stand it, to fight for what I thought was best for the web. I had nothing personally to gain from the decisions being made. At the end, one voice in opposition can slow things down, but can’t make a difference.","markups":[{"type":3,"start":47,"end":111,"href":"http://hueniverse.com/2009/11/wrap-and-the-demise-of-the-oauth-community/","title":"","rel":"","anchorType":0},{"type":1,"start":146,"end":162}]},{"name":"74e1","type":1,"text":"I failed.","markups":[]},{"name":"c911","type":1,"text":"We failed.","markups":[]},{"name":"2b75","type":4,"text":"","markups":[],"layout":1,"metadata":{"id":"0*QX942pbCRaY7jDYU.jpg","originalWidth":400,"originalHeight":177,"externalSrc":"http://hueniversedotcom.files.wordpress.com/2012/07/oauthdead.jpg"}},{"name":"e196","type":1,"text":"Some more thoughts…","markups":[{"type":3,"start":0,"end":19,"href":"http://hueniverse.com/2012/07/on-leaving-oauth/","title":"","rel":"","anchorType":0}]}],"sections":[{"name":"44d6","startIndex":0}]},"postDisplay":{"coverless":true}},"virtuals":{"statusForCollection":"APPROVED","allowNotes":true,"previewImage":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"wordCount":1852,"imageCount":1,"readingTime":7.188679245283019,"subtitle":"","publishedInCount":1,"usersBySocialRecommends":[],"recommends":3,"socialRecommends":[],"isBookmarked":false,"tags":[{"slug":"oauth","name":"Oauth","postCount":304,"virtuals":{"isFollowing":false},"metadata":{"followerCount":31,"postCount":304,"coverImage":{"id":"1*ORSOpmzaqnFxs6KRXVFpmQ.png","originalWidth":2400,"originalHeight":1260}},"type":"Tag"},{"slug":"open-web","name":"Open Web","postCount":90,"virtuals":{"isFollowing":false},"metadata":{"followerCount":7,"postCount":90,"coverImage":{"id":"0*agMNFzszqr2E3oqX.jpg","originalWidth":2000,"originalHeight":387}},"type":"Tag"}],"socialRecommendsCount":0,"responsesCreatedCount":1,"links":{"entries":[{"url":"http://hueniverse.com/2010/09/oauth-bearer-tokens-are-a-terrible-idea/","alts":[{"type":1,"url":"https://cdn.ampproject.org/c/s/hueniverse.com/2010/09/29/oauth-bearer-tokens-are-a-terrible-idea/amp/"}]},{"url":"http://hueniverse.com/2012/07/on-leaving-oauth/","alts":[{"type":1,"url":"https://cdn.ampproject.org/c/s/hueniverse.com/2012/07/30/on-leaving-oauth/amp/"}]},{"url":"http://hueniverse.com/2009/11/wrap-and-the-demise-of-the-oauth-community/","alts":[{"type":1,"url":"https://cdn.ampproject.org/c/s/hueniverse.com/2009/11/23/wrap-and-the-demise-of-the-oauth-community/amp/"}]}],"version":"0.3","generatedAt":1490229354503},"isLockedPreviewOnly":false,"takeoverId":"","metaDescription":"","totalClapCount":0},"coverless":true,"slug":"oauth-2-0-and-the-road-to-hell","translationSourcePostId":"","translationSourceCreatorId":"","isApprovedTranslation":false,"inResponseToPostId":"","inResponseToRemovedAt":0,"isTitleSynthesized":false,"allowResponses":true,"importedUrl":"","importedPublishedAt":1343288243000,"visibility":0,"uniqueSlug":"oauth-2-0-and-the-road-to-hell-8eec45921529","previewContent":{"bodyModel":{"paragraphs":[{"name":"38e1","type":3,"text":"OAuth 2.0 and the Road to Hell","markups":[],"alignment":1},{"name":"3792","type":1,"text":"Update: three years later I wrote something new… introducing Oz.","markups":[{"type":1,"start":0,"end":64}],"alignment":1},{"name":"95f4","type":1,"text":"They say the road to hell is paved with good intentions. Well, that’s OAuth 2.0.","markups":[{"type":3,"start":70,"end":79,"href":"http://tools.ietf.org/html/draft-ietf-oauth-v2","title":"","rel":"","anchorType":0}],"alignment":1}],"sections":[{"startIndex":0}]},"isFullContent":false},"license":0,"inResponseToMediaResourceId":"","canonicalUrl":"https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529","approvedHomeCollectionId":"ee73cfff03f","approvedHomeCollection":{"id":"ee73cfff03f","name":"hueniverse","slug":"hueniverse","tags":[],"creatorId":"b4e3921706ee","description":"The technical musings of Eran Hammer","shortDescription":"The technical musings of Eran Hammer","image":{"imageId":"1*FucaTWCRPOZ6XdfDCe3c4Q.png","filter":"","backgroundSize":"","originalWidth":371,"originalHeight":371,"strategy":"resample","height":0,"width":0},"metadata":{"followerCount":28,"activeAt":1490305770641},"virtuals":{"permissions":{"canPublish":false,"canPublishAll":false,"canRepublish":false,"canRemove":false,"canManageAll":false,"canSubmit":false,"canEditPosts":false,"canAddWriters":false,"canViewStats":false,"canSendNewsletter":false,"canViewLockedPosts":false,"canViewCloaked":false,"canEditOwnPosts":false,"canBeAssignedAuthor":false},"isSubscribed":false,"isNewsletterSubscribed":false,"memberOfMembershipPlanId":""},"logo":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"twitterUsername":"eranhammer","publicEmail":"eran@hammer.io","domain":"hueniverse.com","sections":[{"type":2,"collectionHeaderMetadata":{"title":"hueniverse","description":"","backgroundImage":{},"logoImage":{},"alignment":2,"layout":6}},{"type":1,"postListMetadata":{"source":1,"layout":6,"number":10,"postIds":[]}}],"favicon":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"colorPalette":{"defaultBackgroundSpectrum":{"colorPoints":[{"color":"#FF02B875","point":0},{"color":"#FF00AB6B","point":0.1},{"color":"#FF1C9963","point":0.2},{"color":"#FF092E20","point":1}],"backgroundColor":"#FFFFFFFF"},"highlightSpectrum":{"colorPoints":[{"color":"#FFFFFFFF","point":0},{"color":"#FFE9FDF0","point":0.1},{"color":"#FFE2FAEE","point":0.2},{"color":"#FFADFFCF","point":0.6},{"color":"#FF7DFFB3","point":1}],"backgroundColor":"#FFFFFFFF"}},"navItems":[],"colorBehavior":1,"instantArticlesState":0,"acceleratedMobilePagesState":0,"ampLogo":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"header":{"title":"hueniverse","description":"","backgroundImage":{},"logoImage":{},"alignment":2,"layout":6},"paidForDomainAt":1490229509426,"type":"Collection"},"newsletterId":"","webCanonicalUrl":"https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529","mediumUrl":"https://hueniverse.com/oauth-2-0-and-the-road-to-hell-8eec45921529","migrationId":"e5e8715558e0","notifyFollowers":false,"notifyTwitter":false,"isSponsored":false,"isRequestToPubDisabled":false,"notifyFacebook":false,"responseHiddenOnParentPostAt":0,"isSeries":false,"isSubscriptionLocked":false,"seriesLastAppendedAt":0,"audioVersionDurationSec":0,"type":"Post"},"mentionedUsers":[],"collaborators":[],"membershipPlans":[],"collectionUserRelations":[],"mode":null,"references":{"User":{"b4e3921706ee":{"userId":"b4e3921706ee","name":"Eran Hammer","username":"eranhammer","createdAt":1345095435598,"lastPostCreatedAt":1490305704020,"imageId":"0*3ZLq0yvVG4WO2TBk.jpg","backgroundImageId":"","bio":"","twitterScreenName":"eranhammer","socialStats":{"userId":"b4e3921706ee","usersFollowedCount":46,"usersFollowedByCount":3636,"type":"SocialStats"},"social":{"userId":"lo_b364a39284f5","targetUserId":"b4e3921706ee","type":"Social"},"facebookAccountId":"","allowNotes":1,"type":"User"}},"Collection":{"ee73cfff03f":{"id":"ee73cfff03f","name":"hueniverse","slug":"hueniverse","tags":[],"creatorId":"b4e3921706ee","description":"The technical musings of Eran Hammer","shortDescription":"The technical musings of Eran Hammer","image":{"imageId":"1*FucaTWCRPOZ6XdfDCe3c4Q.png","filter":"","backgroundSize":"","originalWidth":371,"originalHeight":371,"strategy":"resample","height":0,"width":0},"metadata":{"followerCount":28,"activeAt":1490305770641},"virtuals":{"permissions":{"canPublish":false,"canPublishAll":false,"canRepublish":false,"canRemove":false,"canManageAll":false,"canSubmit":false,"canEditPosts":false,"canAddWriters":false,"canViewStats":false,"canSendNewsletter":false,"canViewLockedPosts":false,"canViewCloaked":false,"canEditOwnPosts":false,"canBeAssignedAuthor":false},"isSubscribed":false,"isNewsletterSubscribed":false,"memberOfMembershipPlanId":""},"logo":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"twitterUsername":"eranhammer","publicEmail":"eran@hammer.io","domain":"hueniverse.com","sections":[{"type":2,"collectionHeaderMetadata":{"title":"hueniverse","description":"","backgroundImage":{},"logoImage":{},"alignment":2,"layout":6}},{"type":1,"postListMetadata":{"source":1,"layout":6,"number":10,"postIds":[]}}],"favicon":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"colorPalette":{"defaultBackgroundSpectrum":{"colorPoints":[{"color":"#FF02B875","point":0},{"color":"#FF00AB6B","point":0.1},{"color":"#FF1C9963","point":0.2},{"color":"#FF092E20","point":1}],"backgroundColor":"#FFFFFFFF"},"highlightSpectrum":{"colorPoints":[{"color":"#FFFFFFFF","point":0},{"color":"#FFE9FDF0","point":0.1},{"color":"#FFE2FAEE","point":0.2},{"color":"#FFADFFCF","point":0.6},{"color":"#FF7DFFB3","point":1}],"backgroundColor":"#FFFFFFFF"}},"navItems":[],"colorBehavior":1,"instantArticlesState":0,"acceleratedMobilePagesState":0,"ampLogo":{"imageId":"","filter":"","backgroundSize":"","originalWidth":0,"originalHeight":0,"strategy":"resample","height":0,"width":0},"header":{"title":"hueniverse","description":"","backgroundImage":{},"logoImage":{},"alignment":2,"layout":6},"paidForDomainAt":1490229509426,"type":"Collection"}},"Social":{"b4e3921706ee":{"userId":"lo_b364a39284f5","targetUserId":"b4e3921706ee","type":"Social"}},"SocialStats":{"b4e3921706ee":{"userId":"b4e3921706ee","usersFollowedCount":46,"usersFollowedByCount":3636,"type":"SocialStats"}}}})
* Connection #0 to host hueniverse.com left intact
// ]]></script></body></html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment