Securing Your APIs with OAuth 2.0 - API Days

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I'm Erin perky and I'm excited to be here today I talked to you about securing your api's with OAuth so let's just jump right in this is the spec here we go-oh authorization framework enables third party epoch a I'm just kidding specs are a terrible way to learn this stuff turns out the specs are written like more like a legal contract and you know every word is very carefully chosen because of its meaning and their each word is to find in like five other specs so that's not the best plan for how we're gonna actually learn this stuff and the worst part about OAuth is it's actually it can feel like going through a maze trying to actually navigate this because it's not just one spec it's like 20 and you have to figure out how these all fit together how they relate to each other so we're gonna take a totally different approach we are not going to go through the specs step by step instead we're gonna start by going back in time and talking about why we even have oo auth in the first place so anybody remember this pattern back when like Yelp was brand new this was a very common pattern at the time and this was a new output launch and it would say like okay let's see if any of your friends are already using Yelp please enter your email address please enter the password to your email account we now we understand that this is a terrible pattern right like you don't want to go around teaching users that it's okay to enter their email login in random applications but this was like the only way to do it at the time and it was extremely common even like Facebook was doing this and people would happily give their email password to these applications because they actually wanted the end result of this of this workflow which was that they actually did want the application to have access to their contacts it's just that if you give it your password you're giving it access to everything so we need a way to avoid giving access to your actual email messages but still we wanted to this application be able to access your contacts so ooph was created to solve this particular problem we wanted we want to find a way to let an application access data in an account but only some data and only only without giving it your password right so it turns out that around this time in like the late 2000s a lot of these companies were building api's and everybody had the same problem at around the same time as they're building out api's and developers that these companies got together and formed what eventually became the OAuth spec and the group that now maintains the spec so now when a new app like Yelp launches instead of typing your email password it's you know sign in with Google sign in with Facebook and this is the pattern that we see now all the time the interesting thing though is that this wasn't actually the original goal of OAuth Roth was never actually designed to tell the app who logged in o auth was designed to give access to data so you have like Yelp wants to access your Google contacts or last.fm wants to read data from your Spotify listening history or buffers trying to post to your Twitter account all these things are about accessing API is not about identifying the user I like to think of another analogy of checking into a hotel so when you go to a hotel and you check in to the front desk you give that person your ID card they give you a hotel keycard so you take the hotel keycard and you go to the door and the door you swipe it the key on the door and the door lets you in now this is exactly analogous to an OAuth exchange and what's interesting about this system is that in order for this to work the door doesn't care who you are it does not need to know your name or a unique user ID all it cares about is whether this card has access to this door and that decision is made by the person at the front desk so in autumn the person at the front desk is the authorization server the key card is the access token and the door is the API or the resource server so I bring up this example because I want to point out that it's entirely possible for an API and a system with OAuth to exist where user identity isn't actually even important into the system but of course there are many situations where the application needs to know who logged in and the API certainly needs to know who the user is so it turns out that Roth doesn't say anything about how to do that there is nothing you know that will help you with that solution instead we need something beyond OAuth which is we're open any connect comes into the picture so the other thing to keep in mind about OAuth is that it was originally created for that third-party app access of you know Yelp is trying to access your contacts from Google but it turns out that as the space evolved and as as things are matured over time the Elwha framework actually provides a very good solution for first party apps as well so when you go and visit gmail.com and you click sign-in you don't see a password prompt Gmail does not ask you for a password Gmail actually redirects you to Google's wot server accounts like Google comm and then you go log in there and this has a couple of really really important benefits which is why we use OAuth for a lot of things including first party access as well now which is that notice how there's no password field here it's because some Google accounts don't have passwords because there's many ways you can actually have a Google account one of which is through delegated to a different identity provider so first you enter your email address and then that determines how you're going to log in and whether you're going to do two-factor off so I type in my email address Google then asked me for a password for this account and then it asked me for one of my two-factor off the prompts now the other really important part here is that I'm logging into Gmail in this example right Gmail could care less about whether or how I'm doing two-factor off whether my accounts delegate it to another identity provider and that's really powerful because it means that you have flexibility of consolidating all of your logic into this one os server where that's the thing responsible for authenticating users doing to affect the factor auth and things like that where then you end up back at Gmail and Gmail is happy because it has an access token and that's all I needed in order for it to work so this is the this is the background of why we have OAuth and how it started getting applied into first party apps even though it was originally designed for third party so we're going to take a look at how auth works and talk about go off from the applications point of view first in the second half of this we're going to talk about OAuth from the api's point of view so from the applications point of view the goal of the app is to get an access token it's trying to get that key to someone's account how it gets the access token will be based on what kind of app it is and where it's running so there's a bunch of different Roth flows which will determine how you get the access token the authorization code flow is probably the most common which is used for web apps and native apps there's the device flow for applications running on a device that maybe doesn't have a browser or doesn't have a keyboard so I think like your Apple TV there's also the password flow which is part of the OAuth spec I would argue it's not really in the spirit of OAuth because it does ask if the user to enter the password into the app and there's also client credentials which is for when there is no user involved then you've got like machine to machine communication you just need an access token to access some sort of system level data but the important part is that the end result of all these flows is always the same there is an access token and as far as the app is concerned the access token is just like a hotel keycard it's just a thing that it carries around and it's going to use it to make API requests that access token has no meaning to the application just like in a hotel key you don't care whether it's an RFID or an NFC or a magstripe card or a physical key and you don't care what's on that key you just care that it works when you use it at the door so in OAuth there are essentially these five roles and these five roles are they have specific names in the spec because the spec is you know very picky about how it chooses to name things those names in the spec are not the things that we usually talk about in conversation so the spec names are in the parentheses there you know we usually talk about users not resource owners or devices not user agents but here the goal is that the application the or an OAuth term is the client is trying to get an access token which it can do by getting it from the OAuth server then it's gonna go use the access token at the API how it gets the access token again depends on the flow we're using but it's gonna have to get the user involved somehow so it has to go and communicate somehow with the user using probably their device they're using right so you can start to imagine there's a lot of arrows bouncing around when we'll walk through a couple of those flows starting with the simplest flow which is the sort of foundation of the OAuth flows which is the authorization code flow so in this example we'll start at the top the user is in their browser and they visit the apps website and they click the login button I'm trying to use this application please login the app says great I don't know how to do that but you can go over there and log in there and then they'll tell me when you're not so redirects the user over to the OAuth server that there's a bunch of stuff that goes into that redirect including like the apps client ID identifying it and the scope they're trying of what they're trying to access that's basically the user going over to the OAuth servers saying hey I'm trying to log into this app it wants to access my contacts the OAuth service has great please log in here because I have a password for you please do multi-factor off and then do you approve this request at that point the AA server says great here is a temporary code you can take back to the application that is an authorization code that's a one-time use time limited code that goes back into the browser the browser then delivers it back to the application saying here's the temporary code that the oh uh server gave me you the application can use this to get an access token so behind the scenes then the applications web server will go and talk to the OAuth server again said and saying hey the user gave me this temporary code please give me an access token here's also my client secrets so that you know that I'm actually this real application the audit server says looks good I just issued that code and this client secret checks out so here's an access token and now it can go make API requests so the these lines are colored differently because there are these are two different ways of sending data you might notice the top half of these lines the blue ones always run through the users browser and that the concept of that is called sending data over the front Channel so the the pink lines on the bottom are sending data over the back channel the idea with the back channel is that it is a secure communications channel from a client to a server this is again kind of the normal way of doing things we kind of take it for granted because it's the it's the way that we normally make HTTP requests but it has a really couple of really important properties that the front channel does not have using the front channel is literally using the address bar to send data from one thing to another so benefits of using the back-channel again these are things we usually take for granted because we're just so used to it but when you make an HTTP connection from a client to a server that certificate is verified then the connection is encrypted which means that can't be tampered with and the response that comes back is part of the same connection so the client can trust it it's like hand delivering a message so you walk up you say here is a message you can see that the other person is taking it and accepting it they can verify who you are and everything is happy passing data over the front channel is like throwing it over a wall and hoping they catch it on the other side where neither can see over the wall so in this example the OAuth server is trying to get this authorization code to the application it's really just throwing it over the wall it can't tell whether the applications actually received it or it also can't tell if someone hasn't you know jumped in and stolen it may they're also on the other side of this picture the thing receiving this data all it sees is this authorization code flying over the wall it can't actually tell where it came from on the other side of the wall and this is a really important detail about using the front channel in ooofff is that neither side can really trust that it was successful or that it hasn't been messed with in in-flight so you might say why do we use the front channel at all then if it's this you know this insecure it has a couple of really important benefits one it's how we interact with the user it's how they all us ever can interact with the user to do things like multi-factor authentication it also ensures that the user was there and gave permission for this to happen and is not just relying on the applications word for it and also another another detail is that it means that the receiver doesn't actually need a publicly accessible IP address which it's not that big of a deal in the webserver LAN but if talking about an app on a phone that application running on the phone doesn't have any way for a remote server to push data into it so we use the front Channel to get data into the application so let's walk through an example of this step by step we start out with the application building the link to send the user to to log in so you go find the authorization servers URL you add in a bunch of stuff into the query string that describe the request you're making so response type code is saying doing the auth code flow client ID identifies the application the redirect URLs where the app is waiting for that authorization code the scope is of what the app is trying to access like your contacts state is a random string the app makes up and this is the first of the things that protects the front channel this ends up just being a regular URL and then the the app is this is the login button the user clicks the user lands on the OAuth server logs in approves the request and then is redirected back to the application with the authorization code this is all the front channel steps so at this point the app is just received this authorization code flowing over the fence and says well how do I know that this is from the real OS server I'm gonna check the state parameter that I made up to make sure that it at least came back with the state value I sent that's okay assurance it's not a hundred percent guarantee yet but this is at least one level of of a check and then the sort of closing the loop here is using the back-channel to exchange the authorization code for an access token so the app makes a post request over to the token endpoint this is back to the OAuth server saying here is I'm doing the auth code grant type here's the code I got from the user here is my redirect URL client ID and because this app has a secret includes a secret this is the way that the OAuth server sort of closes the loop and says okay well know that the authorization code couldn't have been stolen because if it was stolen the person the the attacker who stole it wouldn't have the client secret and that way the server case only returns the access token to the real application or if there was some error there's like a way to transmit error codes so this is the sort of baseline a auth flow this is useful for what are called confidential clients which basically means the app has the ability to keep a secret if you notice this flow relies on the presence of the client secret to be secure without the client secret this flow would not be secure somebody could jump in and steal the authorization code public clients are applications that can't keep a secret the easy example of that is a JavaScript app where no matter what you do if you put any API keys into your JavaScript source code that's going to end up down on the user's browser and they can see it by viewing source it's a little bit less obvious but it's also true for mobile apps where the people you know at this one tools available to decompile a binary and look at strings inside of it sure it's a little bit harder but it's still possible so for those applications for browser-based apps and like single page apps and mobile apps you just can't use the client secret which means you can't do the regular auth code flow so if we think back to the off code flow the problem was that the authorization server returns an auth code in the front channel which means the authorization server can't guarantee actually was received by the right application it needs a way to verify that it's not about to return an access token to an attacker which we normally use the client secret for can't use a secret client secret so what do we do instead turns out there is a solution and it's called pixie so pixie is a spec an extension to OAuth it stands for approve key for code exchange and this is the solution for public clients that can't use a client secret let's walk through how this one works it starts off the same the user visits the website and says I'm trying to use this application or launches the mobile app depending on if you're on a browser-based app or a mobile app this app has no client secrets so it says hang on I'm gonna generate a new secret on the fly right now and this is unique per request stores that secret hashes the secret the idea with the hash is it's a one-way operation so even if someone stole the hashed value there's no way to reverse engineer and know what the original secret was so then the app says great go over to the OAuth server and take this hash value with you that causes the user's browser to land back at the OAuth server saying I'm trying to log into this app it's trying to access my contacts and here is this hash it gave me the user logs in approves the request and then the AA server returns that code it remembers the hash value and returns the code back to the browser user takes that code back to the app and now when the app goes to get an access token it doesn't have a client secret but it does have that plain text secret generated at the beginning so it includes that in the back-channel request the server then says ok well I see that you're using this authorization code and when I generated that code there was a hash value associated with it so I'm gonna hash that secret that you're sending me right now and compare them and if they match then I know that the code wasn't stolen so that's the trick for plugging up that that loop of being unable to use a pre provisioned client secret it's sort of like an on-the-fly secret that's new unique per request so that was an extremely quick overview of OAuth clients mostly uh the the OAuth client all the stuff we've been talking about is talking about how clients are talking to servers and getting an access token I want to shift gears now and talk about how the OAuth server and the API coordinate now in a small-scale application like if you're using a built in OS server that's built into your API these are gonna be part of the same codebase so you can just kind of do things however you want but as soon as you start getting into larger scale deployments or using an OAuth server as a service then we need to talk about how these things coordinate there is a really important part here about how we actually deal with the sort of scoping access tokens and and limiting risk and also communicating to the user what's happening so it may see anything wrong with this picture this was an actual example of a sort of OAuth worm that happened a couple of years ago the Scopes here are this application is requesting to read send delete and manage your email and manage your contacts and it's saying that Google Docs is trying to do this which is a little bit fishy what happens if you look at what this little drop-down now this starts to look pretty suspicious right so what happened here is that somebody went into the Google developer console right a certain application called a Google Docs upload to the Google Docs icon and essentially just tried you know impersonated Google Docs as soon as one person clicks this they get an access token with the scope of being able to send email from that users account and read all their contacts so they can use the contacts API pull down their address book send an email to all the people in their contacts list saying hey I just shared a Google Doc with you click here to view it that person next person's gonna click it it's not a spammy milk as it's coming from a real gmail account to a real gmail account that person's gonna click it opening google docs they're gonna see that prompt and then the process repeats it's actually spiraled out of control so fast that Google tweeted this out this was like 20 minutes into this incident and then there was also at the same time this reddit thread unfolding which was fascinating just hit refresh on over and over again because like Google engineers started chiming in saying okay we're trying to figure this out oh we figured it out and we blocked the client ID now everything's fine right so the solution was that they just locked down the client ID used the next time to put anybody clicked that link they got an error page did that actually solve the problem I don't think so because the problem was that users were tricked into clicking okay when they shouldn't have been not that there was any actual vulnerability here in in Google's API or even in OAuth so this idea of scope and getting users consent to these operations becomes pretty important when we're dealing with us because you can see how it can blow out of control here's some other examples of of these consent screens talking about or showing how these servers present information to the user so this is github describing what this application is trying to do I think people would not have fallen for this nearly as much because of two important points one it shows the developer named ahead of time and to that URL they're gonna get something back to you at the bottom is a lot more visible than be hiding behind a drop-down wunderlist does this thing where they show what the app can do and what the app can't do which i think is pretty nice spot of ice is not the best example pretty much you're just going to click the only button with color on the screen and not read anything because it's so small Facebook does this cool thing where they actually say this app will receive this data but you can edit the input you provide to the app and then you can go in and unselect scopes and then Fitbit took that idea very literally and just has checkboxes for choosing what you actually share with the application which this mechanism has been built into the OAuth spec for a very long time but not a lot of apps have actually taken advantage of it so this is scope is this idea of limiting what an app can do what an access token can do for on behalf of a user it's not the way you're going to build a permission system into your API but it is how you're going to mitigate risk and especially around third-party access so the the other half of this is dealing with actual access tokens in your API so I want to talk about access tokens for a few minutes as far as the application is concerned an access token is just a string it doesn't mean anything it's just going to put it in the header and make a request the I on the API side you all of a sudden care a lot about what access tokens mean and how to how to validate them right so access tokens basically fall into two different families your access tokens are either gonna be reference tokens or self included tokens reference tokens are just a way of saying the token itself is R and as a random string and it points to a record somewhere else the simplest example is storing tokens in a database table where you have a column that's the token you have a column for like the user ID and the expiration date and permissions and etc etc there's many different ways you can implement this but that's in a simple example the idea of the self encoded tokens is that the data about the token lives inside the token itself and then it's somehow signed or encrypted or both again there's many different ways you can implement self encoded tokens so the important thing though is if you're building an app you don't care about this difference you're gonna take that token put it in a header and move along if you're building an API you're gonna be receiving these tokens and now you need to somehow verify them and extract data from them and again it is only the API that should ever try to understand access tokens if you're building an application pretend they are just a random string so reference tokens and Suffolk are tokens these are two different ways of handling this and they have trade-offs so there are benefits to both and there are drawbacks to both benefits of reference tokens is that they are sort of very simple if you you store them in a database which means if you want to revoke one or like deactivate in the whole application or deactivate a user account it's very easy you go look in your storage and you delete the tokens that you don't want anymore the next time your API checks whether tokens valid it'll look in the database in the token won't be there but the downside is that it means you have to store all active tokens and if you only have like I don't know 10,000 users or so whatever a database of 10,000 rows is not that big of a deal but if you have millions of users or millions of users and hundreds of thousands of applications that starts to get to be a lot of data also importantly the API has to actually go and look in the database or look over HTTP to check whether tokens are valid which adds latency and sort of centralizes how you can build your architecture so this ends up really only being the best for smaller scale api's especially if there's an integrated OAuth server because then it's just sort of simpler and there's fewer moving parts but these drawbacks start to be a real problem if you're building a larger scale system and then also it's not even really feasible if you're using an external oopps server as a service so stuffings encoded tokens have a couple of really important properties as well they don't need to be stored anywhere because everything about the token that you care about lives inside the token string it means that you can you have better separation of concerns so your API is no longer a need shared state with your authorization servers it also means your API eyes can validate tokens without calling back to the OAuth server that generated them because there's cellphone coded and they say whether or not they're valid right there the downside is there is no way to revoke a self encoded token because the token is a statement about whether it's valid so if you want to revoke tokens you have to sort of add the state back into your system somehow but this doesn't have being the best for larger scale distributed architectures and also using external servers so let's look at an example of this one way to deal with self encoded tokens one way to implement self encoded tokens is using the JSON web token standard it ends up being a very convenient mechanism because there's good library support there is actually a spec working its way through the OAuth group right now to actually standardize this particular token format for access tokens this is an example JSON web token if you look there's two dots in there and if you split in the dots you find three parts if you base64 decode the three parts you get JSON data it's important to note this is not encrypted which means anything you put into the token is visible to the end-user and the application it's just signed it's signed by the authorization server and that is so that you can verify that this token was not tampered with by the application so that K ID property is the key that signed the token the k ID is the identifier of the key so you go into the keys document of the server which you can find in the metadata of the server that JW KS URI says where the keys live if you click on that you get the actual key data and notice that matching K ID property there so your access token comes in you find the K ID of that you go look at the keys of the server you find the matching key and plug it into a library and it tells you whether or not it is valid that's enough to tell whether the jot is valid you then have to make a decision is that enough that's very fast it turns out that math once you have the token cashed it can happen in like a millisecond which is fantastic it means it's super scalable right the downside is that you can't revoke these tokens which means there is a window in which you might be getting the wrong answer there's another option to validate tokens which is to go back to the OAuth server and ask hey is this token really valid so let's look at this example if you have access tokens that last for eight hours and one is issued at time zero and then you you check the John signature it says it's valid you go and ask the OAuth server remotely is this valid you get the right answer you get the same answer now where it goes by same thing then the user goes into their security settings deactivates this application and the ropes now another hour goes by and the app uses the token well if you've done local validation it still looks valid because the token hasn't changed and you can't provoke you can't change that token once it's been issued if you were to go back and ask the OAuth server if as token is valid the OAuth server says no it's not valid because the user revoked it so now you've got different answers depending on how you're validating tokens and you will continue to get different answers until the token expires and then it's you get the same answer again so this is a really tricky challenge because you have to decide what is your tolerance for getting a different answer of whether tokens are valid and both in terms of the functionality of it but also the time window so we end up with end up with the sum this pattern ends up being a pretty common way to solve this where you have a gateway that sits out on the internet and that API gateway is doing only the local validation so it takes like you know less than a millisecond to validate these tokens the benefit is that it's able to throw out junk requests expire tokens you know invalid just junk thrown at it and it'll only pass back to the backend API is things that pass Bala Dacian that does mean that it's potentially passing back requests to these kpi's for tokens that have been revoked for reasons other than the token expired so your what that means though is that at least these api's aren't getting slammed with junk requests from the public Internet so at this point these API is now have to decide do I care whether this token has potentially been revoked or not and the answer is different depending on what the API is doing if you have this customer API that's like returning the user's profile image it's probably not the end of the world if that's also returned for a token that's been revoked probably no new information has been leaked but if you have an API that's going to actually go and charge that users credit card you really don't want that to run with a revoked access token so for that particular operation you can actually go and then do token introspection you add in the latency of what that takes to go back to the OAuth server and ask but then you do get the right answer and that's a way to sort of split the difference of getting the speed benefits but also getting the security of getting the right answer all the time the other thing to keep in mind here is that you have a lot of flexibility in terms of how long access tokens should last you can you can and you can make different decisions based on different again different rules of your system so how long access tokens last are affect how long you're gonna have a different answer for those for those two different ways of validating access tokens so again you can again split the difference and make make decisions based on how your what your tolerance is so you can say Abin users get one-hour access tokens 24-hour refresh tokens they have to log in every day consumer users I don't want to bother so they get unlimited refresh tokens and they stay logged in for 24 hours but then if someone's going to do something sensitive in the system they have only four hour access tokens so you can see there's a lot of flexibility here and a lot of the OAuth the tools and the servers and the products that you'll use give you this flexibility and give you these knobs to turn so I just want to leave you with a couple of links to additional resources and further reading if you didn't already find the author simplified book we have some copies back at the booth oh Ofcom is the eBook version of the book oh I thought comm slash playground is a interactive walk through of all the OAuth flows so you can actually seize that except the exchanges Lithonia again as a community website of OAuth it's a good resource to find related blog posts if you haven't yet signed up for an octave developer account it's a great way to try out this stuff and try out the blog posts and play around in your own little environment there the book is also available at AOL to simplify calm and I will leave it thank you very much [Applause]
Info
Channel: OktaDev
Views: 41,149
Rating: 4.9563637 out of 5
Keywords: oauth, security, api, web, oauth2
Id: PfvSD6MmEmQ
Channel Id: undefined
Length: 31min 36sec (1896 seconds)
Published: Tue Oct 01 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.