OAuth Has Ruined Everything

OAuth Sucks. I’m probably not telling you something that you don’t already know. If you’ve ever had to setup authentication to one (or heaven forbid) multiple authentication providers (Google, Facebook, Twitter, Instagram, etc.), then you already know that it’s enough to make anyone want to switch careers.

Nobody has ever implemented an OAuth flow for their application and then said, “That was fun. Let’s do it again.”

Don’t believe me? Just go to Twitter and search for “OAuth Sucks”. Or just search “OAuth”. Or best of all just follow the OAuthSucks Twitter account. It’s a sentiment that’s so common, it has it’s own Twitter account. How did I find this account? I tried to register it of course.

But why is OAuth so awful? And does it have to be this way? In this post, we’ll take a look. OAuth (2.0 specifically) has a litany of problems, starting with the fact that the 2.0 spec itself essentially allows anything to be considered “OAuth compliant”.

OAuth And The Road To Hell

In an article called “OAuth And The Road To Hell”, Eran Hammer, who was originally on the OAuth 2.0 working group, talks about why he left, asked them to withdraw his name from the specification and even called it “the biggest professional disappointment of my career.” Now granted, that was 2012. He may have had a bigger disappointment since then.

To summarize the post for you, pressure from enterprise interests resulted in a spec that did not really enforce an opinion on anything and left all implementation details up to interpretation. It’s essentially a spec that was designed to conform to whatever the implementer needed it to look like. A specification that is different depending on what you need it to look like is no specification at all.

All pipe is to be made of a long hole, surrounded by metal centered around the hole.

No fittings are to be put on pipe unless specified. If you do, straight pipes become crooked pipes.

– Excerpt from The Piping Specification (Unknown Source)

Even more damning than that is the fact that the main problem with the OAuth 1.0 specification was that it was overly complex. There is a site called OAuthBible whose sole purpose is just to explain the concept of OAuth. Hammer called the 2.0 spec more complicated than 1.0.

So OAuth is complex, confusing, and the people that created it can’t agree on whether or not it’s bad, or just plain horrible. But the fact remains that it is how you have to authenticate to third party providers most of the time. And since, as Eran explained, the spec allows implementers to do anything they want, each and every provider has to explain to you how to do OAuth based on the way they implemented it.

The only thing worse than OAuth is the attempt by all of the implementers to explain to developers how to actually use it. You basically need to be an expert on everyone’s proprietary implementation, which is exactly what specifications are supposed to mitigate.

The truly sad part of all of this is that, in my opinion, social logins are one of the best things to happen to the web in recent years.

Nobody Wants To Register

Registering for applications is a tax that nobody really wants to pay, especially on mobile devices. Social logins are the “registration tax loophole”. Most of us are already on social media in some form or another. Even if you just scope to Twitter, Facebook and Google, you’re probably going to be able to cover most everyone.

Our social networks already know too much about us (I’m looking at you over-sharers). Instead of having to register for every new service we want to try, we can just tell them to verify with one of these social networks that we are who we say we are. In fact, this might be the only real value social networking services deliver. And here you thought it was all memes, vines and pithy quotes about how happy people are on their anniversaries.

“Burke, you sound so bitter.” I know. That’s what happens when you deal with OAuth.

When implementing social logins, we don’t actually want to use a third party API, we just want to ask them to verify a user. That should be easier right? HAHAHAHA….no.

Adding Google Sign-In

Let’s look at just Google for a minute. Google has an authentication flow specifically when you just want a button that says “Sign In With Google”. Does it use OAuth? How would I know. It doesn’t say.

What it does say is that one can “Enable Google Sign-In with only a few lines of code.” ORLY? Let’s find out.

Google wants you to include a script in the head of your page and an element that the script will turn into a button. When you click on that button, a modal window will open and you will have the chance to authenticate using Google. When you sign in, the window closes and there is a global callback that fires. This is what it looks like.

<html lang="en">
  <head>
    <meta name="google-signin-scope" content="profile email">
    <meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
    <script src="https://apis.google.com/js/platform.js" async defer></script>
  </head>
  <body>
    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
    <script>
      function onSignIn(googleUser) {
        // The ID token you need to pass to your backend:
        var id_token = googleUser.getAuthResponse().id_token;
        console.log("ID Token: " + id_token);
      };
    </script>
  </body>
</html>

That’s pretty much straight from the docs. And you know what? It works.

google-sign-in

The user signs in, and you get a token back. Done right? WRONG.

That token means jack squat. In fact Google says, “If you use Google Sign-In with an app or site that communicates with a backend server, you might need to identify the currently signed in user on the server.”

Well, since that’s virtually every application ever, there is now another step to the process. The client-side flow gets you the token, but now you need to verify that token. If you scroll down, it tells you to send the token to your server and then validate that…

  • The ID token is a JWT that is properly signed with an appropriate Google public key (available in JWK or PEM format).
  • The value of aud in the ID token is equal to one of your app’s client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app’s backend server.
  • The value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
  • The expiry time (exp) of the ID token has not passed.
  • If your authentication request specified a hosted domain, the ID token has a hd claim that matches your Google Apps hosted domain.

Awesome. A bunch of terminology that I don’t know. Lucky for you, Google has some libraries that are going to help you out. Down at the bottom of the page, they show you how easy it is to authenticate using the Java Google API Client Library. What if you’re not using Java? Well, they have a Python example too.

Not using Java or Python? Then you’re screwed.

In my case, I was using .NET. Hmmm. No library for .NET. Let’s check NuGet.

nuget

Google API…that looks like it. Let’s use that one. I’ll just use the same namespaces that the Java library uses because they would be consistant right? No. Of course they aren’t. So let’s do some Googling to see if we can figure out if anyone has every successfully done this with .NET.

All of my hits bring me back to the same GitHub sample project that looks like a low level implementation of WHAT IS THIS I DON’T EVEN.

what is this

As it turns out, what Google is actually wanting here is an implementation of JWT, or JSON Web Tokens, yet another specification for you to learn. There is a .NET library available for JWT, but good luck trying to figure out how to implement it. I eventually pulled it off, but only after lifting code from what’s got to be the most obscure message board on the internet. So obscure that I can’t find it anymore.

If you’re interested in how to validate JWTs with .NET, here is a Gist that contains the code that I lifted.

At Telerik, we’re all about making the developer experience better, and I can’t think of a worse development experience than OAuth. Telerik Backend Services was designed to mitigate this sort of nonsense. Let’s take a look at how it works.

Google Login With Telerik Backend Services

First, we need to enable Social Authentication in our project in the Platform Dashboard.

enable-social

Now we can work directly with the Backend Services API (AKA Everlive) instead of having to proxy through our own server. Lets just add it from Bower.

bower install everlive --save-dev

The client OAuth flow stays the same. The developer uses Google’s script include to open the modal and ask the user to sign in. After the user has signed in, instead of dealing with a JSON Web Token, we can use the actual OAuth token since the Platform SDK is going to validate it for us.

<script>
    window.onGoogleSignIn = function (user) {
        var token = user.wc.access_token,
            el = new Everlive("5tnum1NuePyeHNwk");

        el.authentication.loginWithGoogle(token,
            function () {
                alert("Logged In!");
            },
            function (e) {
                alert("Error: " + e);
            }
        );
    };
</script>

And we’re done.

The Backend Services SDK will also do the same work for Facebook, Twitter, Windows Live and even Active Directory (for all my enterprise peeps out there).

We Can Do Better

Telerik Backend Services makes this a much less painful process. However, we still have to know which token to get, how to get that token, and how to implement it for each identity provider we want to integrate. And we have to know this for every single provider we want to integrate with, since it’s going to be different everywhere. That’s ridiculous.

This is my formal call for a proper identity solution on the web.

Why does OAuth suck? Because it’s proprietary. It’s not a standard, it’s a just a made up word that roughly translates to, “Good [bleeping] luck”.

We have got to standardize this. This is the web people. If we make this easier, it will encourage more developers to use established credential stores instead of creating more, which just increases the attack surface for hackers wishing to see your Target purchases or which dating websites you’re a member of. Personally, I’m looking forward to the day when I never have to register for another site again.

In the meantime, we have Telerik Backend Services to at least ease the pain of an otherwise nearly impossible endeavor. I hate you OAuth. Now and forever.

Grab the sample code for this article from GitHub.

Image courtesy of Daria

[cm_ad_changer campaign_id=11]

Comments