OAuth 2.0 is an authorization framework that enables applications to obtain limited access to user accounts on an HTTP service, such as Facebook or Google, without exposing the user’s password.
Installation
OAuth 2.0 is a protocol, not a tool to be installed. You interact with OAuth 2.0 through libraries and frameworks within your programming language or by directly making HTTP requests to authorization servers.
Core Concepts
- Resource Owner: The user who owns the data and grants permission to access it.
- Client: The application requesting access to the Resource Owner’s data.
- Authorization Server: The server that authenticates the Resource Owner and issues access tokens after obtaining authorization.
- Resource Server: The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
- Resource Owner Password Credentials: The Resource Owner’s username and password, used directly by the client to obtain an access token. (Not recommended for most third-party applications).
- Authorization Grant: A credential representing the Resource Owner’s authorization to access resources server.
- Access Token: A credential used by the client to make authorized requests to the Resource Server.
- Refresh Token: A credential used to obtain a new access token when the current one expires.
- Scope: Defines the level of access the client is requesting. For example,
read_profileorwrite_posts. - Client ID: A unique identifier for the client application, issued by the Authorization Server.
- Client Secret: A secret string used by the client to authenticate with the Authorization Server.
Flows / Usage
Authorization Code Grant
This is the most common and secure flow for web applications.
-
Client requests authorization from Resource Owner: The client redirects the Resource Owner’s browser to the Authorization Server’s
/authorizeendpoint.GET https://authorization-server.com/oauth/authorize? response_type=code& client_id=YOUR_CLIENT_ID& redirect_uri=https://your-app.com/callback& scope=read_profile%20write_posts& state=a_random_string_to_prevent_csrfresponse_type=code: Specifies that the client is requesting an authorization code.client_id: The unique identifier for your application.redirect_uri: The URI where the Authorization Server will redirect the Resource Owner back to after authorization. Must be pre-registered.scope: A space-separated list of permissions the client is requesting.state: An opaque value used by the client to maintain state between the request and callback.
-
Resource Owner authorizes the client: The user logs in to the Authorization Server and approves (or denies) the requested permissions.
-
Authorization Server redirects back to Client with Authorization Code: If authorized, the Authorization Server redirects the Resource Owner’s browser back to the
redirect_uriwith an authorizationcodeand thestateparameter.GET https://your-app.com/callback? code=AUTHORIZATION_CODE_FROM_SERVER& state=a_random_string_to_prevent_csrf -
Client exchanges Authorization Code for Access Token: The client (server-side) makes a direct request to the Authorization Server’s
/tokenendpoint to exchange the authorization code for an access token.POST https://authorization-server.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& code=AUTHORIZATION_CODE_FROM_SERVER& redirect_uri=https://your-app.com/callback& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRETgrant_type=authorization_code: Specifies that you are exchanging an authorization code.code: The authorization code received in the previous step.redirect_uri: Must match the one used in the/authorizerequest.client_id: Your application’s client ID.client_secret: Your application’s client secret.
-
Authorization Server responds with Access Token: The Authorization Server validates the code and client credentials and responds with an access token (and optionally a refresh token).
{ "access_token": "ACCESS_TOKEN_VALUE", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "REFRESH_TOKEN_VALUE", "scope": "read_profile write_posts" } -
Client uses Access Token to access Resource Server: The client includes the
access_tokenin theAuthorizationheader of requests to the Resource Server.GET https://resource-server.com/api/user/profile Authorization: Bearer ACCESS_TOKEN_VALUE
Implicit Grant (Browser-based Apps - Deprecated and Not Recommended)
This flow is for single-page applications (SPAs) where a client secret cannot be kept secure. It’s less secure as the access token is returned directly in the URL fragment.
-
Client requests authorization from Resource Owner: Similar to Authorization Code Grant, but
response_typeistoken.GET https://authorization-server.com/oauth/authorize? response_type=token& client_id=YOUR_CLIENT_ID& redirect_uri=https://your-spa.com/callback& scope=read_profile& state=a_random_string_to_prevent_csrf -
Resource Owner authorizes the client: User logs in and approves.
-
Authorization Server redirects back to Client with Access Token: The Authorization Server redirects the Resource Owner’s browser back to the
redirect_uriwith theaccess_tokenin the URL fragment.GET https://your-spa.com/callback# access_token=ACCESS_TOKEN_VALUE& token_type=Bearer& expires_in=3600& scope=read_profile& state=a_random_string_to_prevent_csrf -
Client uses Access Token to access Resource Server: The SPA extracts the
access_tokenfrom the URL fragment and uses it in requests to the Resource Server.GET https://resource-server.com/api/user/profile Authorization: Bearer ACCESS_TOKEN_VALUE
Resource Owner Password Credentials Grant (Direct Login - Not Recommended for Third-Party Apps)
The client collects the Resource Owner’s username and password and sends them directly to the Authorization Server to get an access token. Only use this if you are the resource owner and the client is your own application.
-
Client requests Access Token with User Credentials:
POST https://authorization-server.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=password& username=USER_EMAIL@example.com& password=USER_PASSWORD& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRET& scope=read_profilegrant_type=password: Specifies you are using user credentials.username: The Resource Owner’s username.password: The Resource Owner’s password.client_id,client_secret: Your application’s credentials.scope: Requested permissions.
-
Authorization Server responds with Access Token: The Authorization Server validates the credentials and responds with an access token.
{ "access_token": "ACCESS_TOKEN_VALUE", "token_type": "Bearer", "expires_in": 3600, "scope": "read_profile" } -
Client uses Access Token to access Resource Server: Same as step 6 in Authorization Code Grant.
Client Credentials Grant (Machine-to-Machine)
This flow is used for clients accessing their own resources, not on behalf of a user.
-
Client requests Access Token using its own credentials:
POST https://authorization-server.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRET& scope=read_api_datagrant_type=client_credentials: Specifies you are using client credentials.client_id,client_secret: Your application’s credentials.scope: Requested permissions for the client itself.
-
Authorization Server responds with Access Token:
{ "access_token": "ACCESS_TOKEN_VALUE", "token_type": "Bearer", "expires_in": 3600, "scope": "read_api_data" } -
Client uses Access Token to access Resource Server: Same as step 6 in Authorization Code Grant.
Common Patterns
-
Handling Token Expiration and Refresh: When an
access_tokenexpires (indicated by a 401 Unauthorized response from the Resource Server), use therefresh_tokento obtain a newaccess_token.POST https://authorization-server.com/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=refresh_token& refresh_token=REFRESH_TOKEN_VALUE& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRET& scope=read_profile // Optional: can request a subset of original scopes -
Validating Access Tokens: Many APIs provide an endpoint to introspect an access token, or the token itself might be a JWT (JSON Web Token) that can be decoded and validated locally (check signature, expiration, issuer, audience).
-
Introspection Endpoint Example:
POST https://authorization-server.com/oauth/introspect Content-Type: application/x-www-form-urlencoded token=ACCESS_TOKEN_VALUE& client_id=YOUR_CLIENT_ID& client_secret=YOUR_CLIENT_SECRETResponse indicates if the token is active, its scopes, etc.
-
JWT Decoding (Conceptual - uses a library): If your
access_tokenis a JWT, you can use a library to decode its header and payload to inspect its contents (e.g., expirationexp, issueriss, audienceaud).
-
-
Implementing CSRF Protection with
state: When initiating the authorization flow, generate a unique, unguessable random string and store it in the user’s session. Compare this storedstatewith thestateparameter received in the callback URL to ensure the request originated from your application.
Gotchas
redirect_uriMismatch: Theredirect_uriprovided in both the authorization request and the token exchange request must exactly match a pre-registered URI with the Authorization Server. Even minor differences (e.g., trailing slash, http vs https) will cause failure.- Client Secret Exposure: Never embed your
client_secretin client-side JavaScript or mobile applications. Use flows like Authorization Code Grant with PKCE, or the Resource Owner Password Credentials Grant (with extreme caution and only for first-party apps). - Token Storage: Securely store access and refresh tokens. For web apps, consider HttpOnly cookies for refresh tokens and in-memory storage or secure local storage for access tokens.
- Scope Validation: The Authorization Server may issue tokens with fewer scopes than requested. Always check the
scopereturned in the token response and validate it before performing actions. - Authorization Code Expiration: Authorization codes are short-lived (typically minutes) and can only be used once.
token_type: Always check thetoken_typein the token response.Beareris common, meaning the token is presented directly in theAuthorization: Bearer <token>header. Other types might exist.- PKCE (Proof Key for Code Exchange): For public clients (like SPAs and mobile apps) using the Authorization Code Grant, PKCE is highly recommended to prevent authorization code interception attacks. It involves generating a
code_verifierandcode_challengeduring the authorization request.