EXPLAINER

OAuth 2.0

OAuth 2.0 is a protocol for granting a client limited access to an API without sharing the user's password. It is how sign-in buttons and Microsoft Graph access tokens usually start. It is not itself a login profile; OpenID Connect adds identity on top.

Short answer: OAuth 2.0 lets an app call an API with a token the user (or an admin) consented to, instead of a password. Login identity is OpenID Connect. Tokens are often JWTs. For agents, see OAuth for AI Agents.

What it is

OAuth 2.0 is an authorisation framework. A client (your app) wants to call a resource server (an API) on behalf of a resource owner (a person) or as itself. An authorisation server issues an access token after the owner consents. The client sends that token to the API. The owner's password, if there is one, is typed into the authorisation server, not into your app.

OAuth is not a complete login system. It does not by itself say the token subject is a specific person. OpenID Connect adds an identity layer on top. People still say "OAuth login" for that combination. OAuth for AI Agents is the narrower case of agents holding tokens. API Keys are a different, simpler credential. API Authentication: Keys, Sessions and OAuth compares them for ordinary APIs.

Why and when it is used

Use OAuth when a user must grant your app access to their account on someone else's API: mail, files, a calendar, Microsoft Graph. Use the client-credentials variant when a program acts as itself with no user, and treat that as a high privilege. Use an API key only when the API's threat model is "anyone with the key is the app" and there is no per-user consent.

Do not invent a flow that asks the user to paste their password into your form so you can log into another site. That is credential sharing, and it breaks the moment the other site adds multifactor authentication. Do not use the obsolete implicit flow for new apps.

How it works

The common user-facing flow is authorisation code with PKCE. Your app sends the user to the authorisation server with a client id, the scopes it wants, a redirect URI, and a PKCE challenge. The user signs in and consents. The server redirects back with a short-lived code. Your app exchanges the code, plus the PKCE verifier, for an access token and usually a refresh token. The access token goes to the API in a header (Authorization: Bearer ...) and expires in minutes or hours. The refresh token gets a new access token without another login, and should be stored like a password.

Scopes name what was granted (Files.Read, not "everything"). The API must check them. A token without the scope, or a token for a different API, is a 401 or 403, not a prompt to log in harder. Confidential clients (a server) can hold a client secret. Public clients (a mobile app or a single-page app) cannot keep a secret, which is why PKCE exists.

Technologies and dependencies

An authorisation server ( Entra ID, Google, or your own), a client library that implements the flow rather than a hand-rolled redirect if you can help it, and secure storage for refresh tokens. JWTs are a common token format but OAuth does not require them; opaque tokens that the API introspects are valid. HTTPS is mandatory. Redirect URIs must match exactly.

How to get started

  1. Register a client. Set one localhost redirect URI.
  2. Use a library's auth-code + PKCE example. Do not copy a gist that puts the token in the URL fragment and calls it done.
  3. Request one read scope. Complete login. Print the scopes you received, not the token, in any log.
  4. Call the API with the access token. Then wait until it expires or force expiry and use the refresh token.
  5. Revoke the grant in the provider's UI and confirm the next call fails.
  6. Store refresh tokens encrypted at rest, tied to your user id, and delete them on disconnect.

If the provider's documentation and your library disagree, trust the current provider docs and a recent library version, not a 2014 blog.

Cautions and trade-offs

Tokens in localStorage are easy for any script on the page to steal. Prefer a secure, httpOnly cookie session of your own, and keep the provider's tokens on the server. Redirect URI wildcards are a phishing hole. Over-broad scopes train users to click consent blindly and train admins to reject your app.

Refresh tokens live a long time. Theft of a refresh token is theft of access until revocation. Rotate them when the provider supports it. Never log tokens. And do not confuse OAuth with authorisation inside your own database. The token says the provider allowed this client to call that API. Your app still decides which of your rows the user may touch (Authentication versus Authorization).