OAuth 2.0 is the protocol that lets one application act on a user's behalf at another — "let this app read my Google calendar," "let Slack post to my GitHub." It's not authentication ("who are you?") but authorization ("what is this app allowed to do for you?"). Get the flow right and you delegate cleanly; get it wrong and you build a phishing surface.
← Back to Securityread:calendar, write:posts. Smaller scopes mean smaller blast radius if leaked.The flow nearly everyone should use, for both web apps and mobile/SPA clients:
code_challenge (PKCE).code.code + code_verifier for tokens at the token endpoint.PKCE (Proof Key for Code Exchange) defends against code-interception attacks. Originally designed for mobile, now mandatory for all clients in OAuth 2.1, including server-side webapps.
Service-to-service. No user involved. The client authenticates with its own ID and secret (or a private key / mTLS) and receives a token to act on its own behalf. The right grant for backend integrations, scheduled jobs, and machine-to-machine APIs.
For input-constrained devices — TVs, CLI tools, IoT. The device shows a code; the user goes to a URL on a phone or laptop, enters the code, approves. The device polls until approved. How gh auth login, AWS CLI SSO, smart TV Netflix logins all work.
state ParameterThe state param prevents CSRF on the redirect back. Generate a random per-request value, store it in a session, verify on callback. Skipping it is how attackers tie an attacker-controlled auth flow to the victim's session.
The auth server must exactly match the redirect URI against a registered allow-list — no wildcards, no path-prefix matches. Open redirects in your callback URL are how attackers exfiltrate tokens to their own servers.
localStorage is readable by any JavaScript on your origin — one XSS, every token leaks. Use HttpOnly cookies for browser-stored tokens, paired with a backend that exchanges them for the API. The "BFF (Backend-for-Frontend) pattern" is now the recommended browser architecture.
An access token says "this client may act for some user." It does not authoritatively identify the user. For login, use OIDC's ID token, which is signed and includes sub, iss, aud. Mixing the two is a common cause of authentication bugs.
Modern guidance: rotate refresh tokens on every use. Detect reuse (the same refresh token presented twice) as a sign of compromise and revoke the entire token family. Public clients (SPA, mobile) should always rotate; confidential clients can choose.
Asking for repo when you only need repo:read; asking for https://www.googleapis.com/auth/gmail.modify when gmail.readonly would do. Users notice. So do regulators. Ask for the minimum.