
Python
Many APIs require authentication to control who can access data and what they can do. Authentication proves your identity to the server, ensuring secure communication and preventing unauthorized access. Understanding different authentication methods is essential for working with modern web services.
Authentication serves several purposes:
import requests
# Without authentication - likely fails
response = requests.get('https://api.example.com/private-data')
print(response.status_code) # Probably 401 Unauthorized
# With authentication - succeeds
headers = {'Authorization': 'Bearer YOUR_TOKEN_HERE'}
response = requests.get('https://api.example.com/private-data', headers=headers)
print(response.status_code) # 200 OKThe simplest form of authentication. You get a unique key and include it with each request.
import requests
api_key = 'YOUR_API_KEY_HERE'
headers = {
'X-API-Key': api_key
# or 'Authorization': f'ApiKey {api_key}'
}
response = requests.get(
'https://api.example.com/data',
headers=headers
)
print(response.json())import requests
api_key = 'YOUR_API_KEY_HERE'
params = {
'api_key': api_key
}
response = requests.get(
'https://api.example.com/data',
params=params
)
print(response.json())import requests
api_key = 'YOUR_OPENWEATHERMAP_API_KEY'
response = requests.get(
'https://api.openweathermap.org/data/2.5/weather',
params={
'q': 'London',
'appid': api_key,
'units': 'metric'
}
)
if response.status_code == 200:
weather = response.json()
print(f"Temperature: {weather['main']['temp']}°C")
print(f"Description: {weather['weather'][0]['description']}")
else:
print(f"Error: {response.status_code}")Bearer tokens are commonly used for OAuth 2.0 and JWT (JSON Web Token) authentication.
import requests
# Get token from login endpoint
login_response = requests.post(
'https://api.example.com/login',
json={
'email': 'user@example.com',
'password': 'password123'
}
)
if login_response.status_code == 200:
token = login_response.json()['token']
# Use token for authenticated requests
headers = {
'Authorization': f'Bearer {token}'
}
response = requests.get(
'https://api.example.com/user/profile',
headers=headers
)
user = response.json()
print(f"User: {user['name']}")
else:
print("Login failed")import requests
import time
class APIClient:
def __init__(self, base_url, email, password):
self.base_url = base_url
self.email = email
self.password = password
self.token = None
self.token_expiry = 0
def refresh_token(self):
"""Get a new token"""
response = requests.post(
f'{self.base_url}/login',
json={
'email': self.email,
'password': self.password
}
)
if response.status_code == 200:
data = response.json()
self.token = data['token']
self.token_expiry = time.time() + data.get('expires_in', 3600)
return True
return False
def get_headers(self):
"""Get headers with valid token"""
if time.time() >= self.token_expiry:
self.refresh_token()
return {
'Authorization': f'Bearer {self.token}'
}
def get(self, endpoint):
"""Make authenticated GET request"""
response = requests.get(
f'{self.base_url}/{endpoint}',
headers=self.get_headers()
)
if response.status_code == 401:
# Token expired, refresh and retry
self.refresh_token()
response = requests.get(
f'{self.base_url}/{endpoint}',
headers=self.get_headers()
)
return response.json() if response.ok else None
# Using the client
client = APIClient(
'https://api.example.com',
'user@example.com',
'password123'
)
user = client.get('user/profile')
if user:
print(f"User: {user}")Username and password sent with each request (usually over HTTPS).
import requests
from requests.auth import HTTPBasicAuth
username = 'john_doe'
password = 'secure_password'
# Method 1: Using HTTPBasicAuth
response = requests.get(
'https://api.example.com/data',
auth=HTTPBasicAuth(username, password)
)
# Method 2: Tuple shorthand
response = requests.get(
'https://api.example.com/data',
auth=(username, password)
)
# Method 3: Manual header (base64 encoded)
import base64
credentials = base64.b64encode(f'{username}:{password}'.encode()).decode()
headers = {
'Authorization': f'Basic {credentials}'
}
response = requests.get(
'https://api.example.com/data',
headers=headers
)
print(response.json())OAuth 2.0 is a standard for secure third-party authentication without sharing passwords.
import requests
from urllib.parse import urlencode, parse_qs
from urllib.request import urlopen
class OAuth2Client:
def __init__(self, client_id, client_secret, redirect_uri):
self.client_id = client_id
self.client_secret = client_secret
self.redirect_uri = redirect_uri
self.token = None
def get_authorization_url(self, auth_url):
"""Generate URL for user to authorize"""
params = {
'client_id': self.client_id,
'redirect_uri': self.redirect_uri,
'response_type': 'code',
'scope': 'read write'
}
return f"{auth_url}?{urlencode(params)}"
def exchange_code_for_token(self, token_url, code):
"""Exchange authorization code for access token"""
data = {
'client_id': self.client_id,
'client_secret': self.client_secret,
'code': code,
'redirect_uri': self.redirect_uri,
'grant_type': 'authorization_code'
}
response = requests.post(token_url, data=data)
if response.status_code == 200:
self.token = response.json()['access_token']
return True
return False
def get_with_token(self, resource_url):
"""Make authenticated request with token"""
headers = {
'Authorization': f'Bearer {self.token}'
}
response = requests.get(resource_url, headers=headers)
return response.json() if response.ok else None
# Using OAuth 2.0
oauth = OAuth2Client(
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
redirect_uri='https://myapp.com/callback'
)
# Step 1: Direct user to authorization URL
auth_url = oauth.get_authorization_url('https://provider.com/oauth/authorize')
print(f"Visit: {auth_url}")
# Step 2: After user authorizes, you get code from redirect
code = 'AUTHORIZATION_CODE_HERE'
# Step 3: Exchange code for token
if oauth.exchange_code_for_token('https://provider.com/oauth/token', code):
# Step 4: Use token to access resources
user = oauth.get_with_token('https://api.provider.com/user')
print(f"User: {user}")import os
from dotenv import load_dotenv
# Load from environment variables
load_dotenv() # pip install python-dotenv
api_key = os.getenv('API_KEY')
api_secret = os.getenv('API_SECRET')
# ❌ Never hardcode credentials
# api_key = 'abc123def456'
# Make request with safe credentials
headers = {
'X-API-Key': api_key
}
response = requests.get('https://api.example.com/data', headers=headers)import requests
from typing import Dict, Optional
class AuthenticatedAPIClient:
"""API client with built-in authentication"""
def __init__(self, base_url: str, auth_type: str, credentials: Dict):
self.base_url = base_url
self.auth_type = auth_type
self.credentials = credentials
self.session = requests.Session()
self._setup_auth()
def _setup_auth(self):
"""Configure session with authentication"""
if self.auth_type == 'api_key':
self.session.headers.update({
'X-API-Key': self.credentials['api_key']
})
elif self.auth_type == 'bearer':
self.session.headers.update({
'Authorization': f"Bearer {self.credentials['token']}"
})
elif self.auth_type == 'basic':
self.session.auth = (
self.credentials['username'],
self.credentials['password']
)
def get(self, endpoint: str, **kwargs) -> Optional[Dict]:
"""Make authenticated GET request"""
try:
response = self.session.get(
f'{self.base_url}/{endpoint}',
timeout=5,
**kwargs
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
def post(self, endpoint: str, data: Dict, **kwargs) -> Optional[Dict]:
"""Make authenticated POST request"""
try:
response = self.session.post(
f'{self.base_url}/{endpoint}',
json=data,
timeout=5,
**kwargs
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Using the client with API key
client = AuthenticatedAPIClient(
base_url='https://api.example.com',
auth_type='api_key',
credentials={'api_key': 'YOUR_API_KEY'}
)
data = client.get('users')import requests
def make_authenticated_request(url, headers, max_retries=1):
"""Make request and handle 401 errors"""
for attempt in range(max_retries):
response = requests.get(url, headers=headers, timeout=5)
if response.status_code == 401:
print("Authentication failed. Check your credentials.")
return None
if response.status_code == 403:
print("Authenticated but permission denied.")
return None
if response.ok:
return response.json()
print(f"Error: {response.status_code}")
return None
return None
# Usage
headers = {'Authorization': 'Bearer INVALID_TOKEN'}
data = make_authenticated_request('https://api.example.com/data', headers)| Method | Use Case | Example |
|---|---|---|
| API Key | Simple, public APIs | `headers = {'X-API-Key': key}` |
| Basic Auth | Internal APIs | `auth=(username, password)` |
| Bearer Token | OAuth 2.0, JWT | `Authorization: Bearer token` |
| OAuth 2.0 | Third-party services | Multi-step authorization |
| Store Safely | All methods | Use environment variables |
| Handle 401 | All methods | Check credentials when unauthorized |
Learn about rate limiting and how to work within API constraints.
Ready to practice? Try challenges or explore resources
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward