CodingNic

Authentication and User Security

Introduction to OAuth

Authentication and User Security 18 min read

Introduction to OAuth

Introduction to OAuth

So far in this module, every authentication path has assumed you are the identity provider. Users register on your site, you store their passwords (hashed), you verify them at login, you issue their session or token. You’re the one keeping the keys.

That’s a lot of responsibility. And for many apps, it’s responsibility you’d rather not have. Password resets, account recovery, suspicious-login emails, two-factor authentication, breach response — these are all genuine work, and getting them right is harder than building login itself.

There’s a different approach: let someone else handle identity, and just listen to their answer. Click “Sign in with Google” on any modern site and you’re seeing this pattern in action. Google does the password verification. Google handles the recovery flows. Google deals with the bots and brute-force attempts. Your app just gets a yes-or-no answer (and a few user details) at the end.

The protocol underneath this is called OAuth. This lesson is about understanding what it is, why it exists, and what it actually does — without writing the code. By the end you’ll know enough to recognise OAuth-flavoured code when you see it, and enough to decide whether you want it in your own apps.


What OAuth was originally for (and why people are confused about it)

Before we go further, an honest detour about a source of confusion.

OAuth was not designed for authentication. It was designed for authorization — specifically, for letting a third-party app access some of your data on another site, without having to share your password.

Picture the original problem: it’s 2007, you’ve signed up for a photo-printing service, and they ask for your Flickr password so they can grab your photos and print them. That’s a terrible idea. You’d be giving them full access to your account — they could delete photos, change your email, do anything you could. And there’s no way to revoke just that one app’s access without changing your password (and locking out every other app too).

OAuth was the answer. It says: “instead of giving the printing service your Flickr password, click a button on Flickr that grants them limited access — say, read-only access to your photos, expiring in 30 days. They get a token. You can revoke that token whenever you want, without changing your password.”

That’s the original purpose: delegated authorization for APIs.

But people realised something: if the third-party app can verify that Flickr says you’re the owner of alice@example.com, that’s effectively a login. Why make people register a new password on every site when Google already knows who they are?

So OAuth got bolted onto authentication. And to clean up the rough edges, a thin standard called OpenID Connect (OIDC) was layered on top — specifically for the “log in with a third-party identity provider” use case.

When you click “Sign in with Google” today, you are technically using OpenID Connect, which is built on OAuth 2.0. Most people just call the whole thing “OAuth” or “social login.”

Two takeaways:

  1. OAuth is about delegating access — originally to data, increasingly to identity.
  2. When someone says “we use OAuth for login,” they usually mean “we use OpenID Connect on top of OAuth 2.0.” Don’t worry about the distinction unless you’re implementing it yourself.

The vocabulary

OAuth has four key roles. Naming them clearly is half the battle.

  • Resource Owner — the human. The user with the account.
  • Client — the app that wants to use the user’s identity or data. Your Books app, in our case.
  • Authorization Server — the service that authenticates the user and issues tokens. Google, GitHub, Facebook, Auth0, Okta, etc.
  • Resource Server — the service that holds the user’s data and accepts tokens to release it. Often the same provider as the authorization server (Google APIs, GitHub APIs, etc.).

Mapped onto “Sign in with Google for the Books app”:

Role Who
Resource Owner Alice (the user)
Client The Books app
Authorization Server Google’s OAuth service
Resource Server Google’s user-info API

Alice is granting the Books app permission to read her name and email from Google. The Books app never sees her Google password — Google’s authorization server does.


The flow, conceptually

The most common OAuth flow is called the Authorization Code flow. Here’s what happens when Alice clicks “Sign in with Google” on the Books app — described in plain terms, no code:

1. The Books app sends Alice to Google.

Instead of showing its own login form, the Books app constructs a URL like https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&scope=email%20profile and redirects Alice’s browser to it. The URL includes:

  • Who is asking (the client_id — the Books app’s public identifier with Google).
  • What is being asked for (scope=email profile — Alice’s email and basic profile).
  • Where to send Alice back to afterwards (redirect_uri).

2. Google authenticates Alice.

If Alice isn’t already signed into Google, she signs in there. This step happens on Google’s servers — not on the Books app’s. The Books app never sees her Google password.

3. Google asks Alice for consent.

Google shows Alice a screen like: “Books App wants access to your email address and basic profile information. Allow?”

This is the part users actually notice. It’s also the part where Alice can say no. Granting consent is explicit, not implied.

4. Google redirects Alice back to the Books app with an authorization code.

Assuming Alice says yes, Google sends her browser back to the redirect_uri the Books app provided, with a one-time authorization code in the URL: https://books.app/auth/callback?code=abc123.

This code is not a token yet. It’s a short-lived ticket that proves Alice agreed to something. By itself it does nothing useful.

5. The Books app (server-side) exchanges the code for tokens.

The Books app’s server makes a backend request directly to Google: “Here’s the code you gave us, plus our client secret. Please trade it for tokens.”

Google verifies that:

  • The code is valid and unused.
  • The client secret matches (proving the request really is from the Books app, not from some attacker who intercepted the code).

If everything checks out, Google responds with:

  • An access token — used to call Google APIs on Alice’s behalf.
  • An ID token — a JWT (yes, the same kind from Lesson 10) containing Alice’s identity: her email, name, Google user ID, and so on.
  • (Sometimes) a refresh token — used to get a new access token when the old one expires.

6. The Books app reads the ID token and signs Alice in.

The Books app decodes the ID token, sees that Google has verified Alice’s email is alice@example.com, and creates (or looks up) a user in its own database matching that email. It then issues its own session cookie — exactly like in Lesson 4 — and Alice is logged in.

From Alice’s point of view, the whole thing was: click a button, see Google’s consent screen, click “Allow,” end up signed in to the Books app. The dance with codes and tokens happened invisibly behind the redirects.


Why an authorization code, then an exchange? Why not a token directly?

A reasonable question after that flow.

The reason for the code-and-exchange dance is security. The redirect from Google to the Books app travels through the user’s browser. URLs in browsers are exposed — they show up in browser history, in Referer headers, in server logs. If Google handed back the access token directly in the URL, that token might leak.

The authorization code is single-use and short-lived (typically valid for a few minutes). Even if someone intercepts it, they can’t trade it for a token without the Books app’s client_secret, which only lives on the Books app’s server.

This separation is why production OAuth requires a backend. There used to be a flow called the Implicit Flow that skipped the exchange step and returned tokens directly, intended for purely browser-side apps. It’s now deprecated in favour of using the Authorization Code flow with an extension called PKCE (Proof Key for Code Exchange) which handles the security in a different way. You’ll see PKCE mentioned in any modern OAuth library.


What the user sees, what they don’t

The user sees:

  • A button on your site that says “Sign in with Google” (or GitHub, or Facebook, etc).
  • A redirect to Google’s familiar login + consent screen.
  • A redirect back to your site, now signed in.

The user doesn’t see:

  • The client ID and redirect URI you registered with Google.
  • The authorization code in the redirect URL.
  • The token exchange happening on your backend.
  • The ID token your server decoded to know who they are.

This invisibility is part of the appeal. Users trust the Google login experience because they see it every day, and they trust your app slightly more because it didn’t ask for a new password.


What you gain (and what you give up)

Gains

  • No password storage. You never see the user’s password. You can’t leak it, lose it, or accidentally log it. Google has spent more on password security than your startup ever will.
  • No password reset flows. Forgot-password emails, security questions, account recovery: not your problem. Google handles it.
  • Trust transfer. If Google says Alice’s email is verified, you can trust that. You don’t need your own email-verification flow for accounts that came through Google.
  • Faster signups. Users who already have a Google account can be in your app in two clicks.
  • Better security defaults. Two-factor authentication, suspicious-login detection, geo-warnings, hardware key support — all handled by the provider, all available to your users for free.

Costs

  • Provider lock-in. What happens if a user’s Google account gets locked? They can’t sign in to your app either. You’ll usually offer multiple providers (Google + GitHub + email/password) to mitigate this — but each one adds setup complexity.
  • You depend on someone else’s uptime. If Google’s OAuth service is down, your “Sign in with Google” button breaks. Rare, but not zero.
  • Privacy considerations. Every login tells Google that the user just signed in to your app. Some users prefer not to have that data exhaust.
  • The flow has many edge cases. What if the user’s email at Google changes? What if they revoke access from their Google account dashboard? What if you need fields Google doesn’t provide? Real implementations handle a lot of “what ifs” that look invisible until you hit them.
  • You usually still need your own user table. Even with OAuth, you typically create a row in your users table the first time someone signs in, store their email and provider ID, and use that row as their identity inside your app. OAuth replaces the authentication step, not the user model.

How this looks in practice

A common production pattern for a Flask app:

  1. Install an OAuth library (the popular Flask choices are Authlib and the older Flask-Dance).
  2. Register your app with the providers you want — Google, GitHub, etc. You get a client_id and client_secret from each.
  3. Add two routes per provider: one that kicks off the flow (/auth/google), and one that handles the callback (/auth/google/callback).
  4. In the callback, look up or create the user, then sign them in with Flask-Login’s login_user(user) — exactly as in Lesson 9.
  5. Keep your existing /login and /register routes for users who prefer email/password. OAuth is usually offered alongside, not instead of, traditional login.

The library handles every dance step above. Your code is mostly “here’s my client ID, here’s the user row to create or fetch, here’s the redirect URL.” A typical Authlib + Google setup is around 30 lines.

We’re not writing that code in this lesson. The point is that you can now read it and know what each piece is doing.


When to reach for OAuth

A rough rule:

  • Consumer apps where signup friction matters. “Sign in with Google” routinely doubles signup conversion. If your users have Google accounts and your competitors offer it, you probably should too.
  • B2B apps where customers want SSO. Enterprises often require their employees to sign in via the company’s identity provider (Okta, Azure AD). That’s OAuth/SAML under the hood. Without it, you might be disqualified from selling to them.
  • Apps that need to read other services’ data. If you need to fetch the user’s Google Calendar events or their GitHub repositories, OAuth is the way. That’s its original purpose.

When to stick with email/password:

  • Internal tools where everyone uses the same email domain you control.
  • Apps where privacy matters more than convenience.
  • Anything you’re building to learn, where the simpler path teaches more.

A note on alternatives and adjacent terms

You’ll see these names in the OAuth world. Quick disambiguation:

  • OAuth 1.0a — the older protocol. Mostly historical at this point. If you’re starting today, use 2.0.
  • OAuth 2.0 — the current standard. What everyone means when they say “OAuth.”
  • OpenID Connect (OIDC) — a thin layer on top of OAuth 2.0, specifically for authentication. Defines the ID token, the userinfo endpoint, and a standard openid scope.
  • SAML — an older, XML-based protocol for the same job. Common in enterprise SSO. Different syntax, similar idea.
  • PKCE — an extension that lets public clients (mobile apps, SPAs) use OAuth safely without a client_secret.
  • Magic links — a different approach to passwordless login: user types their email, you send a one-time signed link to that email, clicking it logs them in. Not OAuth at all, but often mentioned in the same conversation.

You don’t need to learn any of these now. Knowing they exist saves you from feeling lost when they come up.


Summary

  • OAuth is a protocol for delegated access — letting one app act on a user’s behalf with another service.
  • It was originally designed for authorization (data access), but the OpenID Connect layer on top of it makes it work for authentication too.
  • The Authorization Code flow involves: redirect to provider → user authenticates and consents → provider redirects back with a code → your server exchanges the code for tokens → you read the ID token and sign the user in.
  • The dance exists for security: codes in URLs can leak, so the actual tokens are issued only after a backend exchange.
  • Benefits: no password storage, no reset flows, trust transfer, faster signups, better security defaults.
  • Costs: provider lock-in, dependency on uptime, privacy implications, real edge cases, you still need your own user table.
  • For Flask, Authlib is the most popular library. Wire OAuth login into your existing app and finish with login_user(user).

Outcome

You understand what’s happening behind every “Sign in with Google” button. You know the vocabulary, the flow, the trade-offs, and the production tools — all without having had to wade through a full implementation. Next lesson, we look at the other question that comes up after authentication: once we know who the user is, how do we decide what they’re allowed to do?