OAuth 2.0 Authorization Code Flow — Complete Delegated Auth Guide
In this tutorial, you will learn about OAuth 2.0 Authorization Code Flow. We cover key concepts, practical examples, and best practices to help you master this topic.
The OAuth 2.0 authorization code flow allows users to grant third-party applications limited access to their resources without sharing their password. It is the most secure grant type for web and mobile applications.
What You'll Learn
You'll learn how the authorization code flow works, including the redirect-based flow, code exchange, and token issuance.
Why It Matters
This pattern powers "Login with Google/Facebook/GitHub" and is required for any application that accesses user data through third-party APIs.
Real-World Use
A project management app lets users import contacts from Google. The authorization code flow shows a Google consent screen, and the app receives a token to read contacts without ever seeing the user's Google password.
sequenceDiagram
participant User
participant App as Client App
participant Auth as Authorization Server
participant API as Resource Server
User->>App: Click "Login with Provider"
App->>Auth: Redirect with client_id, redirect_uri, scope, state
Auth->>User: Login & Consent
User->>Auth: Grant Permission
Auth->>App: Redirect with authorization code
App->>Auth: POST /token (code, client_secret)
Auth->>App: access_token + refresh_token
App->>API: GET /data (Bearer token)
API->>App: Data
Teacher's Mindset
The authorization code flow is like a valet parking ticket. You give your car key (authorization) to the valet, who takes it to the parking lot (auth server). The valet gives you a ticket (code), which you exchange for your car later.
Implementation
from flask import Flask, request, jsonify
import requests
import secrets
app = Flask(__name__)
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
REDIRECT_URI = "https://app.example.com/callback"
AUTH_SERVER = "https://auth.example.com"
@app.route("/auth/login")
def login():
state = secrets.token_urlsafe(32)
params = {
"response_type": "code",
"client_id": CLIENT_ID,
"redirect_uri": REDIRECT_URI,
"scope": "openid profile email",
"state": state
}
auth_url = f"{AUTH_SERVER}/authorize?{urllib.parse.urlencode(params)}"
return jsonify({"auth_url": auth_url, "state": state})
@app.route("/auth/callback")
def callback():
code = request.args.get("code")
state = request.args.get("state")
if not code:
return jsonify({"error": "Missing code"}), 400
token_response = requests.post(
f"{AUTH_SERVER}/token",
data={
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI,
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET
},
headers={"Content-Type": "application/x-www-form-urlencoded"}
)
if token_response.status_code != 200:
return jsonify({"error": "Token exchange failed"}), 400
return jsonify(token_response.json())
Common Mistakes
| Mistake | Fix |
|---|---|
| Missing state parameter (CSRF) | Always include and validate state |
| Exposing client_secret in client-side code | Use PKCE for mobile/public clients |
| Not validating redirect_uri | Whitelist exact redirect URIs |
| Using implicit grant (deprecated) | Use authorization code with PKCE |
| Not using HTTPS for redirect | Code intercepted in transit |
Practice Questions
- Why is the state parameter important?
- How does the authorization code differ from implicit grant?
- What is the purpose of the client_secret?
- Why must redirect_uris be whitelisted?
- What is a CSRF attack on OAuth callback?
Challenge
Implement the authorization code flow with a mock authorization server. Support login, consent screen, callback with code exchange, and token usage. Implement state parameter validation.
What's Next
Learn about OAuth 2.0 client credentials flow for server-to-server communication.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro