Aaron Parecki: All right. Thanks so much, Marc. It’s great to be back here. It’s been too long, so I’m very excited to be back here in front of everybody today.
Today, I’m going to talk all about why we actually need OAuth.
I need my slides on the screen.
So, yeah. Today, why do we actually even need OAuth? I know a lot of people have probably used it. A lot of people have probably tried to use it and failed in various ways. It’s not necessarily obvious how this stuff works. So, we’re going to try to clear some of that up today.
But as more and more of our lives (every day of our actual lives) is moving online, security of the online world is becoming super, super important. It used to be that--
Well, hackers can do now everything from extracting millions of dollars from businesses with ransomware and even taking down critical infrastructure and even taking over YouTube channels and streaming cryptocurrency scams. It happens all the time. It used to be that the extent of the damage someone could do was just steal someone’s address book and spam their friends.
Yeah, we know security is important, but what does this have to do with OAuth? That is my goal today is to show you how OAuth can actually make your online lives and your applications you’re building more secure and help prevent a lot of attacks like these.
I’m Aaron Parecki. I work at Okta where I have taught thousands of developers about how OAuth works and how to use it securely and well. I have a book and a video course to talk about this in great detail.
I also participate in the IETF, which is where the actual OAuth spec is made. A lot of work is done there to improve a lot of different aspects of the Internet and how these things work. So, let’s just jump right in.
This is OAuth2. This is the spec, RFC 6749. And if you’ve ever tried to read this stuff, I apologize because it turns out specs are really just not good tutorials. They’re really not meant to be a beginner’s guide to how this stuff works.
They’re a lot more like a legal reference where every word in this spec is very carefully chosen. Oftentimes, there are words that are defined in other specifications. They build upon each other, so there isn’t just one spec for anything, really.
OAuth is one of the most complicated, in that sense. There are dozens of specs that make up OAuth. Some of them are even made by different groups outside of the IETF, which just adds to the confusion.
There are several different organizations working on different aspects of this space. It can be very, very challenging to try to find your way through this maze of specs when you’re just faced with the specs.
So, that’s why we’re not talking about the specs because it turns out that’s actually very boring. It’s pretty dry stuff. It’s only really interesting once you know about why you should even care about this in the first place. So, we’re going to take a step back, zoom out, and look at this from a different level.
You might be familiar with OAuth from its use in buttons like these: Sign in with Facebook, Sign in with Google. We’ve seen these all over the Web, now. It’s very common to use this pattern.
Is this OAuth? Well, yes, but also no. There’s some aspect of this that is OAuth and some that isn’t. So, let’s go back and talk about why OAuth was actually originally created.
Originally, OAuth was created to limit or delegate access to data. Now those are some fancy words, so what does it actually mean?
Well, this used to be the way this stuff worked online. You would have a brand new app like Yelp, which would launch. Yelp wanted to go and see if any of your friends were already using Yelp and then make the connections in this new social network.
And what it would do, is it would ask you to enter your email address and ask you for the password to your email, which should be setting off a bunch of red flags right now in your head.
Aaron: We generally recognize this is not a good idea today. But it was extremely common. Even Facebook was doing this up until actually pretty recently. So, you kind of have this inherent idea of why this is bad, but let’s actually go dig into that.
One of the big problems is that when you’re giving this application (like Yelp or Facebook) to log in to your email, it’s saying it only needs access to your contacts because it wants to just see if your friends are already there. So, even though it only needs access to some of the data in your account, by giving it your password, you’ve given it access to all of the data in your account.
So, that means it’s going to say it’s going to access your contact list. But then, in reality, it could also read your actual emails. It could also send email from your account because you’ve just given it the key to your account. And importantly, there is no way to take this back. Once you’ve given your password to an app, that’s it. Until you change your password, that app can do whatever you can do.
So, essentially what this means is that if you do this, you are completely trusting this application to do the right thing. And not only are you trusting it to only do what it’s saying it’s going to be doing, you’re also trusting it to do that securely.
So, let’s say, yeah, you do believe that when Facebook says, “We only access your contacts and your email, nothing else,” maybe you do believe that, but you’re also placing this trust in the fact that Facebook isn’t going to accidentally log your password in some file somewhere or isn’t accidentally going to have a bug that causes them to go and access other data.
So, it’d be really nice if there was a way where we didn’t have to have that inherent trust. We’re not going to stop users from doing this because users actually do want to share this data, the contact list. We want to let users do that because otherwise, they’re going to find ways around.
But we would like to prevent those apps from accessing data that it doesn’t need. So, ideally, we’re going to find a way to let apps access one part of an API while not letting whatever that thing is access other parts of the API. That’s this idea of limiting the scope of what an application can do. At the same time, we can also limit the lifetime of that access. We can say, “Yeah, you can access my contacts for one day.”
So, let’s bring this into the real world for a second. As it turns out, we actually do have this pattern in the real world and that is this idea of issuing limited capability things or tokens (if you want to call them that).
When you go to a hotel and you check-in, you go to the front desk and you show that person your ID and credit card. Then they give you back the hotel key. You go to the room, you swipe the key, and the door opens up. Now, that hotel key gives you access to only certain things in the hotel. It gives you access to your room, maybe the hotel gym, maybe the pool, maybe the roof, and the front door after it’s locked at night.
If we didn’t have that system, it will be like you go to the hotel and you get the skeleton key that can open up all the doors, which doesn’t really make sense. This does exist and this works well in the real world. We want a way to translate that online.
It’s again mainly because of this inherent issue around trust. It started with this idea of third-party apps where you have one company’s application accessing data in a different company’s API. So, Yelp accessing data from Google, or Last.fm trying to pull what you’ve listened to from Spotify, or Buffer trying to post data into your Twitter account.
How are we going to do this? We can’t give the password to the application because then it would access to everything. So instead, we need to do some sort of dance where we can let this application get something like a hotel key.
So, if we start out at the application where there’s a button that says, “Connect your Google account,” that application, we’re not going to type in the Google password. Instead, that application can send you over to the Google website, which is OAuth server.
That is where you would then log in with your email address and your password. That might be also where you then you have to use your two-factor auth, your YubiKey, face ID, or something at Google. Then Google would also ask you, “Is it okay if Facebook gets this data?”
Assuming you’d click yes, Google then sends you back to the application. Now it has this hotel key that it can use to go get the data that you’ve explicitly agreed to. That’s really the core of how OAuth works is it’s got this line between the application and the OAuth server.
A big part of this (for the third-party app use case) is this idea of asking the user for permission. You’ve seen screens like this all the time. This is the consent screen in OAuth. This is an application that is requesting access to see my contacts, download my contacts, edit the contacts. But, by granting this, I won’t be giving this application the ability to see any of my emails. That’s because I am at Google’s website when I’m granting this request.
It looks different on different services. Sometimes the different services will display this screen in a different way and have different information on it, but it’s the same idea.
This is what it looks like on Twitter where it says, “This application will be able to see the tweets from your timeline, see your Twitter profile information, see the accounts you follow.” But notably what’s missing from that list is reading DMs, posting tweets for you. So, you know that by granting this application access through OAuth, it is only going to be able to do these things.
On GitHub, it again looks different. GitHub has a list of what this app will be able to do and in which organizations.
Facebook is actually an interesting example where it has a sort of summary and then it lets you click in to get more details where you can actually then remove access. And you can say, even though the app is asking for access to my friend list, I going to actually not grant that. That’s kind of a nice way to give the user more control.
Fitbit does that as well where an application can ask for access to all of your Fitbit data, and then you can actually decide I don’t want it to access my location data or my sleep data.
This kind of thing makes a lot of sense when we talk about third-party applications where, again, the app is made by a different company than where that data lives that it’s trying to access.
What about first-party apps? It doesn’t really make sense, if you download the Twitter app, if the first thing that it does is ask you if it’s okay to access your Twitter data because it is the Twitter application, so that trust is sort of already there.
This is actually something I hear a lot, which is, “Okay, well, I’m not writing. I’m not using third-party apps. I’m not making an ecosystem where my developers are third parties. They are all in my company.”
Why can’t I ask for the user’s password in my application? One of the biggest reasons that I hear this is because the creators of these applications (usually mobile apps) often place a very high value on the branding and design aesthetic of the application, often to a fault, which is what this screenshot represents because, I don’t know if you can see it--
Aaron: [Laughter] --but there is a button there that says, “Sign in,” at the bottom, and it is light gray text on a light green. It’s basically invisible even not on a projector.
This is a real application, by the way. I don’t even remember what it is because they forgot to put their actual brand on it. But they had such a design in mind of what the screen should look like and the fact is that you can’t do this when you’re using OAuth because of how that sort of take you out of the app to the OAuth server works.
So, they’ll be like, “Sure. Why can’t I put a password dialogue in my app and ask for the user’s password in my app?” Because again, you don’t have the trust issue with first-party apps.
Let me show you another example of someone who does this, and that’s Apple. If you go to icloud.com and try to sign in, you are presented with a password prompt for your iCloud account (or maybe it’s called an Apple ID). They’re actually not very consistent about what they even call the account.
So, you type in your password here. Great, you’re logged into your iCloud account on the browser. Fine.
Think for a minute, where else have you ever entered your iCloud password? Turns out, a lot of different places.
There’s icloud.com. There’s also the Apple Store. There’s also the App Store on your computer, which is now not a browser. It’s a native app. And then just to confuse things, there’s also your keychain password, which is the system password for your computer that sometimes is also prompted for.
Here’s a challenge for you. Try to describe to anybody how to tell whether it’s safe to enter your password here or whether one of these dialogues is fake. It’s pretty much impossible. It’s even harder on mobile.
This is, again, a real example from this blog post. On the left is a real prompt. That’s the one that sometimes just randomly pops up on your phone, and it says, “By the way, we need you to sign in to the iTunes store again,” for some reason. You’re never really sure why. You enter your password and then the dialogue goes away and everything is fine.
On the right is a fake prompt. This is you’re in an app. That application popped up this dialogue. The dialogue looks identical because it is a system default styled dialogue. There is no indication about which of these is fake. If you enter your password into the fake one, that app developer gets your password.
Why is this a problem? Let’s take this to another level which is a very common problem and the source of a lot of attacks online which is phishing. This kind of looks fake, honestly, but it’s actually a real sharing dialogue that I sent myself from an iCloud account to make this screenshot. I did change the domain name by one character to demonstrate how easy it is to make these things look real. The domain, of course, should be icloud.com. The domain in that screenshot is noreply-icloud.com. I moved the @ to the other spot.
This is what Apple’s shared folder notifications look like in email. You get an email like this, and it says, “Hey, click here to view this file. Someone shared it with you.”
If you get a fake one of these, that link will take you to a fake website, not Apple’s website. It is very easy to make those fake websites look identical to the real website. The only difference would be the URL. It’s also not that hard to make a URL that looks close enough to the real one that it will trick most people.
If you’ve now already given your password to someone because they put up a fake password dialogue in your computer or your phone. If that wasn’t enough to get your password before, you’re just going to give it to them in this shared file dialogue and now they’re in that way.
Cool. But you have multifactor authentication turned on, right? So, you’re safe. You get this little prompt whenever you sign in to stuff in your iCloud account. And then you go and type in that code into the website to make sure that it’s actually you in front of the screen.
Well, it turns out, that doesn’t actually solve the problem either because if you think you’re logging in to Apple and you get a multifactor code like this, you’re going to go type it into the attacker’s website. Now they’ve just bypassed your multifactor authentication.
So, what good is any of this then? How do we solve that? Well, it turns out that not all multifactor authentication is created equal. That’s really the problem here.
Some of them are phishable. Anything that involves the user sort of typing in something from one place to another, so any codes sent to you over SMS, if you are expected to type that code into another place, you can be tricked into typing it into the wrong place. That includes the Apple push notification with the code. Anything that works that way.
Also, the prompts, like Google has, which are just a pop in your app that says, “Hey, are you trying to sign in, yes or no?” If you think you’re trying to sign in, you will click yes. This is only going to stop the ones where the attacker is trying to log into your account and you’re not aware of it happening. So, they do something. They just don’t stop all of the attacks.
There’s a different type of multifactor authentication which is not able to be phished. These are the ones based around WebAuthn and Fido. So, it’s going to be your YubiKey or your touch ID on your phone, face ID, Windows Hello, all those kinds of things. The reason for that is because, in the last couple of years, we’ve finally gotten support by operating systems and browsers to actually bake this stuff in at the level we need in order to make it not phishable.
The main way that works is by actually tying the credential that is created from these MFA systems to the domain that you’re logging in on. So, that credential is unique to this domain, which means the same phone will present different credentials to different websites based on the domain. That’s why it can’t be phished because you can’t be tricked into providing the MFA code for the Apple website to the Google website because it just doesn't work that. It’s physically not possible.
Cool. So, we’ve solved phishing. We solved all of this stuff.
However, we’ve now created a new problem, which is for companies that operate a large number of websites under one brand. For example, Google.
How many different apps does Google have? Gmail, YouTube, google.com, Blogger. Anybody still use that? Those are all different domain names, which means they can’t share the non-phishable multifactor authentication.
So, how do we solve this? Well, if we had one domain that was used for logging in and providing the multifactor authentication and those were able to somehow share that domain just for the log-in stage, we could solve it, which is exactly what OAuth does.
So, we start up the application. In this case, it’s Gmail, which is a Google brand. You click sign-in, and Gmail does not ask you for your Google password. This is very notable. If you pay attention to any time you’re signing in to anything that’s related to Google, those applications, you don’t type your password into them.
Instead, it sends you over to the Google OAuth server. That’s accounts.google.com. That is where you sign in. That’s where you type in your email. You type in your password. That’s where you do your multifactor authentication, which means you can do the ones that can’t be phished. Then you get sent back to Gmail.
So, again, we’re able to use OAuth even though it’s a first-party scenario. Even though I’m still logging into a Google application with my Google account, it still makes sense to use OAuth to do that.
So, now when I log into YouTube, we do the same flow. We go over to Google, we sign in there, do the MFA, come back to YouTube, and we’re signed in. If you’re on blogger.com, the same thing. So, that’s how we can use OAuth even if we don’t have the inherent trust issue of not wanting to share the password with the app because it is under that same company’s brand.
The last step of this is something that people often don’t think about when they start until they get kind of far into the process and realize there’s a lot more work they have to do. And that is your whole registration and account recovery flows. So, if you’re building an application and you want users to sign in, you also need people to sign up for the account, create an account. You also need to handle the case if they forgot their password in order to handle password resets. So, you’re going to start diagraming what this looks like when you’re going to start wireframing your screens and figuring out what you need to build.
You’re going to start with, okay, we have this sort of homepage launch screen of the app. Launch the application and it says please login or sign up. They tap the login button and that goes into a login form. Cool.
If they type their username and password correctly, you can log them in and everything’s great. If they type in the wrong password, you have to show them a message and send them back into the login form. Eventually, they will get it right and they’re logged in, right?
Well, what if they forgot their password? You need to give them a way to reset their password. So, now you have a second form to create, a password reset form. They enter their email address, and it will send them an email. They will go click the link in the email. It takes you to a new page in the application that you now have to design, which is confirming that that link was correct and then giving them a way to create a new password. Then they can be logged in.
Okay. We’re getting there. We still have to handle the case of signing up. So, they click the other button in the home screen, which is to create an account. You’re going to show them the registration form.
What if they enter an email that already exists? Well, you should probably tell them to reset their password or log in, in case they forgot it. So, then they enter an email that doesn’t exist. You send them another email to design. You have to make this email look good too which is, “Hey, thanks for signing up. Go ahead and click this link to finish creating your account.” Then they can create a password and then they can be signed in.
Okay. So, that’s quite a bit. This is vastly simplified. There’s actually a lot more that I didn’t even include on this. So, that’s like, is their password good? Is it just the same letter over and over again? Is it one of the common passwords? Maybe you should reject it and tell them to pick a better password. Maybe you need to add some rate-limiting to the form that sends those email links because you don’t people to be able to use your system to spam existing users. Maybe you need to--
Yeah. There are several lines I didn’t even include on this. So, you can imagine how much goes into building this kind of system.
If you’re building this into your native app or your single-page apps or your web apps, that’s a lot of dialogues to design and a lot of things to manage. If you are launching an app across multiple platforms, you have to do all of that work every time. So again, this is where we can use OAuth to help solve this.
Back to our OAuth flow, let’s say you build the application and you want to have users create an account or sign up. Well, in your application code, all you do is you say, “Go over to the OAuth server,” and then you make it the OAuth server’s job to deal with that complicated diagram. The OAuth server will sort of handle the user for a while and eventually send the user back to the app and now you can be logged in.
So, as an app developer, you can basically treat that like a black box and not really worry about what’s going on inside because you just know the OAuth server is going to do its job and make that work and let you know when it’s done. That OAuth server could be an open-source project that you’re running on some server. It could be a service that you’re paying for. It doesn’t really matter where that happens to be because, from your app’s point of view, you’ve just sent the user out and wait for them to come back.
So, back to our original question. Is this OAuth? Yes, because one of the things this does and one of the reasons people use these buttons is it offloads all that complicated stuff about logging into apps into the OAuth server. So, you know, when you use a sign-in with Google button as the app developer, you don’t worry about do they have a Google account, have they forgotten their Google password, do they need to do MFA or not. It’s the business of the OAuth server. But this is not OAuth in that OAuth by itself doesn’t actually give you enough to make this work because, again, going back to the reason OAuth was created, it was for providing access to data.
Again, think about the hotel key example. When you go to the room of your door and swipe the key, the door doesn’t need to know your name or your email, or your phone number, or anything about you. It does not need anything about your identity. All that the door needs to know is, does this little piece of plastic have the information in it that says, “I should unlock right now”? That’s the core that OAuth was created to solve was apps getting access to things.
So, then what is this? This is OAuth plus extra stuff. OAuth is a good foundation for this. We do have to add a little bit more on top in order to make those kinds of buttons works. Think about OAuth as, again, it’s providing access to data. If you then say what that data is, maybe that data is information about the user. But you then have to create that in your own little bubble of deciding how that’s going to work, which is exactly why so many of these OAuth libraries that you’ll use have special hard coated bits and pieces in them for all these different providers because everybody did it a slightly different way.
There is an effort standardizing this. However, it’s mostly being done in the sort of enterprise and corporate world, and that’s OpenId Connect. That’s filling in that aspect of OAuth of user identity. It’s adding that into the OAuth framework. We just don’t see it in the sort of consumer APIs like Google and Facebook, usually.
So, OAuth is always about accessing APIs. OpenId Connect is about identifying the user.
OAuth is a great foundation for avoiding handling passwords and apps for all of the reasons we talked about, like you don’t want to have to trust the application. You don’t want to have to risk applications accidentally doing something wrong with passwords if they are given to them, even if the user trusts the application. But also, really importantly, it’s how we can use the better multifactor authentication systems in these applications where, again, that logic is moved outside of the app. It’s offloading all that complexity of the registration flows and all of that into the OAuth server to make it the OAuth server’s job. So, this works well.
What’s happened that’s coming in the future? There is a lot of work still being done in OAuth. OAuth is by no means a finished specification. Currently, there’s a lot of work to add more layers of security for various reasons. There are certain use cases that require even tighter controls of various parts of the flows. In particular, the health and finance world. They’re building profiles of OAuth or adding additional features into it to tighten things up and make it even more strong.
Myself, in particular, I’m working on a revision to the core draft, OAuth 2.1. The goal here is to really kind of clean up the mess of specs over the last ten years and consolidate everything to give people an easier starting point once you do want to read the spec because, honestly, right now, there are about 12 drafts you have to read, starting from 2012, in order to get to the point of what most of the industry considers is the best way to do OAuth.
So, if you are excited about learning more, I have a bunch of resources for you. Oauth.net is the community website of OAuth where you can find links to all of the specs. You can find links to the additional new work being done. You can find links to books, resources, code.
My video course and book is available at oauth.wtf. If you’re interested in OAuth in the world of personal websites, check out indieauth.net. We’ll talk more about that on Thursday at the Indie Web Camp as well. But that’s how you can use the same OAuth foundation to bring it into your WordPress blog or your own personal website to use your website to log into things as well.
Thank you very much. This has been fun. Have a great rest of the conference.