
OAuth 2.0 Overview
I keep having to look up the same things in RFC 6749 — the names of the endpoints, which parameters go on which one, and which grant types still matter. So this is my own cheat sheet, mostly for myself.
The three endpoints
OAuth defines three endpoints. The first two live on the authorization server, the third is on the client.
- Authorization endpoint — where the user is redirected to sign in and approve access. Takes
response_type,client_id,redirect_uri,scopeandstate. - Token endpoint — the back-channel endpoint the client calls to exchange a grant for an access token. Takes
grant_type,code,redirect_uri,client_idand, for confidential clients,client_secret. - Redirection endpoint — the client's URL that the authorization server sends the user back to. It doesn't take parameters itself, but it receives them in the query string:
code,state, or on errorserroranderror_description. For the implicit grant the access token comes back in the URL fragment instead.
The four grant types
The spec defines four ways to actually get a token. In practice only two of them are still worth using.
Authorization code — the one you should be using for almost everything. The user is redirected to the auth server, comes back with a code, and the client exchanges that code at the token endpoint for an access token (and optionally a refresh token). Combine with PKCE for public clients and you're in good shape.
Client credentials — used when there's no user involved. A server calling another server on its own behalf. Client authenticates itself at the token endpoint and gets an access token back. Simple.
Implicit — returns the access token directly in the URL fragment after authorization, skipping the token endpoint. It was meant for single-page apps that couldn't do a secure back-channel call, but it leaks tokens into browser history and has no refresh mechanism. Use authorization code with PKCE instead.
Resource owner password credentials — the user hands their password to the client, which forwards it to the auth server. It defeats most of the point of OAuth and should only exist in legacy migrations.
What a normal flow looks like
For the code flow, in order:
- Client redirects the user to
/authorizewithresponse_type=code, aclient_id, aredirect_uri, thescope, and astatevalue it generated. - User authenticates and consents on the auth server.
- Auth server redirects back to
redirect_uriwith?code=...&state=.... - Client verifies
statematches what it sent, then POSTs to/tokenwithgrant_type=authorization_code, thecode, itsclient_id(andclient_secretif confidential) and the sameredirect_uri. - Auth server returns an access token, optionally a refresh token, and the token metadata.
The state parameter is there to stop CSRF. Always generate it, always verify it. If your library doesn't do this for you, find a different library.
Response you get back
The token endpoint returns JSON like this:
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "...",
"scope": "read write"
}scope is only echoed back if it's different from what was requested. refresh_token only shows up if the client is allowed to have one.
That's pretty much all I reach for day to day. For the edge cases — device flow, token introspection, revocation, dynamic client registration — those live in their own RFCs and I'll write them up separately when I need them.