API Authentication — Complete Guide to Verifying Identity
In this tutorial, you will learn about API Authentication. We cover key concepts, practical examples, and best practices to help you master this topic.
API authentication verifies the identity of clients calling an API using API keys, OAuth 2.0, JWT tokens, basic auth, or mutual TLS, ensuring only authorized clients access protected endpoints.
What You'll Learn
- Common API authentication methods and their use cases
- Implementing API keys and JWT authentication
- OAuth 2.0 flows for delegated authorization
Why It Matters
Without authentication, any client can access your API. Proper authentication prevents unauthorized access, enables per-client Rate Limiting, and provides audit trails for API usage.
Real-World Use
Durga Antivirus Pro uses three auth methods: API keys for server-to-server integrations (threat feed partners), OAuth 2.0 for user-facing applications (dashboard), and JWT tokens for internal microservice communication.
flowchart LR
A["API Authentication"] --> B["API Keys"]
A --> C["OAuth 2.0"]
A --> D["JWT"]
A --> E["Basic Auth"]
A --> F["mTLS"]
style A fill:#dbeafe,stroke:#2563eb
Code Examples
# API key authentication
from flask import Flask, request, jsonify, abort
app = Flask(__name__)
API_KEYS = {'key_abc123': 'partner_1', 'key_def456': 'partner_2'}
def require_api_key(f):
def wrapper(*args, **kwargs):
api_key = request.headers.get('X-API-Key')
if not api_key or api_key not in API_KEYS:
abort(401, 'Invalid API key')
request.client = API_KEYS[api_key]
return f(*args, **kwargs)
return wrapper
@app.route('/api/threats')
@require_api_key
def get_threats():
return jsonify({'client': request.client, 'threats': []})
Expected output: Requests without valid API key receive 401; authenticated requests include client identity.
# JWT authentication
import jwt
from flask import Flask, request, jsonify
from datetime import datetime, timedelta
app = Flask(__name__)
SECRET = 'your-secret-key'
def create_token(user_id, role):
payload = {
'sub': user_id,
'role': role,
'exp': datetime.utcnow() + timedelta(hours=1),
'iat': datetime.utcnow(),
}
return jwt.encode(payload, SECRET, algorithm='HS256')
def require_auth(f):
def wrapper(*args, **kwargs):
token = request.headers.get('Authorization', '').replace('Bearer ', '')
try:
payload = jwt.decode(token, SECRET, algorithms=['HS256'])
request.user = payload
except jwt.ExpiredSignatureError:
return jsonify({'error': 'Token expired'}), 401
except jwt.InvalidTokenError:
return jsonify({'error': 'Invalid token'}), 401
return f(*args, **kwargs)
return wrapper
@app.route('/api/profile')
@require_auth
def get_profile():
return jsonify({'user_id': request.user['sub'], 'role': request.user['role']})
Expected output: JWT token in Authorization header is decoded; expired or invalid tokens are rejected.
// OAuth 2.0 client credentials flow
const axios = require('axios');
async function getAccessToken(clientId, clientSecret) {
const response = await axios.post('https://auth.example.com/oauth/token', {
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: 'threats:read',
});
return response.data.access_token;
}
async function callApi() {
const token = await getAccessToken('my-client', 'my-secret');
const data = await axios.get('https://api.example.com/threats', {
headers: { Authorization: `Bearer ${token}` },
});
console.log(data.data);
}
Expected output: OAuth 2.0 client credentials flow returns access token used to authenticate API requests.
Common Mistakes
1. Storing API Keys in Client-Side Code
API keys in frontend JavaScript are visible to users. Use server-side proxies for browser-based applications.
2. Using Basic Auth Without TLS
Basic auth sends credentials in base64 (not encrypted). Always use with HTTPS.
3. Not Rotating Keys and Secrets
Static keys that never rotate become a security risk. Implement key rotation policies.
4. JWT Without Expiration
Tokens that never expire cannot be revoked. Always set short expirations (15-60 min) with refresh tokens.
5. Mixing Authentication and Authorization
Authentication verifies identity; authorization verifies permissions. Implement both separately.
Practice Questions
- What are three common API authentication methods?
- Why should API keys not be stored in client-side code?
- What is the difference between authentication and authorization?
- Why must JWT tokens have an expiration time?
- When should you use OAuth 2.0 vs simple API keys?
Answers:
- API keys, JWT tokens, and OAuth 2.0.
- Client-side code is visible to users, exposing keys for anyone to copy and use.
- Authentication verifies who you are; authorization verifies what you are allowed to do.
- Without expiration, compromised tokens grant indefinite access and cannot be revoked.
- Use API keys for server-to-server; use OAuth 2.0 for user-facing applications and delegated access.
Challenge: Implement three authentication methods for a single API: API keys for partner integrations, JWT tokens for user sessions, and OAuth 2.0 client credentials for service accounts. Include key rotation and token refresh.
FAQ
Mini Project
Build an authentication system for a task management API supporting three methods: API key (X-API-Key header), JWT (Authorization: Bearer), and Basic Auth. Include middleware that detects the method, verifies credentials, and attaches user identity to the request.
What's Next
Explore API authorization patterns for role-based access control, or learn about API security best practices for comprehensive endpoint protection.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro