← All talks

OAuth2: Beyond The Specs

BSides Lisbon · 201833:27363 viewsPublished 2018-12Watch on YouTube ↗
Speakers
Tags
CategoryTechnical
StyleTalk
Mentioned in this talk
Protocols
About this talk
Pipedrive's journey from API token authentication to OAuth2 reveals practical implementation challenges that specifications don't address. This talk covers OAuth protocol fundamentals, real-world deployment differences across platforms, CSRF attack prevention via the state parameter, synchronization pitfalls with refresh tokens, and webhook management for multi-app ecosystems.
Show original YouTube description
What if you roll out OAuth, and realize there are a bunch of small things you didn’t consider? It’s what happened to us at Pipedrive, and although it’s likely not over just yet, we’re running smoothly. It’s a good time to share what we’ve learned and save others some time. While building Pipedrive’s marketplace for third-party apps, we transitioned from API token authentication to OAuth, and it’s been an interesting learning experience. In this talk, I will explain how the protocol works, discuss differences in how OAuth is implemented on different platforms, and explain how we managed the transition from API token to OAuth. I will explain how CSRF attacks work in OAuth, how the state parameter can prevent them, how to manage synchronization between server and clients, and what you can run into when you roll out OAuth for dozens of apps.
Show transcript [en]

this working oh yeah okay okay hello everybody how you doing hope you had a nice break so I'm very happy to be here my name is daniela working developer relations at piledrive and i'm here today to talk to you about off who here is familiar with all in raise your hand okay some so the idea is I will explain a little bit what it is how it works and then I will share some things that we learned in five dryable implementing go out and while releasing it for our market base all right sounds good okay so just to give you a little bit of context this is Estonia is where my tribe was founded it's a country known for the

cold weather and the cool software companies and pipedrive is one of those yeah thanks and was founded in 2010 we have over 80 million in funding now we are more than four hundred people working in 5dr and this is some of the people from the Estonian offices so what do we do my drive is not a security related product we're actually a CRM for sales people that we have some cool features you can see some here we focus a lot on activities we try to make everything very easy for sales people so that they can focus on the on the things that that that that they can control in their sales pipeline all right so why am

I here talking about oh wow one thing that we know is that it's impossible to create a CRM that covers a hundred percent of every possible need that salespeople have so that's why we created a marketplace which is a space where other companies and other developers can create apps that work with pipedrive to cover those needs that salespeople have the we don't don't cover natively okay and this is where I come in the picture again my name is Daniele and what working in developer relation means that I talk with these developers I talk with these companies and I try to make their lives easier so if there are something to to to improve with our libraries I work on that

or to some support and one of the the main topics that that comes up all the time is because it can be tricky sometimes so the idea for this presentation is I will try to explain it in the easiest way possible so that I'll say some of you some time when you have to deal with it in the future so let's start with the definition well is an open standard for access delegation and what does that mean so if you're a user of any platform you have access to some private resources through a password okay now what happens if you want to share some of these resources with someone else with a third party platform

the way it used to work before off was released back in 2007 or so looked like this so you would share your password now I don't think I need to explain at a security conference why this is a bad idea but aside from the obvious reason that you don't want to give all that access to someone else there's something else more practical maybe in a way Kenny anybody has some ideas you can just shout it out no one so there's another thing if if I share my password with ten people it's very it's impossible for me to revoke access to only one of these because if I change the password I revoke access to everybody and if I

don't change the password everybody still has access okay so it's not the the best best approach a better way to handle the to handle this is by delegating the granting of permission to to something else which is the off server which acts like a bouncer and sits in the middle between the the private resources and the third party platform okay so based on rules that the user decides it can grant permission to some of these platforms and deny permission to some others so in our in our example in in our case when a user installs one of these applications there are there are prompted with a page that says hey this application needs to have

access to your contacts your deals your activities or your credit that if you are installing the application has anybody ever done a log in with Google or Facebook okay I thought so it's basically the same thing and oh that's that's built on off there's a piece of protocol on top of it it's a different protocol it's called Open ID Connect but it's basically the same thing the concept is the same and so the application is installed so the private resource is the pipedrive account the the guest in this example is the client application for example asana and the bouncer is the the authentication server so we didn't always have all if I Drive like many

other companies and platforms that provide an API we started you we started with API tokens do you know what an API token is what an API key is okay good so it's basically like a password it's just a string that you can include with all your API calls it's just an extra parameter and it's all you need to start using an API it's very fast and easy way to start using the API and it's especially if you're trying to build something internally like for your own company it's it's not the best solution if you want to share the application that you are creating with the whole world because for a few reasons first of all it's complicated for the final user

because if you develop an application then users API token and I want to use it I need to go to my pod apply Drive account copy the API token come to your platform and paste it so it's kind of not the best user experience and again it has the same problems that sharing a password has you're giving access to everything and again it you cannot revoke access to only one of these these platforms all right with all on the other hand is very easy for the final user to start using your application because the installation is very easy it's just one click and you can defy fine you can define scopes which means you can define certain

subsets of resources that your application needs to have access to to work okay so yeah and and and so the user when they install the application can see what kind of data you need to have access to they're much more comfortable with it and it's much more likely that they will give your application a shot all right so let's see how the product works we'll focus mainly on on the authorization code flow there are four different variants of all this is one this is the the variation that is used every time that you're dealing with marketplaces and applications whether it's for pipedrive github Spotify or whatever so there are a few actors involved there is the final user there

is a client which doesn't mean front-end or browser it means the client application is still a server for example asana there is an authentication server and the there is a resource server now these two they could be two different service servers could be one server could be a complex architecture the first simplicity I'll just call this pipe drive alright so the goal of the whole of flow is for the client to have access to the user's resources and how does does it do that using what's called an access token the first access token is exchanged for what is called an authentication code and we'll see that I would see how it works and then every once in a while the

access token expires so the client needs to what's gonna refresh it refresh the term refresh is a little bit ambiguous there's nothing that's being refreshed really you just ask for a new access token but that's what it's called so first step the page that we've seen before the client ask the user through the server can I have access to your your data if the user approves the server redirects to the client with this authentication code the client it receives the authentication code and can exchange it for the first pair of access token and refresh token and so it can now use this access token to make API calls for example to get a list of

contacts or anything else and then after a while the access token expires and the client needs to request a new one using the Refresh token okay are you with me so far cool so let's see how what what calls are actually made a little step back every time you are dealing with an authentication flow you need to first register your app which means you need to create it on on the the platform that you're using in this case PI Drive and you type in some some data but the most important thing is the callback URL so this is you're telling the server where the user should be redirected after they approve the installation okay and also the list of data that you need

to have access to and what kind of access is it read-only is it write read and write after you create the the application after you register it you get you are given a client ID and a client secret and this is how the server can identify the application so the user installs again it's prompted with this with this with this page but if you take a look at the the URL bar right there you can see that you have the client ID that we just talked about and the redirect URI so where should I be redirected after installing this application and install and voila I'm redirected to this very ugly client right now but it's just to

show you what's going on I'm redirected to the client see this is the redirect URL plus I have this code right now it's the authentication code the first of the from so everything so far is visible is on the browser it's on the front end so you can see everything that's going on from this point on what the calls that are made are server-to-server so are there hidden from the from the user postman anybody uses postman okay it's just a tool with a very cool visual interface that you can use to make calls HTTP requests and so on you can do more with it but this is what I use it for so the first call

after getting the access token the authentication code you need to request the first access token okay and this is how the call is prepared he needs to be authenticated with basic owl so you need to have user name and password which will be encoded in base64 in the in the actual final request and in the body of the request you have grant type authorization code in this case code the authentication code that has been generated by the server and the redirect URI just for just a double check the names of these parameters can change from platform to platform but the concept is is always the same you send the authorization code and you get the first access token so

you send a request and this is the response again the the parameters name could names could change but you still get an access token and usually a refresh token we'll talk about it so this is what you get you you receive an access token a token type that is usually bearer in how many milliseconds the access token will expire and the Refresh token so you will you will need to use this one when you want to request a new access token and you also get a list of resources again that you can have access to so you receive the access token and you can use it to make API calls and how do you do that you just

included in the header with bearer space and the token in this case postman does that for you here I'm just making a we'll get requests to get the deals of my account and voila okay it's very very simple to use it then it expires you need to refresh it and the the request is very similar to the first one that we've seen it just what changes is now you have grant type is refresh token and refresh token is a refreshed order and you get a new access token now if someone has very good eyes maybe you notice that in this case the Refresh token that you are sending it's actually the same to the one you are receiving so

why is that does anybody have any idea if you guess it correctly I I'll buy you a beer or something it's tricky so the truth is that when you when you read the specifications of wow this is what it says it's it's it's optional to to reissue the Refresh token so it's up to you when you are implementing the alt server to decide if you want to if you want your user to use always the same refresh token forever or every time the user fresh token you Rishon you want so it will basically basically be a one use only refresh token and in part drive we started reissuing refresh token in the beginning and so all refresh tokens

were just one use only and we started having some issues with developers using our our flow because they were not used to this thing they were contact contacting us saying we're having issues with your health it's not working refresh tokens are not working what's going on so we started looking around we asked ourselves what do other platforms do so this is this is how what drive used to work so first time you get a refresh token second time you get a different one then you go and look for example to Spotify this is the response to the first request you get access token and a refresh token but then when you use a refresh token this

is what you get you only get an access token so what does that mean it means that the same Refresh token can be used more than once you can always use the same Refresh token then you look someone else right github and this is the response to the first request you only get the access token you don't get Refresh token at all so that single access token lasts forever yeah and so as I said we started racially refresh tokens but we thought it probably should be more secure right it makes sense but it turns out that maybe is more secure I don't even know but it definitely adds an extra layer of complexity that is it looks not so

complex but developers turns out are not used to it so you get a lot of support requests and failed a refresh token requests so after changing this after stopping reissuing refresh tokens that the situation got much better and we left the in the in the response that we are sending still the same refresh token Jess not to break those that already had the the implementation correctly and they were updating the refresh token every time okay makes sense so this is something cool to - something important to keep in mind if you're implementing or not server I would suggest don't reissue the Refresh tokens one final thing before closing the chapter this is a custom endpoint that we created in pipe drive

and it's an endpoint that's used to exchange an API token with the first pair of access token and refresh token so again if you have your implementation using the API token you can use this endpoint and exchange it and for me it would resolve it would look like an app that I already installed okay we did this because we had a lot of integrations built with API token and we wanted to help them transition to actual app using the off flow we can talk more about if you're interested but so this is what we've covered so far do you have any questions at this point before we move on yeah go ahead you get access what happens if

a password leaks it's the same yeah you can you can revoke the token so yeah so if some if again because you have different access tokens for everyone you can revoke just one so if you if you find out that there there has been a leak you can just revoke that access token and make the user go through the whole flow again to request a new access token make sense yeah so I think I got the question so the the the thing is if my access token leaks okay that means that someone else is using it is using the the access token that should be my own right so you the server you can decide to revoke that access token and

for me it will look like the application has been uninstalled so I cannot use that application anymore to start using it again I need to go through the whole authentication the page that says do you want to install this again I need to go through the whole thing again and you get a new access token okay but what if what instead of all going through the whole process you just issue ask for a new and your token with the Refresh token so if the refresh token leaks no no if you if you leak the access token the simplest way is to have the Refresh token working so the client could just use the Refresh token to get a new one yeah if they

aren't you if you if you aren't implementing this is mandatory to have the the Refresh token working it won't work this make sense yeah so you're saying that you can request the new access token using the Refresh token yeah yes it just depends on who is doing like if the client finds out that there's something wrong with one access token he can refresh and get anyone if if instead you want to just revoke the whole the whole thing refresh token an access token the user needs to go through the whole process again but you say that the Refresh token you weren't using the Refresh token because it was giving the developers problems well go ahead maybe

someone can can the the call for a refresh token includes the access token as well right sorry the the call for the refreshing token also includes the access token if the access to no revoke it doesn't just refresh so just to refresh token I don't know if I answered totally but maybe we can talk about it so i share quickly some things that we learned while dealing with many apps and then we'll take a look at cross-site request forgery attacks in this protocol so talking about synchronization with the clients let's talk about web hooks do you know what a book is okay so web hook is is just a fancy name to describe a URL on the client that the

server can call every time that something is triggered it's just the trigger something happens the server also URL on the client and sends probably some data why do we need weapons what what are they used for what's the problem so when you have a client and a server dealing with data often what you want to do is to keep the data synchronized in some way so if something happens on the server you want it to be mirrored on the client okay how do you achieve this the old-school way of doing this looks something like this you would set a timer on the client and every once in a while you go and check what's going

on the server so you go you check what's going on in the server you find some new data and you download it on the client then you set the timer again something else happens on the server but you don't know it yet because you still are not locating to that then you go find out what's new on the server and you copy the data ok it works but but of course you are making unnecessary calls because you are checking all the time even when nothing happens and the data is not updated in real time so with the web hook you reverse the whole thing so simply when something something happens on the server some new data is created

for example is the server that sends the data back to the client ok so so you just do the minimum amount of calls necessary and the data is always updated in real time so it's not the only application that you have for web hooks so let's talk a little bit about uninstallation and trial explorations what's the issue when a user installs an application the client starts making some request some API calls and the server checks if everything is looks good or not and the the request can be approved or rejected ok when the user uninstalled an application or the trial the trial expires or something else happens this is what the situation looks like you

have all the requests are rejected because that client should not have access to anything anymore all right but what's what's the problem the problem is that the client has no no way of knowing that like on its own so it will keep trying to make this request which will be rejected so how do you solve it with a web hook so when the application is uninstalled you send back to the client hey you've been uninstalled stop making requests ok and also you should provide an end point for revoking the access token from the client so if for example the app is a paid and user stops paying the application should be able to uninstall itself okay

so this is another end point that should be provided similarly when an app is installed it can create it can create its own web hooks so we can say hey server every time that something happens I want you to send the data back to me and again what's the issue if the app is uninstalled all the requests coming from the client are rejected again but if you don't do anything else you have you still have data going from the server to the client okay so it's very simple again you just need to remember to delete these Web books and the this could look like obvious things but it turns out sometimes you don't you don't

figure it out until you are dealing with many many apps and many many requests all right so this is the the kind of the final chapter and I wanted to talk about this because it's something important to understand but it's not always clear for all developers how did how cross-site request forgery attacks work in this protocol and how you can prevent them using the state parameter and it's not clear for everybody because sometimes so yeah so first of all what is to say the state parameter it's a it's a an optional parameter per specification that you can include in the flow and it's a parameter that can prevent that kind of attacks it's just a string that

is bounced back and forth between the client and the server the server sends it back to the client as it is it doesn't even touch it you can see here there is the the URL that we've seen before with the code plus state parameter and it's not certainly clear always how this work because if you google and try to understand it on your own you you you sometimes find websites that say things like if you don't use the state parameter an attacker could gain access to a victim's resources which is kind of true but it's not precise it's it's a bit more clear if you read the specification so the important bit is the last part so

it says that is the victim that can be tricked into saving their own private data thinking that they're saving it to their own account but instead they're saving it on the attackers account okay so we'll see how normal flow works we'll see how the attack works and then we'll see how the state parameter can prevent it in our normal flow just to recap the user installs the application the authorization server generates an authentication code that's linked to that specific user the user is redirected to the client with this code exchange is the code for an access token that's also linked to that specific account and then the client can use this access token to make API calls for

example to send in a new lead okay that ends up on that specific account because that access token is linked to that account okay so how does the attack work the attacker starts the process just like any other user yeah so they approve the app an authorization code is generated on the server but at this point instead of being redirected to the client with this code they interrupt the request as we seen before it's just a URL right so you just take that URL and you have the victim go to this URL instead of them and this can happen in a number of ways it can be in a malicious email it can be hidden somewhere iframes

images so on so let's see what happens the client goes to the the the user goes to the client with this authorization code that's linked so the attackers account is exchanged the code is exchanged for an access token and now the client that the user is sending the new then the the the data through the client using an access token that's linked to the attackers account okay and so this is how the data ends up actually on the attackers account alright so how do you solve this using the state parameter the state parameter is generated by the client and it's a string that identifies uniquely that specific session which means that specific user okay and and this parameter is is passed with

each step of the phone so when the user is redirected to the client with this code there is also a state parameter that identifies it's me it's the same it's the same session okay and in the same way the attacker has a state parameter that's linked to its own their own account so now if the attacker tries to have the victim go to this URL instead of them well it's very easy now for the client to see hey the the session that is making the request it's not the same of these state parameters that I'm receiving so there's something fishy going on and the the request can simply be rejected this is something that it is is optional also in piledrive

because it's optional per specification I don't think we ever enforce it but if you are developing an app using the OAuth flow it's definitely recommended that you use it I don't know why it's optional honestly the specifications maybe someone knows can tell me but yeah it's definitely recommended that you use it we've talked about a few things do you have any more questions was it clear enough yeah for those who are new to the whole thing yeah shy audience it's cool if you have any more questions anyway I'll be around you can you can we can clarify that the thing is well thank you for your attention guys thank you for there is there is a question Hey and not

really a question I was just going to say that that state parameter yeah I've seen it used as a way as a way to basically pass information through the OAuth flow so basically let's imagine that you you can come from two different places so I've seen clients pass random stuff into the state saying homepage or yeah yeah and basically yeah not not utilizing the the code as it used to be or simply ignoring it like getting CS RAF error and well what is this and simply ignore the kill because it was breaking the oil flow it's simply say again simply broke when it breaks since since the basically imagine that you were using a client

that would make the verification of the code for yourself mmm-hmm and it was breaking so then clients would simply pass ignore states ignore state option and and in that way it would work okay so basically clients don't know what the code does so but yeah if you ignore it is it for something else yeah so as I said it's just it's Ramat the server is doesn't do anything with it it just sends it back so yes it's up it's up to the client to decide how to use it and this is how it should be used to prevent this kind of attack but yes it can be used to just know for example where the user was what

the user was doing before they went to the the home flow so that they can restart from the same point or something like that it should should be used for if you want to do that you can do you can do it it's probably a good idea to do both things so you generate a string that has the information of what you were doing at that point and also has a way of identifying that the session but yes it's totally up to the to the client yeah

rock n roll thank you very attention guys thank you for having me