<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zai Shi</title>
    <description>The latest articles on DEV Community by Zai Shi (@fomalhautb).</description>
    <link>https://dev.to/fomalhautb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1336006%2F8c779346-909a-46f3-a8ad-802fc36d82a3.png</url>
      <title>DEV Community: Zai Shi</title>
      <link>https://dev.to/fomalhautb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fomalhautb"/>
    <language>en</language>
    <item>
      <title>I finally understand OAuth 🤯🤯🤯</title>
      <dc:creator>Zai Shi</dc:creator>
      <pubDate>Tue, 24 Sep 2024 01:58:41 +0000</pubDate>
      <link>https://dev.to/fomalhautb/i-finally-understand-oauth-2ldf</link>
      <guid>https://dev.to/fomalhautb/i-finally-understand-oauth-2ldf</guid>
      <description>&lt;p&gt;Let’s be real — OAuth can feel like a mystery wrapped in an enigma. The general idea is simple enough: “Authenticate users, good things happen, everybody’s happy.” But then you look at the details, and suddenly you're buried in a bunch of seemingly random parameters. Every tutorial online is like, "Just use this," but no one really explains why all these things are there! 🤔&lt;/p&gt;

&lt;p&gt;I was in that boat for a long time—until I started building my own authentication library. That's when I had to dig deep into the nitty-gritty, reading through hundreds of pages of OAuth specs (yes, it was as fun as it sounds 😅). But you know what? After all that, I realized OAuth is actually super logical. Every parameter is just to prevent one or more types of attacks. 🛡️&lt;/p&gt;

&lt;p&gt;In this article, I’m going to start with the simplest "auth" flow you can imagine — sharing your passwords. From there, we’ll tackle each vulnerability one by one, securing it step by step until we arrive at the full, secure OAuth flow you know and love (or maybe just tolerate).&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack Auth: Open-source Auth0/Clerk Alternative
&lt;/h2&gt;

&lt;p&gt;Before we dive in, I want to quickly introduce &lt;a href="https://github.com/stack-auth/stack" rel="noopener noreferrer"&gt;Stack Auth&lt;/a&gt;, the open-source authentication library we’re building. It’s designed to be super easy to set up and offers a beautiful set of UI components right out of the box! Whether you’re building a SaaS product or your next side project, Stack Auth simplifies authentication without compromising on flexibility.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/stack-auth/stack" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkvs5nw28w741w78hvbcz.png" alt="Stack Auth"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The world without OAuth
&lt;/h2&gt;

&lt;p&gt;Big Head wants to save storage space on his Hooli Cloud drive. He finds Pied Piper, an app that promises to compress his files. But for Pied Piper to work its magic, it needs access to his Hooli drive.&lt;/p&gt;

&lt;p&gt;The simplest way for Pied Piper to get that access is to ask Big Head for his Hooli username and password. With those, Pied Piper can log into Hooli on his behalf and access his files.&lt;/p&gt;

&lt;p&gt;Here's how that would go:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ftxd6l0imlg4uf2d39z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ftxd6l0imlg4uf2d39z.png" alt="Flow 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The screen Big Head sees in his browser might look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxo6z0td531etgj8tekup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxo6z0td531etgj8tekup.png" alt="Flow 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack #1: Big Head's credentials are exposed
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcTRtZjMyOHMxMmRnMGY5emdvbGljemxyZ251OXpyMGM4eGp4NXh2biZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F3oD3YQKOzj8cjVoOAg%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcTRtZjMyOHMxMmRnMGY5emdvbGljemxyZ251OXpyMGM4eGp4NXh2biZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F3oD3YQKOzj8cjVoOAg%2Fgiphy.webp" alt="We have a problem"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By handing over his username and password, Big Head gives Pied Piper full access to his entire Hooli account. This includes Hooli Mail, Hooli Chat, and even the ability to change his password! Furthermore, if someone ever hacks Pied Piper, they will get to see Big Head's password in plain text.&lt;/p&gt;

&lt;p&gt;So, they come up with a new plan: generate an access token. This is a key that lets Pied Piper access Big Head's data on Hooli with limited permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tjq8rmfw2qumaukvhmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tjq8rmfw2qumaukvhmx.png" alt="Flow 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is how it would look like to Big Head:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuckasqgv4103j45qgsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxuckasqgv4103j45qgsf.png" alt="Flow 4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this approach is secure, it's not particularly user-friendly. Big Head doesn't want to generate an access token manually every single time he compresses a file, or signs in to a service. He wants Pied Piper to do it for him.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation
&lt;/h3&gt;

&lt;p&gt;Instead of Big Head generating access tokens manually and copying them to Pied Piper, Pied Piper can ask Hooli to generate access tokens on his behalf.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxytx0t1sl79fzufgicxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxytx0t1sl79fzufgicxn.png" alt="Flow 5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This would be amazing if there were no bad actors on this world! Big Head just needs to click a button, and everything is done automatically. But, there is an obvious problem here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack #2: Anyone can just claim to be anyone else
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcDdhYXo3eTBmaGMwdnp5eWVhZmo1bngyZTZyMGx6ZTd3aHFidHF4OSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F26BRuyxFdtlQq5VPa%2Fgiphy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExcDdhYXo3eTBmaGMwdnp5eWVhZmo1bngyZTZyMGx6ZTd3aHFidHF4OSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F26BRuyxFdtlQq5VPa%2Fgiphy.webp" alt="I am your mom"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is absolutely no security in this approach! Pied Piper can just pretend to be acting on behalf of anyone, and Hooli will happily generate an access token.&lt;/p&gt;

&lt;p&gt;So, to ensure the request is really from Big Head, Hooli needs to ask him for confirmation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbb3fg9mzwwcsczdnwzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbb3fg9mzwwcsczdnwzb.png" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the wide world of the web, step 3 is usually done by redirecting Big Head to a page on a &lt;code&gt;hooli.com&lt;/code&gt; domain. So, his browser would show this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x3p7097q7bhrt4mpfqy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x3p7097q7bhrt4mpfqy.jpg" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hooli can now verify that the person sitting in front of the browser is Big Head. In step 3, Hooli can freely design the confirmation process. Hooli could ask Big Head to confirm his email/password login, do 2FA, and/or ask for consent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Putting a name on it: Implicit flow
&lt;/h3&gt;

&lt;p&gt;Early implementations of OAuth looked exactly like this; we call it the &lt;em&gt;implicit flow&lt;/em&gt;. Though, we're not even half-way through this post, so maybe you can guess that you shouldn't use this in your production apps.&lt;/p&gt;

&lt;p&gt;But, let's start giving names to things, in accordance with what OAuth calls them:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz49tbm167l79gmsq6sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz49tbm167l79gmsq6sb.png" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The query parameters in the URL are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;client_id=piedpiper&lt;/code&gt;: This tells Hooli which app is asking for access (in this case, Pied Piper).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;redirect_uri=https://piedpiper.com/callback&lt;/code&gt;: This is where Hooli should send Big Head back to after he approves the connection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scope=drive&lt;/code&gt;: The permissions Pied Piper needs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response_type=token&lt;/code&gt;: Tells Hooli that we are using the implicit flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far so good!&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack #3: Redirect URI manipulation
&lt;/h2&gt;

&lt;p&gt;Endframe, a malicious competitor to Pied Piper, wants to steal Big Head's Hooli drive data.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Endframe sends Big Head an email with the subject, "Connect your Hooli account with Pied Piper".

&lt;ul&gt;
&lt;li&gt;They include a link to &lt;code&gt;https://hooli.com/authorize?...&lt;/code&gt;, with the same &lt;code&gt;client_id&lt;/code&gt; and &lt;code&gt;scope&lt;/code&gt; as a real request from Pied Piper.&lt;/li&gt;
&lt;li&gt;But, they change the &lt;code&gt;redirect_uri&lt;/code&gt; parameter to &lt;code&gt;https://endframe.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Big Head checks the domain and sees it is &lt;code&gt;hooli.com&lt;/code&gt;, so he clicks on the link.&lt;/li&gt;
&lt;li&gt;The Hooli consent screen pops up. Big Head confirms that it is Pied Piper's client ID, so he logs in and confirms access.&lt;/li&gt;
&lt;li&gt;However, after Big Head clicks "Allow," Hooli redirects him to &lt;code&gt;https://endframe.com&lt;/code&gt; instead of &lt;code&gt;https://piedpiper.com/callback&lt;/code&gt;, sending the access token to Endframe.&lt;/li&gt;
&lt;li&gt;Now, Endframe has access to Big Head's Hooli drive!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problem is that Hooli didn't verify that the &lt;code&gt;client_id&lt;/code&gt; and &lt;code&gt;redirect_uri&lt;/code&gt; match.&lt;/p&gt;

&lt;p&gt;The solution is to require Pied Piper to register all possible redirect URIs first. Then, Hooli should refuse to redirect to any other domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack #4: Cross-site request forgery (CSRF)
&lt;/h2&gt;

&lt;p&gt;There are some more advanced attacks however. Endframe can still trick Big Head into logging in with a malicious Hooli account:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Endframe registers an account with Pied Piper.&lt;/li&gt;
&lt;li&gt;They log into Pied Piper and generate an access token &lt;code&gt;access_token_456&lt;/code&gt; for their own Hooli drive.&lt;/li&gt;
&lt;li&gt;They send Big Head an email with the title "Check out our Bachmanity photo album" and a link &lt;code&gt;https://piedpiper.com/callback?access_token=access_token_456&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Big Head checks the domain, sees it is &lt;code&gt;piedpiper.com&lt;/code&gt;, and clicks on it.&lt;/li&gt;
&lt;li&gt;The Pied Piper website opens the callback and logs in Big Head into Endframe's Hooli drive, so any files he uploads will go to Endframe's Hooli drive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;How can we prevent this? We need to make sure that we only finish the OAuth flow if we initiated it.&lt;/p&gt;

&lt;p&gt;To do so, Pied Piper can generate a random string (we call it &lt;code&gt;state&lt;/code&gt;), store it in cookies, and send it to Hooli. Hooli will then send this &lt;code&gt;state&lt;/code&gt; back to Pied Piper when it redirects Big Head back. Pied Piper should then check that the received &lt;code&gt;state&lt;/code&gt; matches the one in the cookies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm3zjrvjp5f9cekxqket.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm3zjrvjp5f9cekxqket.png" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;state=random_string_123&lt;/code&gt;: A randomly generated string to prevent CSRF attacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Attack #5: Eavesdropping access tokens
&lt;/h2&gt;

&lt;p&gt;Endframe isn't giving up. They've come up with another plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They teamed up with a genius developer called Jian Yang and created a "Hot dog or not" tool that detects hot dogs. Maliciously, it also sends the entire browser history to Endframe.

&lt;ul&gt;
&lt;li&gt;(There are a number of other history sniffing or HTTP downgrade attacks that could pull this off, too.) &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Big Head thinks it's funny and installs it.&lt;/li&gt;
&lt;li&gt;Endframe now sees all the access tokens for all services that Big Head ever logged in with, by searching for URLs that look like &lt;code&gt;https://piedpiper.com/callback?access_token=access_token_123&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a fix for this. We need to make sure that access tokens are never exchanged in browser URLs.&lt;/p&gt;

&lt;p&gt;Hooli generates a short-lived "authorization code" and redirects back to Pied Piper with this code. Pied Piper then makes a POST request to another endpoint, which invalidates the authorization code and exchanges it for the access token.&lt;/p&gt;

&lt;p&gt;This way, the access token never ends up in the browser history. We call this the &lt;em&gt;authorization code&lt;/em&gt; flow. It is more secure than the implicit flow, but we're still not done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqwt512qubfcgiru5lh9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqwt512qubfcgiru5lh9.jpg" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;response_type=code&lt;/code&gt;: Tells Hooli that we are using the authorization code flow, instead of the implicit flow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;code=authorization_code_123&lt;/code&gt;: The authorization code Hooli generated for Pied Piper.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;grant_type=authorization_code&lt;/code&gt;: For the authorization code flow, this is always &lt;code&gt;authorization_code&lt;/code&gt; (we won't cover the other grant types).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Attack #6: Eavesdropping authorization codes
&lt;/h2&gt;

&lt;p&gt;If Endframe eavesdrops the authorization code in real-time, they can exchange it for an access token very quickly, before Big Head's browser does.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Big Head still has the "Hot dog or not" tool installed.&lt;/li&gt;
&lt;li&gt;As soon as Big Head connects his Hooli drive account, "Hot dog or not" fetches the authorization code from Big Head's browser history.&lt;/li&gt;
&lt;li&gt;In real time, faster than Big Head's browser can send the request, Endframe swoops in and sends a request to Hooli with Big Head's authorization code. They get the access token and Big Head's request fails.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Currently, anyone with the authorization code can exchange it for an access token. We need to ensure that only the person who initiated the request can do the exchange.&lt;/p&gt;

&lt;p&gt;We do this by securely storing a secret on the client. We hash this secret, and send it to Hooli alongside the very first request. When exchanging the authorization code for the access token, we send the original secret to Hooli. Hooli then compares the hashes, proving that the request is coming from the same client.&lt;/p&gt;

&lt;p&gt;This procedure is called &lt;em&gt;proof key for code exchange&lt;/em&gt; (PKCE).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrydev65thanxbbdt070.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrydev65thanxbbdt070.jpg" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;code_verifier=random_string_456&lt;/code&gt;: The original random string Pied Piper sent to Hooli.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;code_challenge=hashed_string_123&lt;/code&gt;: The hashed code verifier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is this secure? Not quite...&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Attack #7: Redirect URI manipulation on trusted URIs
&lt;/h2&gt;

&lt;p&gt;Imagine that Pied Piper has two registered redirect URIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://piedpiper.com/callback&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://piedpiper.com/share-files-callback&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first one authorizes and compresses Hooli drive files, and the second one shares files publicly with other users. (This could also be the same endpoint with different query parameters.)&lt;/p&gt;

&lt;p&gt;Even though we protect against Endframe replacing the redirect URI with something totally malicious (like &lt;code&gt;https://endframe.com&lt;/code&gt;), if Endframe can intercept the request somehow, they can still modify the URI to point to the other endpoint.&lt;/p&gt;

&lt;p&gt;The solution? Make the client send the current URI again when exchanging the authorization code for the access token. Hooli can then verify that the redirect URI matches the one in the original request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan67rw4nbjclkjoneu1m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fan67rw4nbjclkjoneu1m.png" alt="Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some final notes
&lt;/h2&gt;

&lt;p&gt;This is an informal explanation of the OAuth flow, and the actual specification is much longer. For example, client secrets, refresh tokens, client credentials flow, token grants, etc., are not covered here.&lt;/p&gt;

&lt;p&gt;Furthermore, there are a lot of nitty-gritty details that are required for a secure implementation. You probably shouldn't implement your own OAuth client.&lt;/p&gt;

&lt;p&gt;For diving deeper or if you want to implement OAuth in your apps, here are some good resources.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6749" rel="noopener noreferrer"&gt;The OAuth 2.0 Authorization Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6819" rel="noopener noreferrer"&gt;OAuth 2.0 Threat Model and Security Considerations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps" rel="noopener noreferrer"&gt;OAuth 2.0 for Browser-Based Applications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally, if you don't want to implement OAuth yourself, that is exactly why we built &lt;a href="https://github.com/stack-auth/stack" rel="noopener noreferrer"&gt;Stack Auth&lt;/a&gt;, you can get Google/Github/Microsoft/and more OAuth login by just toggling one switch!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
