# The OAuth Mental Model

## Four roles (memorize these)

OAuth names four actors. Everything else hangs off them.

```mermaid
flowchart TB
    RO["Resource Owner<br/>(the user)"]
    AS["Authorization Server<br/>(Keycloak, Okta, Google, Auth0…)"]
    RS["Resource Server<br/>(API)"]
    CL["Client<br/>(your app)"]

    RO -->|"grants consent / trust"| AS
    RO -->|"owns resources"| RS
    AS -->|"issues access token"| RS
    CL -->|"presents access token"| RS
    CL -->|"requests authorization"| AS
```

| Role | Plain English | Example |
|------|---------------|---------|
| **Resource owner** | User who can grant access | Alice |
| **Client** | App requesting access | Your Spring Boot app |
| **Authorization server** | Issues tokens after consent | Keycloak realm |
| **Resource server** | API that accepts tokens | Your `/api/orders` service |

One company often runs **both** authorization server and resource server (Google issues tokens and hosts Gmail API). In microservices, they are usually separate.

---

## Three token types you will meet

### Access token

- **Purpose:** Prove authorization to call an API
- **Audience:** Resource server
- **Format:** Often opaque or JWT
- **Lifetime:** Short (minutes to an hour)

```http
GET /api/orders HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
```

### Refresh token

- **Purpose:** Obtain a new access token without re-prompting the user
- **Audience:** Authorization server only
- **Lifetime:** Longer (days/weeks), revocable
- **Storage:** Server-side or secure httpOnly cookie — **never** `localStorage` in a browser

### ID token (OIDC, not pure OAuth)

- **Purpose:** Identity claims about the authenticated user
- **Audience:** Client application
- **Format:** JWT
- **Lifetime:** Short; not an API credential

**Rule of thumb:** Use the **access token** for APIs. Use the **ID token** for login/session identity in your client.

---

## Scopes: the valet key notches

Scopes limit what a token can do. They are strings agreed between client and authorization server.

```text
openid profile email
read:orders write:orders
```

| Scope | Meaning |
|-------|---------|
| `openid` | OIDC request — return an ID token |
| `profile` | Name, picture, etc. |
| `email` | Email address |
| `read:orders` | Custom API scope (you define in Keycloak) |

The authorization server shows the user a **consent screen** listing scopes. The issued access token embeds (or maps to) only approved scopes.

---

## Flows = how the client gets tokens

A **grant type** (flow) is the protocol path from "user wants to use app" to "client holds tokens."

| Flow | Use today? | Notes |
|------|------------|-------|
| **Authorization Code + PKCE** | **Yes — default** | SPAs, mobile, server apps |
| Client credentials | Yes | Machine-to-machine, no user |
| Device code | Yes | TVs, CLI devices |
| Implicit | **No** | Replaced by Auth Code + PKCE |
| Resource owner password | **No** | Deprecated; bypasses consent |

A later post in this series walks through Authorization Code + PKCE in detail.

---

## OIDC sits on top of OAuth

```mermaid
flowchart LR
    O["OAuth 2.0"]
    OIDC["OpenID Connect"]
    O -->|"authorization"| Q1["Can this app access that API?"]
    OIDC -->|"identity layer"| Q2["Who is the user?"]
    OIDC -.->|"built on"| O
```

OIDC adds:

- `id_token` JWT
- `/userinfo` endpoint
- Discovery document at `/.well-known/openid-configuration`

When people say "OAuth login," they almost always mean **OIDC**.

---

## Sessions vs tokens (where confusion starts)

| Concept | Where it lives | Typical use |
|---------|----------------|-------------|
| OAuth tokens | Client + auth server contract | API access |
| App session | Your server or cookie | "Logged in to *our* app" |

A common pattern:

1. User completes OIDC flow → your backend receives tokens
2. Backend validates ID token, creates **app session** (cookie)
3. Backend stores refresh token server-side
4. Browser only sees session cookie; never holds refresh token

Your app still needs session management. OAuth does not replace it.

---

## Go deeper

### JWT access tokens vs opaque tokens

**JWT (self-contained):**

- Resource server can validate locally (signature + claims)
- Harder to revoke instantly
- Must keep claims small

**Opaque:**

- Resource server introspects with auth server
- Revocation is immediate
- Extra network hop

Keycloak can do both. Choose based on revocation needs and API topology.

### Audience (`aud`) and issuer (`iss`)

JWTs carry `iss` (who minted) and `aud` (who may consume). Validating only the signature without checking `aud` is a common vulnerability — your API must reject tokens minted for a different client.

### Multi-tenant mental model

In Keycloak:

- **Realm** ≈ tenant
- **Client** ≈ your application registration
- **Users** live in the realm

Okta/Auth0 use different names (Authorization Server, Application) but the same idea: you register your app and get `client_id` + credentials.

---

## What you should know after this post

- [ ] You can name all four roles and one example of each
- [ ] You know access vs refresh vs ID token
- [ ] You default to Authorization Code + PKCE for user-facing clients
- [ ] You separate "OAuth tokens" from "my app's session"

---
