Take a deep dive into some advanced OAuth 2.0 processes and pitfalls like redirect URLs and STATE property. Check out the Book Club episode with Aaron Parecki, author of the book OAuth 2.0 Simplified, and Eric Johnson, Senior Developer Advocate at AWS, where they guide you through some of the main reasons to use the framework, that has already become an industry standard, and what it takes to build a secure web server.
Why is verifying the redirect URL so important?
Aaron Parecki: Confidential clients are going to be things that are deployed on a server, so a .NET app...
Eric Johnson: Okay, so server to server. Okay, that makes sense.
Aaron Parecki: Not necessarily server to server, but it's like when you're writing an application that you're going to be running on a Web server in your own data center, or cloud.
Eric Johnson: Okay.
Aaron Parecki: But you control the environment that the code is running in.
Eric Johnson: Okay, all right, that makes sense. So another one, and you harp on this in your book really well, is the requirement of redirect URL verification. Why is verifying the redirect URLs so important? If I'm building an OAuth server.
Aaron Parecki: A recent requirement in the latest OAuth security best current practice is that redirect URL matching, exact redirect URL matching, is now required. The original OAuth spec didn't require it, it just sort of recommended it. But it is now required.
Eric Johnson: That's crazy talk.
Aaron Parecki: There's two main reasons for it. For public clients the redirect URL is effectively the only confirmation of that application's identity. And because there's no client secret.
Eric Johnson: Yeah, yeah.
Aaron Parecki: There's no password for the app. The only way that the OAuth server and the user can know that this is the real app is by looking at the redirect URL.
So that's one. Without that, then it would be possible for someone to initiate an OAuth flow as a public client using a different redirect URL, and then get that user's authorization code, or in some cases access token if you're using the implicit flow. That’s clearly bad.
The other problem has actually nothing to do with OAuth, it's the fact that any form of open redirector can be used in many different attacks in ways that are very not obvious. An open redirector is when one URL can be used to send somebody to an arbitrary URL. You can use these to chain together attacks where someone can visit a link that is otherwise very nearly legitimate, and then end up on an attacker's website with sometimes very dramatic effects.If you just search for "open redirector," you'll find examples of attacks that have happened that way. And not validating redirect URLs is a form of an open redirector.
Eric Johnson: Ok. Another interesting thing that you call out, and there may be people listening going, "Yeah, Eric Johnson. Yeah, we all knew that." But I didn't, okay? So I'm going to talk about it, and we'll see. It was interesting to me, it's like, "Well, yeah, but I don't want to list every URL that could possibly come from it in my domain." And I'm not proud of this, but that was one of the first thoughts that came to me, I'm like, "I will always force them back to the same one, and then try to figure out some way to redirect them. But that's already built in, right? There's already a mechanism built into this.”
Aaron Parecki: I don't know where you're going.
Eric Johnson: Sorry, I was going to state. Great, I'm leading you well. Yes, that is state. I didn't know about the state, you know, property. Can you explain what the state property does?
Aaron Parecki: Yes. This is something that's actually changing, the recommendations from the OAuth, the recent recommendations, because of PKCE. So PKCE solves CSRF attacks.
Eric Johnson: Right.
Aaron Parecki: If you implemented PKCE properly, then that attack is solved. It used to be the case that state was the solution for a CSRF. And without PKCE, State is absolutely required to prevent CSRF. However, PKCE does it better. Once you're using PKCE for that it actually frees up the state parameter to do what you're talking about, of sending the user back to different parts of your app.
There is a single redirect URL in your application and it's sort of like this is the route that's going to be catching the response from the OAuth server and finishing the OAuth...
Eric Johnson: Right, every time.
Aaron Parecki: Do you want to send them back to the home page or their profile page or their notifications page or the shopping cart, the checkout page, right? So you need to figure out how to send them there, and now you can use state for that. You can just basically put in a string in your state that's like "shopping cart."
Eric Johnson: Yes.
Aaron Parecki: And now I do want to mention that don't build an open redirector yourself, right? Don't allow yourself to redirect to arbitrary locations by using the state parameter.
Eric Johnson: Ok.
Aaron Parecki: You can still have an explicit list of allowed redirects that your applications can redirect with. Otherwise you're building...
Eric Johnson: I hadn't thought of that. So don't build a hole in your own security system. Ok.
Aaron Parecki: Yes. So if you do redirect URLs, then you just need to make sure you have your own explicit list of URLs that are allowed.
Eric Johnson: Yes, that's a good call out, I had not thought of that. When it comes back and it asks me to redirect, I'm going to verify that it's one of the allowable redirects in an array of redirects that I allow. So ok, very cool.
Aaron Parecki: You can use the state parameter to send the user back somewhere without having to have the state parameter have randomness in it because you're using PKCE, which solves CSRF.
Eric Johnson: Ok, got you. Now I'm just thinking out loud, I'm off script here. Could you use PKCE to... Let's say if you encrypt the string, because in PKCE you're creating a string, could that string contain the redirect?
Aaron Parecki: Interesting.
Eric Johnson: Mark that down, someone write that down, Eric Johnson said something interesting.
Aaron Parecki: I'm going to have to think about that.
Eric Johnson: Yes.
Aaron Parecki: There are some interesting implications I have to think through.
Eric Johnson: Yes. You've got state, it's there, but I was just curious. You know, would that be something? Because that's related to that request, specific to that request.
Aaron Parecki: It would have to include enough randomness still.
Eric Johnson: Right. Now, I get that.
Aaron Parecki: The PKCE challenge, or verifier, has to be a certain length, it has a very specific length.
Security considerations as a user and server administrator
Eric Johnson: Ok, that makes sense. So let's jump here on, you know, on one more. We're talking about security, talking about how we kind of lock things down. There is some security... If I do decide to build this serverless OAuth server, which it may happen, and we'll push it out there. I'm not looking to replace anything, but I want to say, yes, I understand how to build that. But there are some security considerations I need to look at. I want to ask about a couple, maybe have you kind of explain it and how we fight that. The first is phishing.
Aaron Parecki: Yes, OAuth phishing is definitely a real thing, and it's becoming more and more prevalent as people are solving traditional phishing. Traditional phishing is becoming harder because we've done a good job of upping the security of these things.
Eric Johnson: Sure.
Aaron Parecki: And now moving to OAuth phishing. The idea with OAuth phishing is that it's not actually an attack on the spec or finding a flaw in the server, it's actually, like any phishing attack, tricking people into doing something. It's tricking people into authorizing a real application to get access to their data, where that application is created by an attacker. It's not even, like, trying to mimic a real application or anything like that, it's just like there is some application registered and someone accidentally authorized it to access their account.
There was a very large example of this a couple years ago with Google.
Eric Johnson: Ok.
Aaron Parecki: It had ripple effects through a lot of the ecosystem of applications that use Google data, like use Google APIs.
Eric Johnson: Sure.
Aaron Parecki: It was called OAuth phishing or an OAuth worm, or whatever you want to call it. But it was effectively that same problem, where someone went to the Google Developers site and made an app and gave it the name Google Docs, just typed that in when they registered the app, got real credentials.
Eric Johnson: Oh, wow, okay.
Aaron Parecki: Then it started the real OAuth flow. If you send somebody a link to log in, that starts an OAuth flow. If they finish the OAuth flow, that app, that real app, gets real access tokens so it can access their data.
So there's no, like, hack. Right? It's just tricking someone into clicking this link. They would spread this by sending an email saying, "This person shared a file with you, view it in Google Docs. Open in Google Docs." Clicking that link would start the OAuth flow to this fake app, the attacker's app, which would say, "Google Docs is trying to access your Google Drive," or whatever. And then all of a sudden the attacker's app can now access all of your data. One of the scopes it also asked for, one of the permissions it asked for, was the ability to send email from your Gmail account.
Eric Johnson: Oh, wow.
Aaron Parecki: So then it could then go to your Gmail account and send an email from you to everybody in your address book with that same message. It just spread super quick.
Eric Johnson: That is maliciously brilliant. I mean it is.
Aaron Parecki: It didn’t do anything really, but it was an effective demonstration.
Eric Johnson: Ok. So if I'd have gotten that. Let's say this a couple times. Anything that asks to send email for me, that's a red flag. Right? Would you agree? Yes. So that's a red flag right there. The first thing, I guess, if we were to fight this, the first thing I would do is look closely at what it's asking to do. How many times do we just go "authorize, authorize, authorize"? It's like signing contracts without ever reading. Right? And so we really need to get that in our head that, I mean, this is your information, read everything. Right? What else could we do?
Aaron Parecki: It is so important. So that dialog that says, "This application is trying to do this, this, and this."
Eric Johnson: Yes
Aaron Parecki: The design of that page is very important. Because if you pack too much into it, people often will just skim it, glaze over, and click the big green "go" button, right? And if it doesn't say enough, then you may not actually know what the full implications of that are. There's this balance you have to strike. That's why designing that page is so hard. This is one of the reasons why making an OAuth server is so hard, because you have to get that right, otherwise you're going to find yourself being in the middle of a phishing attack.
Eric Johnson: When you were listing here's the things you saw in this, this is very detailed. When you said that, it was like, "Okay, that really clicks." Because I don't want to be responsible for having something open up like that. So very interesting.
Aaron Parecki: Clickjacking is actually mentioned in one of the earliest security specs in the OAuth group. The idea with clickjacking is basically you can have a web page and then if you have another web page embedded in it in an iframe and someone is trying to click, type in their password or click a button that says "okay." If you put something else over that where they can't actually see the iframe, you can do it in a way where the clicks, like, bubble through.
Eric Johnson: Yes.
Aaron Parecki: The idea of stealing a click where the user thinks they're clicking on something, but they're actually clicking on something else.In OAuth the idea is that you would iframe in an OAuth page that's trying to grant access to this user's account. Then over it you would put, like, "Download free wallpapers for your phone," right? Click the download. You click the download button over the "ok" button. Then when they click it, it actually goes through and clicks the "ok" button, and then they don't even know that that's happened. But thankfully I feel like this is not super relevant anymore because most OAuth servers at this point don't allow themselves to be iframed in, which is the real problem there.
Eric Johnson: Ok. All right, yes.
Aaron Parecki: They'll pop themselves out of the iframe. There's many other reasons why iframing in an OAuth page is a terrible idea, actually any login page.
Eric Johnson: Yes. Iframes in general are a bad idea. Just my opinion, but yes.
Aaron Parecki: Generally they just cause a lot of trouble.
Eric Johnson: Yes. So as a user, is there any caution you would give me? I mean is there any way... And I agree with you, it's probably a pretty edge case now. But is there any way I can tell?
Aaron Parecki: Clickjacking?
Eric Johnson: Other than inspecting the code.
Aaron Parecki: Not, I don't think so.
Eric Johnson: Yew, that's a tough one.
Aaron Parecki: That's a tough one. But I also feel like it's not even that important anymore because mostly OAuth servers have solved that themselves. The phishing is the one that you need to be aware of because that is something that the only line of defense is the end user there.
Eric Johnson: Once again I would say treat the "accept" button as writing your signature and read everything before you do it.
Aaron Parecki: One of the things Google has done to address that, that worm, that phishing attack, is changing a lot about their OAuth flow. They've done things like if an application wants to be able to send email, they actually have to go through a very expensive vetting process, approval process.
Eric Johnson: Ok, all right, good.
Aaron Parecki: There's a handful of other scopes of these new types of access where the application has to go through manual review, as well. The email one is sort of, like, extreme, but there's, like, Google Drive and things like that where there's, like, potentially sensitive data there, they have to go through a pretty extensive review process, as well. Even now just registering an OAuth app at all if you want it to be used by anybody besides yourself, you have to at least go through a minimal approval process now.
Eric Johnson: So there's some vetting going on, yeah.
Aaron Parecki: It used to be you just show up, register.
Eric Johnson: "I'm breathing, give me access." We talked about redirects earlier. The last one, the last kind of security — or probably not last, but the last one I've got on here is redirect URL manipulations. We talked about redirect URLs, but what do we watch for in that?
Redirect URL manipulations
Aaron Parecki: I guess the last trick with redirect URLs is in the mobile apps. So with Web-based redirect URLs we have the advantage of DNS and HTTPS certificates to do most...
Eric Johnson: Right, right.
Aaron Parecki: So if the OAuth server is about to redirect the user out somewhere, there's a pretty good guarantee that it's going to work because generally browser security prevents those attacks of, like, the coffee shop Wi-Fi taking over.
Eric Johnson: Sure.
Aaron Parecki: Because we've got HSTS and all the certificates and all that stuff now. On mobile it's a very different story.
There is this concept of app-claimed URLs where there's some form of verification the developer of the app has to do to prove they own a URL that can be claimed. But there's also the custom URL scheme model. And custom URL schemes have no registry. So instead of "HTTP://", you do like "example" or "todo://" as your redirect URL scheme for your mobile app, but there's no registry. So any app can claim any of them. Which means any app can pretend to be any other app in that sense.
Eric Johnson: Right.
Aaron Parecki: So for both the redirect URL does not act as any form of identity verification. Whereas in the HTTPS world it acts as a minimal form of identity verification.
Eric Johnson: Ok. You cover quite a bit of that in the book, on mobiles and how to cover that. I know we can't go into that here, but there's extensive coverage of that and I appreciate that. I didn't even know about it.
Key Takeaways from the book
It's been a great conversation. The last question I have for you. Once I read this book and talked with you, there's a billion questions I could ask. So we're best friends now, so prepare for that. What are some key takeaways that you want users to have, or readers to have? If you say, "If nothing else, I want them to understand this," what would you say?
Aaron Parecki: I would say focus on learning the authorization code flow with PKCE because that's just the default most secure way for the most different kinds of environments. Also, OAuth is not as complicated as you think it is.
Eric Johnson: Yes.
Aaron Parecki: There are some complicated parts, but it's not as bad as you think and it's worth learning a little bit in order to actually understand what's going on. And don't build an OAuth server.
Eric Johnson: Don't build your own. There's plenty out there and they're doing it well, right? So yeah, now, I agree. But I'm still going to do a serverless one maybe, we'll see. I'm not going to publish it or anything, but I just want to see if I can do it.
I will tell you, and I know I said it already, but the book really opened up some of the questions I had. I was surprised that there is some flexibility in the spec and that it could kind of be user-dependent sometimes, or server, you know, whoever built the server. But it is a lot simpler than I thought, or it's not near as complex as I thought. I think sometimes we just don't explain it well and your book fixes that. So I really appreciate it, I really appreciate your time. I want to know where I can order that shirt. Obviously bigger than that one, so, you know, you'll have to send me a link and I'll order. Yeah. That's a cool shirt, so.
Aaron Parecki: I don't have these up anywhere yet, actually.
Eric Johnson: Aw.
About the authors
Aaron Parecki is a Senior Security Architect at Okta. He is the author of OAuth 2.0 Simplified, and maintains oauth.net. He regularly writes and gives talks about OAuth and online security. He is an editor of several internet specs, and is the co-founder of IndieWebCamp, a conference focusing on data ownership and online identity. Aaron has spoken at conferences around the world about OAuth, data ownership, quantified self, and home automation, and his work has been featured in Wired, Fast Company and more.
Eric Johnson is a Senior Developer Advocate for serverless applications at Amazon Web Services and is based in Northern Colorado. Eric is a fanatic about serverless and enjoys helping developers understand how serverless technologies introduces a major paradigm shift in how they approach building and running applications at massive scale with minimal administration overhead. Prior to this, Eric has worked as a developer, solutions architect and AWS Evangelist for an AWS partner company.
If Eric could be a Chief Happiness Officer, he wouldn’t have to do anything but show up as he is.