Backend Security Lesson 4 of 6 ⏱️ 4 min read

OAuth 2.0 & OpenID Connect Explained

The authorization code flow with PKCE, scopes, ID tokens vs access tokens, and how "Sign in with Google" really works.

Updated Oct 30, 2026

The problem OAuth solves

Imagine a study app that wants to read your Google Calendar to plan revision sessions. Before OAuth, it would ask for your Google password — giving it total access to your account. OAuth 2.0 lets you grant the app limited, revocable access (just "read calendar") without sharing your password.

OAuth 2.0 vs OpenID Connect

  • OAuth 2.0 is about authorization — giving an app permission to access an API on your behalf. The result is an access token.
  • OpenID Connect (OIDC) is a layer on top of OAuth 2.0 for authentication — proving who the user is. It adds an ID token (a JWT) containing the user's identity.

"Sign in with Google/Microsoft/GitHub" is OpenID Connect.

The four roles

Role Example
Resource owner You, the student
Client The study app
Authorization server Google's login and consent service
Resource server The Google Calendar API

The authorization code flow with PKCE

This is the recommended flow for web apps, mobile apps and single-page apps:

Plaintext
1. App → Browser:  redirect to the authorization server with
                   client_id, redirect_uri, scope, state, code_challenge
2. User logs in at the provider and approves the requested scopes
3. Provider → App: redirect back to redirect_uri?code=AUTH_CODE&state=...
4. App backend → Provider: exchange code + code_verifier for tokens
5. Provider → App: access_token (+ refresh_token, + id_token for OIDC)
6. App → API:      Authorization: Bearer <access_token>

The short-lived authorization code travels through the browser; the tokens are exchanged in a back-channel request.

PKCE: protecting the code

PKCE (Proof Key for Code Exchange) stops attackers who intercept the authorization code from using it:

  1. The app creates a random code verifier.
  2. It sends a code challenge = Base64URL(SHA-256(verifier)) in step 1.
  3. In step 4 it sends the original verifier; the server hashes it and checks it matches.

An attacker with only the code can't produce the verifier.

Python
import base64
import hashlib
import secrets

def make_pkce_pair() -> tuple[str, str]:
    verifier = secrets.token_urlsafe(64)          # 86 characters (allowed range: 43–128)
    digest = hashlib.sha256(verifier.encode("ascii")).digest()
    challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
    return verifier, challenge

verifier, challenge = make_pkce_pair()
print(len(verifier), challenge)

Use PKCE for every client today — including server-side web apps.

The state parameter

Generate a random state, store it in the user's session, and check it when the provider redirects back. A mismatch means the response wasn't started by this user — it blocks CSRF on the login flow.

Scopes limit what an access token can do: openid email profile for sign-in, calendar.readonly for reading a calendar. Request the minimum scopes you need — users are more likely to approve, and a leaked token can do less damage.

ID token vs access token

ID token (OIDC) Access token (OAuth)
Purpose Tells your app who logged in Lets the app call an API
Audience Your app's client ID The API (resource server)
Format Always a JWT JWT or an opaque string
Should you send it to APIs? No Yes

When handling an ID token, verify its signature (using the provider's published keys), issuer, audience, expiry and the nonce you sent.

Other grant types

  • Client credentials — machine-to-machine access with no user (a backend job calling another API).
  • Device authorization — for TVs and CLIs that can't easily show a browser.
  • Implicit and password grants — deprecated; don't use them in new apps.

Practical advice

  • Use a well-maintained OIDC client library or your framework's integration rather than hand-rolling the flow.
  • Register exact redirect URIs; never allow open redirects.
  • Store refresh tokens securely and rotate them.
  • Treat third-party profile data (like email) as verified only if the provider marks it verified.

Common mistakes

  • Using OAuth access tokens to identify users. Use the OIDC ID token or the userinfo endpoint.
  • Skipping state or PKCE.
  • Wildcard redirect URIs, enabling token theft through open redirects.
  • Requesting broad scopes "just in case".

Key takeaways

  • OAuth 2.0 = delegated authorization; OpenID Connect = authentication on top.
  • Use the authorization code flow with PKCE and a random state.
  • ID tokens identify the user to your app; access tokens call APIs.
  • Request minimal scopes and verify every token you accept.
Finished this lesson?
Tick it off to track your Backend Security progress.
Next lesson