Templates
Types
EN

OAuth Flow Diagram Guide

How to draw an OAuth flow diagram that is actually useful — the four participants, front channel vs back channel, and three ready-to-edit examples including PKCE and refresh token rotation.

Published on ·10 min read
oauthsequence-diagramsecuritytemplate

What is an OAuth flow diagram?

An OAuth flow diagram shows how a user grants an application access to their data on another service without handing over their password. It draws four parties and the order in which they talk: the resource owner (the human), the client (your app), the authorization server (the thing that issues tokens), and the resource server (the API holding the data).

Naming those four correctly is most of the value. The single most common mistake in OAuth diagrams is collapsing the authorization server and the resource server into one box labelled "Google". They are different systems with different jobs — one decides who you are and what you may do, the other serves data and checks the token it was handed. Once they are one box, the diagram can no longer show the thing that matters: which of them ever sees the user's password (only the first) and which only ever sees a token (only the second).

The other reason to draw it is that OAuth is a redirect protocol, and redirects are invisible in code. Reading a handler tells you what happens at one endpoint; it does not tell you that the browser bounced through three origins carrying a state parameter that must come back unchanged. A sequence diagram makes the bounce visible, which is why almost every real OAuth bug — mismatched redirect_uri, dropped state, code replayed twice — is obvious in a diagram and invisible in a stack trace.

If you have read the RFC's diagram and still cannot draw your own, that is expected: the spec draws the abstract protocol. Your diagram needs the parts the spec leaves as an exercise, which is what the examples below are.

What an OAuth flow diagram has to show

Five things. The first one is the one that separates a useful OAuth diagram from a redrawn spec figure:

  • Which arrows go through the browser. OAuth has a front channel (redirects the user's browser follows, visible in the address bar and in history) and a back channel (server-to-server calls nobody can see). Every design decision in the protocol comes from that split. Mark it — a dotted arrow, a note, a colour, anything.
  • What each arrow carries. code, access_token, refresh_token and id_token are four different things with four different lifetimes and blast radii. Writing "token" on every arrow throws away the entire security story.
  • The authorization server and the resource server as separate lifelines, even when the same vendor operates both. See above.
  • At least one rejection branch. Expired code, state mismatch, PKCE verifier mismatch, revoked refresh token — pick the one your team actually argues about and draw it as an alt.
  • Where the token ends up. A diagram that stops at "access token issued" answers half the question. The interesting half is what the client does with it: memory, cookie, or somewhere it should not be.

Here is the skeleton — authorization code, no error branches, four separate participants. Every example below is this diagram with one specific thing added.

View the Mermaid source
sequenceDiagram
    participant User as Resource Owner
    participant App as Client App
    participant Auth as Authorization Server
    participant API as Resource Server

    User->>App: click Sign in
    App->>Auth: redirect to /authorize
    Auth->>User: login and consent screen
    User->>Auth: approve
    Auth-->>App: redirect back with code
    App->>Auth: POST /token with the code
    Auth-->>App: access token
    App->>API: GET /me with the access token
    API-->>App: profile data
A minimal OAuth authorization code flow diagram with four participants: resource owner, client app, authorization server and resource server.

How to draw an OAuth flow diagram

Three steps. Step 1 is where most diagrams go wrong, and it takes about two minutes.

Step 1 · Pin down which flow you are drawing

"OAuth" is not one flow, and drawing a generic one produces a diagram that is wrong for every specific case. Answer one question — is there a human present at the moment the token is issued?

If yes, you are drawing authorization code with PKCE. This is the answer for web apps, single-page apps and mobile apps alike. It has been the answer for every browser-based client since PKCE became mandatory for public clients; if you find a tutorial drawing implicit flow (token returned straight in the redirect URL), it predates that and you should not copy it.

If no — a cron job, a service syncing with a partner API — you are drawing client credentials, and your diagram has no user lifeline at all. That absence is information: it is why there is no consent screen and no refresh token.

Everything else (device code for TVs, token exchange between services) is a variation you will know you need. Pick one and draw only it. A diagram covering two flows at once covers neither.

Step 2 · Split the front channel from the back channel

Go through your arrows and sort each one into two piles: the browser carries this and our server calls this directly.

The sort is mechanical — anything that is a redirect, a URL the user's address bar shows, or a form the user submits, is front channel — but the result is the whole point of the protocol. The front channel is observable: it is in browser history, in Referer headers, in server logs, potentially on a shared machine's screen. That is exactly why the authorization code goes through it and the access token does not. The code is short-lived, single-use, and useless without the client secret or a PKCE verifier — it is designed to survive being seen.

Once sorted, check one thing: is there anything on the front channel that would be damaging if a stranger read it over your shoulder? If yes, that is a finding, and it is the kind this diagram exists to produce.

Step 3 · Draw it

Describe the handshake in sentences and let text2diagram lay it out — "the app redirects the browser to the authorization server with a code challenge, the user logs in and approves, the server redirects back with a code, the app exchanges the code plus the verifier for tokens at the token endpoint" comes back as an editable sequenceDiagram.

Or open one of the examples below in the editor and rename the participants to your provider. The arrangement is the part that is hard to get right; Authorization ServerOkta is a find-and-replace.

OAuth flow diagram examples

Three flows the spec's figure does not draw for you: the modern default, what happens when a token expires, and what it looks like when there is no user at all.

1 · Authorization code with PKCE

The two arrows worth studying are the first and the last. The app generates a code_verifier and sends only its hash (code_challenge) through the front channel; at the end it sends the verifier itself through the back channel. An attacker who steals the code out of a redirect has the code but not the verifier, so the exchange fails — that is the entire idea, and it is legible in the diagram in a way it is not in prose.

Also note the check state matches self-arrow. It is not a network call, so people leave it out; leaving it out is how CSRF on the callback endpoint ships. A step that guards something deserves a box even when nothing crosses the wire.

View the Mermaid source
sequenceDiagram
    autonumber
    participant User as Browser
    participant App as Client App
    participant Auth as Authorization Server
    participant API as Resource Server

    App->>App: generate code_verifier and code_challenge
    App->>Auth: GET /authorize with client_id, redirect_uri, code_challenge, state
    Auth->>User: login and consent
    User->>Auth: approve
    Auth-->>App: 302 back to redirect_uri with code and state
    App->>App: check state matches what we sent
    App->>Auth: POST /token with code and code_verifier
    alt verifier does not match the challenge
        Auth-->>App: 400 invalid_grant
    else verifier matches
        Auth-->>App: access_token and refresh_token
        App->>API: GET /me with Bearer access_token
        API-->>App: profile
    end
An OAuth authorization code flow diagram with PKCE, showing code challenge generation, state verification and the invalid_grant rejection branch.

2 · Refresh token rotation and reuse detection

This is the flow teams skip and then debug at 2am. Access tokens expire constantly, so this path runs far more often than the login above — and it has a branch most diagrams omit.

With rotation, each refresh burns the old token and issues a new one. That turns a stolen refresh token into a detectable event: if RT1 is presented twice, either the attacker or the real client is using a token the server already retired, and the server cannot tell which. The only safe response is to revoke the whole family and force a fresh login. Drawing that second branch is what turns "we rotate refresh tokens" from a checkbox into a behaviour with a defined outcome.

View the Mermaid source
sequenceDiagram
    autonumber
    participant App as Client App
    participant Auth as Authorization Server
    participant API as Resource Server

    App->>API: GET /orders with Bearer access_token
    API-->>App: 401 token expired
    App->>Auth: POST /token with refresh token RT1
    alt RT1 is unused and valid
        Auth->>Auth: revoke RT1, issue RT2
        Auth-->>App: new access_token and RT2
        App->>API: retry GET /orders
        API-->>App: 200 OK
    else RT1 was already used - it leaked
        Auth->>Auth: revoke the whole token family
        Auth-->>App: 400 invalid_grant
        App->>App: clear session, send the user to login
    end
An OAuth refresh token flow diagram showing rotation on success and family-wide revocation when a refresh token is reused.

3 · Client credentials — no user at all

The shape to notice is what is missing: no browser lifeline, no consent screen, no redirect, no front channel at all. Every arrow here is server to server, which is why this flow is allowed to use a plain client secret and why PKCE has nothing to do here.

The branch worth drawing is the boring one — the token expiring partway through a long batch. It is boring right up until a nightly sync half-completes and leaves two systems disagreeing, at which point everyone wants to know whether the job re-authenticates and resumes or gives up. The diagram answers that in one glance.

View the Mermaid source
sequenceDiagram
    autonumber
    participant Job as Nightly Job
    participant Auth as Authorization Server
    participant API as Partner API

    Note over Job: no user is present - nobody to consent
    Job->>Auth: POST /token with client_id and client_secret
    Auth-->>Job: short lived access_token, scoped
    Job->>API: POST /sync with Bearer access_token
    alt token still valid
        API-->>Job: 200 OK
    else token expired mid batch
        API-->>Job: 401
        Job->>Auth: POST /token again
        Auth-->>Job: fresh access_token
        Job->>API: retry POST /sync
        API-->>Job: 200 OK
    end
An OAuth client credentials flow diagram for machine-to-machine access, including re-authentication when the token expires mid-batch.

If an arrow carries a secret through the browser, that is the finding

Draw the diagram, then read only the front-channel arrows and ask what each one would cost you if it were screenshotted. An authorization code: nothing, by design. An access token in a URL fragment: a session. A client secret anywhere near the browser: everything — and it means the app is a public client that should be using PKCE instead.

This is the one review pass that an OAuth diagram makes cheap and that reading code makes nearly impossible, because the front channel is spread across a redirect, a callback route and a browser you do not control.

FAQ

Continue reading

Try text2diagram now

Open the tool
← Back to all tutorials