Delegation without the password
A Socratic walk-through of delegation without the password — reasoned out one step at a time, not lectured.
The question we started with
THE QUESTION #How do you let one service act for you somewhere else without ever giving it your credentials?
A scheduling tool wants to read your calendar. The direct approach is to ask for your calendar password, log in as you, and fetch it. That worked, was common, and had a name people used without embarrassment: the password anti-pattern.
Ask what is actually wrong with it, though, rather than assuming. The tool gets your password — but suppose you trust the tool. Even then, four things are broken, and naming them precisely tells you what any replacement has to provide.
Reasoning it through
REASONING #Take them in turn. A password is not scoped: it grants everything the account can do, and you wanted to hand over read access to a calendar, not the ability to delete your mail. A password is not time-limited: it is as good next year as today. A password cannot be withdrawn selectively: revoking it from one tool revokes it from you and every other tool at once. And a password is often not the whole story anyway — with a second factor in play, a stored password no longer even works.
So the replacement needs to be a credential that is narrower than the password, expires, is independently revocable, and can be issued after whatever authentication ceremony the account actually requires. That is a fair description of what OAuth 2.0 exists to produce.
Now, who issues it? Not the tool — the tool is the party we are limiting. It has to be issued by something that can verify you and that the calendar service already trusts. Call that the authorization server. Four roles fall out naturally: you as the resource owner, the tool as the client, the authorization server that authenticates you and mints tokens, and the resource server holding the calendar.
The crucial structural move follows. You authenticate at the authorization server, not at the client. The tool redirects your browser away to a site it does not control, you sign in there, you are shown what is being asked for, and you approve or refuse. The password is entered on a page belonging to the party that already had it. The tool never sees it — not because it promised not to look, but because it was never on the path.
Then a question about the return trip. The authorization server has to get something back to the tool. Why does it return a short-lived authorization code rather than the token itself?
Because of where the return trip runs. It comes back through your browser as a redirect, and that path is leaky: URLs land in history, in server logs, in referrer headers, in a proxy's records. So the front channel carries only a code, which is single-use, expires in about a minute, and is worthless on its own. The tool then makes a direct server-to-server call — the back channel — presenting the code together with proof that it is the client the code was issued to, and receives the token there. The token itself never touches the browser's address bar.
What does the tool end up holding? An access token, limited by scope to the operations you approved, valid for minutes or hours, and addressed to a particular resource server. Alongside it, usually, a refresh token: a longer-lived credential good only at the authorization server, exchangeable for fresh access tokens, and revocable from a single place.
Now a correction worth making, because it is the most common misreading of this whole design. The token says nothing about who you are. It says: the holder may do these things, on this resource, until this time. A service that treats "I successfully used this token" as proof of identity is making an inference the protocol does not license, and that inference has produced real vulnerabilities. Proving identity needs the layer built on top for exactly that purpose, OpenID Connect, whose ID token is a signed statement about the user, addressed to the client, and meant to be verified rather than merely spent.
The analogy
THE ANALOGY #A valet key. It starts the car and it is genuinely a key, but it will not open the boot or the glovebox, and the dealership can void it without changing the locks on your own key. You hand the valet something real and usable, shaped to exactly the one job you wanted done.
a valet key is cut by the manufacturer and its limits are physical, whereas a token's limits are only claims that each receiving service must actively check — an unchecked scope is a valet key that quietly opens the boot after all.
Clarifying the model
THE MODEL #Three refinements.
First, the security gain is not that the token is more secret than the password. It is not — it is a bearer credential, and stealing it is worthwhile. The gain is in blast radius: narrower, shorter, and individually revocable, so a compromise costs less and can be contained without disrupting anything else.
Second, "OAuth logs you in" is a widespread and unhelpful compression. OAuth delegates access; OpenID Connect asserts identity. They usually travel together, which is why the two get conflated, but they answer different questions and are validated differently.
Third, consent has to be meaningful to be worth anything. A screen listing scopes nobody reads, in an application whose developer requested everything just in case, delegates far more than the user intended. The protocol makes least privilege possible; it cannot make it happen.
A picture of it
THE PICTURE #How to readRead it as a map of what touches what. PASSWORD connects to exactly two things — you and the authorization server — and there is no path from it to CLIENT_APP, which is the entire point of the design. Everything the client holds hangs off GRANT, and every one of those edges is narrowing: limited by a scope, accepted by one resource server, revocable at the single node that recorded it. The many-side markers show where multiplicity lives: many grants per user, many tokens per grant, so one can be withdrawn without disturbing the others.
What became clearer
WHAT CLEARED #Delegation is not about sharing a secret carefully; it is about never sharing it and issuing a purpose-built substitute instead. Once you see that the password's real defects are its breadth, its permanence and its indivisibility, the whole redirect dance stops looking baroque — each step exists to keep the password on one side of a line while a narrower, expiring, revocable credential crosses to the other.
Where to go next
ONWARD #- Why the authorization code must be bound to the client that requested it, and what happens when it is intercepted.
- Audience restriction: why a token minted for one resource server must be refused by another.
- How refresh-token rotation turns a long-lived credential into a detectable one when copied.
Key terms
TERMS #| Term | What it means |
|---|---|
| OAuth 2.0 | a delegated authorization framework in which a resource owner grants a client limited access to a resource server without sharing credentials. |
| Authorization code | a short-lived single-use value returned through the browser and exchanged directly for a token. |
| Scope | the requested and granted set of operations a token permits. |
| Refresh token | a longer-lived credential, used only at the authorization server, that obtains new access tokens. |
| OpenID Connect | the identity layer over OAuth 2.0 that supplies a verifiable assertion about who the user is. |
Every term the collection defines is gathered in the glossary.