What's going on with the OAuth 2.0 Implicit flow?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hey folks I'm Nate Barbettini, product manager here at Okta and I'm here with Aaron Parecki. Thanks. I'm Aaron Parecki. I'm a developer advocate at Okta and also a member of the OAuth Working Group. So I've been seeing the OAuth working group talking about the implicit flow talking about some of the best practices changing around that, I know you're really involved in that so I'm kind of curious what what's going on. Yeah sure thing. So I've been involved in the working group and part of the part of the group that is working on the specific guidance around the implicit flow now and some the changes around that. So it's something that's relatively recently been part of the discussions in the group part of the last couple of meetings of the group as well as discussions on the mailing list things like that. And what what's the impetus for the discussion what kicked it off like is there a somebody find a vulnerability in the implicit flow or like why are we talking about this now? Yeah yeah sure. So there's no new vulnerability or anything like there's no significant event that even necessarily triggered this. It's more that the implicit flow has never really been secure from the beginning and everybody kind of knew that. But at the time we didn't really have any alternatives. So you know think in like 2010 when mobile app platforms were brand new and single page apps were just starting to become a thing right. And --. That's a long time ago. It's a long time ago. We kind of just take these things for granted now. But at that time in that ecosystem browsers worked very differently, and we didn't have a lot of good tools available to browsers at the time to do things sort of properly -- like the regular OAuth way. And because of that people still wanted to do OAuth in a browser based app in pure JavaScript. And so we needed something because you couldn't you couldn't do the regular auth code flow in the browser at the time. For anyone who's not not super deep in the OAuth world why is it that we can't do the auth code flow in a browser or couldn't? Without getting too far down in the weeds, the basic reason was that cross-domain requests were not allowed in browsers for security reasons for a very long time. And as web development evolved and apps got more complicated and people are using CDNs for things and app deployments are getting more complicated, we obviously need a way to do cross-domain and requests and the whole cross-origin resource sharing policies started popping up in browsers and there now are good tools to enable specifically when you want to do a cross-domain post request to allow it from only certain places than others right. So on my server I can say these specific places -- these origins are allowed to make across domain request. Otherwise keep it locked down and you can't make a request. Exactly. Yeah. And the whole the whole way that the regular OAuth flow works is by doing a POST request -- you know the very last step is is the app to the POST request over to the token endpoint with authorization code that it has, and it gets back and access token. That post request, if your OAuth server is on a different domain than your app, then that is a cross-origin and request. Right. And that can only happen if the OAuth server says it's okay. And, prior to the sort of new way browsers are working that wasn't even possible in browsers. Got it. So way back then we kind of said well if you want to do OAuth in a browser based app, we'll kind of let you cheat around the system and you don't have to use a client secret, you're just going to do what we call the Implicit flow and you just use the client ID. Yeah you just use a client ID, and more importantly it returns the access token in the redirect from the authorization server and bypasses that entire second step. So it looks simpler at the surface as well because you know there's fewer steps. It seems more more direct. Just for curiosity why do we have that extra step. Why why don't we just do the simpler route? Yeah. So the simpler route of just returning the access token you know immediately in the redirect -- the downside is that there's more ways that can sort of go wrong. The reason that a lot of the attacks happen and a lot of vulnerabilities happen is because there are a bunch of different ways that that redirect step can fail. If you imagine that like you know the whole way that captive Wi-Fi portals work, right? You're like "hey I'm gonna go to example dot com and then instead you get the captive login page. You're on boingo wireless 2 dot com or something. Exactly. So when the access token is returned in that redirect step, if that's intercepted it's basically just game over at that point, because in OAuth, an access token can just be used by anybody who has. It's called a Bearer Token. Right. So if an attacker can steal the access token they can then make API requests and nobody would ever know that that is happening from an attacker. So we have this extra steps the access token doesn't come back in the in the redirect, we get a code back, and then you have to make an additional request -- a POST request to exchange the code for an access token. I think what what still confuses me and some people is that it seems like if you're not-- if you don't trust the network on the redirect how come you trust the network on the POST request? It seems like it's still maybe has the same problem. Yeah. So it's a it's subtle. As we all know with security there is no such thing as 100% secure. Right. Everything is about mitigating risk and you're playing a numbers game. Cryptography is not perfectly secure. Cryptography is based on the idea that it is very hard to guess numbers. Right? Right. And we use we use large enough numbers where it is practically impossible but it is still theoretically possible for someone to crack it. So the same thing is true here right, where you obviously can't solve everything but you can eliminate the easy attacks. And one of the easiest attacks is stealing that redirect because there's more ways to steal it than there are ways to intercept that POST request. Right. Somebody could... even just logging of URIs that are going by. You could see if the access token is in the URI in the query string or something and somebody is just logging every request that goes through some gateway or something they could even inadvertently capture the access token. Inadvertently for sure. Another great example is browser extensions because that is now code running in the browser that the app developer isn't even aware of. Which are probably allowed to see the address bar. Certainly If you just click "Sure give it all permissions" when you installed it. Absolutely be able to watch the URL and watch for stuff to appear there. Browsers now are more featureful. You can sign into your Google account in your Chrome browser and now your web history is synced to Google, which now means if there's an access token in the URL now the access gets sent up to Google. And then maybe back down to your other computers. Now there's multiple copies of it floating around which are even more opportunities to steal it. And that's all a very different threat profile than intercepting that POST request that the browser makes. Gotcha. So coming back to what's changing -- for a long time the implicit flow is how we did OAuth in the browser. So what is changing? What's the new proposal on the table? So the implicit flow was created in a time where browser security worked -- browsers worked differently and under constraints that are mostly no longer relevant. So the other main thing that has changed is browsers used to not be able to modify the path part of the URL in JavaScript without triggering a page reload. If you're building a single page app you don't want the page to reload if you're modifying the address bar. Obviously as soon as you finish the redirect you want to remove the stuff from the query string. So you want JavaScript to clear that out. Now there is a fantastic API for it, the Session History Management API. So we have all these tools available to us now that actually enable us to do OAuth more securely in a browser which was not true 10 years ago. So the landscape has just slowly evolved and that is the main motivator for this new guidance. Which is that the Implicit flow has always been a -- I don't wanna say hack -- but less than ideal solution. And it's just there wasn't a good story to tell otherwise. Just like well right now this is the best we can do. This is the best we can do right now given the current constraints. Ten years later, tools have gotten better, ecosystem has changed, those constraints no longer apply. So all we needed to do was just to reevaluate the spec and re-evaluate say like hey does this still make sense. And the answer now is no it doesn't make sense anymore. So the other main thing that changed is sort of in parallel to this, the mobile app landscape has been evolving. A little bit of evolution of that since 2010 right. Just a little bit. Yeah. But interestingly also in 2010 the spec was recommending the implicit flow for mobile apps, because it wasn't obvious why -- well you couldn't use a secret mobile apps, we knew that from the beginning. And if you can't use the secret then the implicit flow was a natural way to not use the secret and do the OAuth flow. We call those public clients right. Public clients where you're not -- you can't guarantee that the secret be kept safe. Exactly. Back in 2010, the implicit flow was recommended for mobile apps but then very quickly that started changing and the PKCE extension was developed. So that was something that was created specifically for mobile apps as a better solution to doing OAuth on mobile for all these same reasons. So PKCE kind of fits fits a little gap there which is I can use the authorization code flow which is the two step process where I get a code and then I have to exchange it. But normally that requires a secret. The way PKCE solves it is instead of using a preconfigured secret that's shared across all installs of the app it uses a it makes up a new secret on the fly every time. So it's like a dynamic secret. Yeah. So every time an app wants to initiate the OAuth flow it just makes up a new secret, hashes it, and then does the regular OAuth flow with that additional hash value and gets the access token in the back channel. So the PKCE... can you call it a spec? the PKCE extension makes it possible to securely do the authorization code flow on a mobile device without a secret but still ensure that someone else couldn't intercept the code or steal it from you or try to beat you to getting the access token from it or something. Yeah. So that's been the best practice recommendation in mobile for a couple of years now, right? Several years. Yeah. PKCE is an RFC it's a separate RFC it's an extension to OAuth 2.0. It's been working for several years now it's been in production a bunch of places. So it was created for mobile apps but it turns out it's useful for any public client. Where you can't store a secret but you still want to use the best flow which is the authorization code flow. Yeah exactly. So now what we're seeing is because browsers can make cross-domain POST requests and because they can modify the address bar they can now actually just use PKCE as written with no changes to the spec. No additional spec needed. So the auth code flow plus PKCE is now a great solution for browser based apps. So the proposal in the OAuth working group is basically just -- hey we have this spec PKCE, it works well for mobile, the landscape has changed in browsers, why don't we use it in browsers too, and it turns out there's there's no reason why we can't. Yeah. PKCE is useful in browser based apps just like it is a mobile apps. That is essentially what these two new specs are are saying. Security Recommendations and the Browser Based Apps spec which is the one I'm writing. What a lot of people are wondering is, is this something that we should go out and just go change immediately like should I go. PKCE-ify all of my apps tomorrow? If you have apps that exist that are using the implicit flow, there's no new risks to you. You have always been in a sort of risky situation hopefully you've addressed those risks by doing all the other protections you can against attacks. None of that has changed. So as long as you are doing things properly and have built a secure app and aren't using you know random third party JavaScripts hosted on CDNs from questionable domains then you're probably fine. No need to tear everything out and rip it out and start over. Eventually yes. Roll it into your sort of natural product lifecycle migration that you are going to be doing anyway. Building new apps absolutely use PKCE going forward. Gotcha. So this isn't like a CVE found zero day need to go replace this immediately, but it's something to think about. Yeah there's no CVE for this. There was no vulnerability found. So I guess coming coming at the question from a different way too... If I do switch to PKCE using the authorization code flow in my browser apps, does that mean that my browser app is just 100% secure? Like I don't have to worry about any other security? Is it rock solid? Yeah. Good questions. This is one of the sort of unfortunate things about browser based apps which is that there isn't really a secure storage API in browsers. Which means at the end of both the implicit flow and at the end of the auth code plus PKCE the result is the same. You have an access token. And there isn't a good way to store that in a browser. There isn't a secure way to store it. Anywhere you put it is accessible to any other JavaScript on the page which means it's accessible to browser extensions. And if you have third party scripts on the page that you don't know what they're doing, they could also see that data and PKCE vs Implicit doesn't change that. What PKCE does solve is protecting that redirect step. So it is more secure, but it is not perfectly secure. Because again there is no such thing as perfect security anyway. Until we have a secure API in browsers to store secrets that are only accessible to the single origin or whatever it is, that will always be the case. So there's another thing to keep in mind here which is that this guidance is only really applicable to the situation where you have a pure JavaScript app served by a static web server. So think like hosting HTML on Amazon S3. I've got React loaded straight from my CDN or something. Exactly. Yeah. That server, all it does is send a file to your browser. Right. It can't do anything else. Even if you are using a single page app framework like React and Angular, it is often being hosted and served from a dynamic web server. A lot of times it might be like Spring Boot on the back end or ASP.net or PHP powering the API and then maybe like serving the files. Yeah exactly. And in those cases, you do the OAuth flow on the server where the server is the thing that exchanges the auth code for the access token. And that lets you keep that on the server where you can securely store it and then you just maintain a session to the browser. And that session cookie can be locked down because there are good API for session cookies where you can limit them to not even be visible by JavaScript for example which means nobody can steal it. And that is the most secure way you can do it. Keep a single communication channel from your single page app to your server, all the OAuth is managed at the server and that's where the access token lives and that's the thing making API requests out to your API is that your app needs to hit. So to recap here a little bit. The proposal that you're working on in the OAuth working group is basically plugging one of the gaps that. Something could get stolen before now, can no longer get stolen. That's a distinct improvement in the overall security of your browser based application. Yeah but it is worth pointing out that plugging that gap still leaves plenty of other gaps, like browsers are really leaky browsers are really insecure. Yeah. What are some of the other things that people should be thinking about to keep browser based apps secure? It's things like, make sure you know exactly what code is running on the page. Don't just load random JavaScript from CDNs that you don't know. Definitely use HTTPS, like none of this is secure without HTTPS. Use Let's Encrypt. You can get you get a free cert now There's no reason not to anymore. If you are for sure using HTTPS everywhere set a long lived HSTS policy where it forces the browser to lock onto HTTPS for 6 months or whatever it is because you know your website's always gonna be on HTTPS. Yep. Should people think about doing Content Security Policy on their pages? Yeah absolutely. Have a good content security policy so that you can better know what code is running on the page. There's a whole list of the kinds of things on the OWASP that's. Open Web Application Security Project. Yeah exactly yeah. OWASP and we'll put that on the screen. OWASP. Or maybe this way. OWASP And that is a fantastic resource for web app security. If you are building a pure Javascript app with no server-side component, and you're doing OAuth in the browser, or dealing with any sort of credentials of any sort, definitely read all of that and do all of those things. Well if you got to the end of this video and you're still here, thank you for watching. If none of this OAuth stuff makes sense to you or you're struggling with the jargon check out my video called OAuth and OpenID Connect in Plain English we'll put a link to it down in the description. Also have a fun talk I gave at Oktane 19 about all the different ways OAuth can go wrong, so to take a look at that if you're interested and I've got a blog post which talks about how exactly to do auth code flow and PKCE in a browser. It does not use any frameworks, it is just in pure JavaScript to demonstrate exactly how all these pieces work. Very cool. Thanks for watching.
Info
Channel: OktaDev
Views: 48,132
Rating: 4.9679999 out of 5
Keywords: oauth, openid connect
Id: CHzERullHe8
Channel Id: undefined
Length: 17min 17sec (1037 seconds)
Published: Mon Jun 10 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.