OAuth2 Authorization Server — Core Component for Token Issuance
In this tutorial, you will learn about OAuth2 Authorization Server. We cover key concepts, practical examples, and best practices to help you master this topic.
The authorization server is the core of OAuth2 — it authenticates resource owners, obtains consent, registers clients, and issues access and refresh tokens.
What You'll Learn
The responsibilities of an authorization server, how to build one, endpoint design, and security considerations.
Why It Matters
The authorization server is the most security-critical component in OAuth2. A compromised authorization server compromises every token it issued. Getting it right is essential.
Real-World Use
Google Accounts, Auth0, Keycloak, Okta — all are authorization servers. They handle millions of authentications daily, issuing tokens for thousands of clients.
flowchart LR
A["Auth Server"] --> B["/authorize\nUser auth + consent"]
A --> C["/token\nExchange codes, refresh"]
A --> D["/introspect\nValidate tokens (RS)"]
A --> E["/revoke\nRevoke tokens"]
A --> F["/.well-known/jwks.json\nPublic keys"]
A --> G["/register\nClient registration"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fef3c7,stroke:#d97706
style C fill:#fef3c7,stroke:#d97706
style D fill:#fef3c7,stroke:#d97706
style E fill:#fef3c7,stroke:#d97706
style F fill:#fef3c7,stroke:#d97706
style G fill:#fef3c7,stroke:#d97706
Required Endpoints
| Endpoint | Purpose |
|---|---|
/authorize |
User authentication and consent |
/token |
Exchange codes, refresh tokens |
/introspect |
(Optional) Validate opaque tokens |
/revoke |
(Optional) Token revocation |
/.well-known/jwks.json |
Public keys for JWT verification |
/.well-known/openid-configuration |
Discovery (for OIDC) |
Code Example: Simple Authorization Server
from flask import Flask, request, redirect, jsonify
import jwt, secrets, datetime, hashlib
app = Flask(__name__)
SECRET = secrets.token_hex(32)
# Stores
clients = {
"web-app": {"secret": "web-secret", "type": "confidential",
"redirect_uris": ["https://app.com/callback"]}
}
auth_codes = {}
refresh_tokens = {}
@app.route("/authorize")
def authorize():
client_id = request.args.get("client_id")
redirect_uri = request.args.get("redirect_uri")
state = request.args.get("state")
client = clients.get(client_id)
if not client or redirect_uri not in client["redirect_uris"]:
return "Invalid client", 400
# Simulate user authentication (in real app, show login form)
user = request.args.get("user", "default-user")
# Generate authorization code
code = secrets.token_urlsafe(32)
auth_codes[code] = {
"client_id": client_id,
"user": user,
"redirect_uri": redirect_uri,
"expires": datetime.datetime.utcnow() + datetime.timedelta(minutes=2)
}
redirect_url = f"{redirect_uri}?code={code}&state={state}"
return redirect(redirect_url)
@app.route("/token", methods=["POST"])
def token():
grant_type = request.form.get("grant_type")
if grant_type == "authorization_code":
code = request.form.get("code")
stored = auth_codes.pop(code, None)
if not stored or datetime.datetime.utcnow() > stored["expires"]:
return jsonify({"error": "invalid_grant"}), 400
access_token = jwt.encode({
"sub": stored["user"],
"scope": "openid profile",
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}, SECRET, algorithm="HS256")
return jsonify({
"access_token": access_token,
"token_type": "Bearer",
"expires_in": 3600
})
return jsonify({"error": "unsupported_grant_type"}), 400
if __name__ == "__main__":
app.run(port=5001)
Common Mistakes
1. Not Validating redirect_uri
The authorization server must validate redirect_uri against the registered URIs for each client.
2. Short Authorization Code Lifetime
Codes should expire within 1-2 minutes to prevent interception attacks.
3. Not Rate-Limiting Token Endpoint
The token endpoint is vulnerable to brute force. Implement Rate Limiting.
4. Storing Secrets in Plain Text
Client secrets must be hashed. Access tokens should be hashed if stored.
5. Not Supporting Token Revocation
The authorization server should provide a revocation endpoint for clients to revoke tokens.
Practice Questions
- What endpoints does an authorization server need?
- Why must authorization codes have short lifetimes?
- How does the authorization server authenticate clients?
- What is the consent screen?
- How does token introspection work?
Answers:
- /authorize, /token, plus optional /introspect, /revoke, /.well-known/jwks.json.
- If intercepted, the attacker has only a short window to exchange the code.
- Confidential clients authenticate with client_secret. Public clients use PKCE.
- The consent screen shows the user what scopes the client is requesting and asks for approval.
- The resource server sends the token to the introspection endpoint. The auth server returns the token's active state and metadata.
Challenge: Build a minimal but functional authorization server that supports Authorization Code grant, client registration, redirect URI validation, and token issuance.
FAQ
Mini Project
Build a minimal authorization server with client registration, Authorization Code grant, token issuance (JWT), redirect URI validation, and a mock consent screen.
What's Next
Now learn about the OAuth2 Resource Server — the component that protects data using access tokens.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro