Provides a simple OAuth server deployed as an AWS Lambda function, intended to support development with Localstack
Project description
Simple OAuth Server
A lightweight OAuth 2.0 server deployable to AWS Lambda, designed for development and testing environments. Provides RS256 JWT token issuance, validation, and JWKS endpoint support for securing REST APIs.
Key Features
- Token Issuance: Client credentials flow with RS256 JWTs
- Token Validation: AWS API Gateway Lambda authorizer integration
- JWKS Endpoint: RFC 7517 compliant public key discovery
- Token Decoder: Optional JWT validation decorator for Lambda functions
- Automatic Key Generation: RSA key pairs created during deployment
- Flexible Configuration: YAML-based client and permission setup
Quick Start
Prerequisites
- AWS account with credentials configured
- Pulumi CLI installed
- Python 3.9+ environment
Basic Deployment
# __main__.py
import simple_oauth_server
# Define test clients
config = """
clients:
api_client:
client_secret: "my-secret-key"
audience: "my-api"
sub: "api-user-1"
scope: "read:data write:data"
permissions:
- "read:data"
- "write:data"
admin_client:
client_secret: "admin-secret"
audience: "my-api"
sub: "admin-user"
scope: "*:*"
roles: ["admin"]
permissions:
- "admin"
"""
# Deploy OAuth server
oauth_server = simple_oauth_server.start("oauth", config=config)
Deploy with Pulumi:
pulumi up
The server automatically generates RSA key pairs and deploys three Lambda functions:
- Token issuer (
POST /token) - Token validator (API Gateway authorizer)
- JWKS endpoint (
GET /.well-known/jwks.json)
Usage
Token Issuance
Request bearer tokens using client credentials:
curl --request POST \
--url https://your-oauth-server/token \
--header 'Content-Type: application/json' \
--data '{
"client_id": "api_client",
"client_secret": "my-secret-key",
"audience": "my-api",
"grant_type": "client_credentials"
}'
Response:
{
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 86400
}
JWKS Endpoint
Public key discovery for token validation:
curl --request GET \
--url https://your-oauth-server/.well-known/jwks.json
Returns RSA public keys in JWK format for signature verification.
API Gateway Integration
Configure the token validator as a Lambda authorizer in AWS API Gateway:
- Create Lambda authorizer using the deployed validator function
- Configure API routes to use the authorizer
- Clients include tokens in requests:
curl --request GET \
--url https://your-api-gateway/my-api/data \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...'
The validator checks token signature, expiration, audience, and scopes, then returns an IAM policy allowing access to authorized resources.
Token Decoder (Optional)
For Lambda functions that need to validate JWTs directly:
from simple_oauth_server.token_decoder import token_decoder
@token_decoder(
jwks_url="https://your-oauth-server/.well-known/jwks.json",
audience="my-api",
issuer="https://oauth.local/"
)
def my_lambda_handler(event, context):
# JWT claims available in event['requestContext']['authorizer']
authorizer = event.get('requestContext', {}).get('authorizer', {})
user_id = authorizer.get('sub', 'unknown')
scopes = authorizer.get('scope', '').split()
return {
'statusCode': 200,
'body': f'Hello {user_id}, scopes: {scopes}'
}
Configuration
Client Configuration
Define clients in YAML format with credentials and permissions:
clients:
client_name:
client_secret: "secret-key" # Required: client authentication
audience: "api-identifier" # Required: target API
sub: "user-identity" # Required: subject claim
scope: "read:data write:data" # Optional: OAuth scopes
permissions: # Optional: fine-grained permissions
- "read:data"
- "write:data"
roles: ["user", "admin"] # Optional: role metadata
groups: ["team-a"] # Optional: group metadata
Environment Variables
Configure at runtime:
# Token issuer/validator settings
export ISSUER="https://oauth.local/"
# Permission-to-resource mapping for IAM policies
export AUTH0_AUTH_MAPPINGS='{
"read:data": [{"method": "GET", "resourcePath": "/data"}],
"admin": [{"method": "*", "resourcePath": "*"}]
}'
JWT Claims
Issued tokens include:
Standard Claims:
iss: Issuer (from ISSUER env var)sub: Subject (from client config)aud: Audience (from client config)iat: Issued at timestampexp: Expiration timestamp
Custom Claims:
scope: Space-delimited OAuth scopespermissions: Array of permission stringsroles: Array of role stringsgroups: Array of group strings
Scope Validation
The validator derives required scopes from API Gateway method ARN:
GET /data→ requiresread:dataPOST /data→ requireswrite:dataDELETE /data/{id}→ requiresdelete:data
Wildcards supported: read:*, write:*, *:*
Authorizer Context
Successful validation provides context to backend APIs:
{
"principalId": "user-identity",
"context": {
"sub": "user-identity",
"scope": "read:data write:data",
"scopes": "read:data write:data",
"roles": "[\"user\", \"admin\"]",
"groups": "[\"team-a\"]",
"permissions": "[\"read:data\", \"write:data\"]"
}
}
Development & Testing
Running Tests
# Install test dependencies and run tests
hatch run test:pytest
# Run with coverage
hatch run test:pytest --cov=simple_oauth_server
# Run specific test categories
hatch run test:pytest tests/test_authorizer.py
hatch run test:pytest tests/test_validator.py
Local Development
For testing without AWS deployment:
# Generate RSA keys manually (optional - deployment auto-generates)
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
# Set environment variables
export ISSUER="https://oauth.local/"
export AUTH0_AUTH_MAPPINGS='{"read:pets": [{"method": "GET", "resourcePath": "/pets"}]}'
LocalStack Integration
The project includes LocalStack support for testing AWS Lambda deployment locally without AWS costs.
Test Environment
Uses Hatch for dependency management with dedicated test environment including:
- pytest for test execution
- pytest-cov for coverage reporting
- requests for HTTP client testing
- AsymmetricKeyPair utility for ephemeral test keys
API Reference
Lambda Handlers
- Token Issuer:
simple_oauth_server.token_authorizer::handler - Token Validator:
simple_oauth_server.token_validator::handler - JWKS Endpoint:
simple_oauth_server.jwks_handler::handler
Key Modules
token_decoder.py: JWT validation decorator for Lambda functionsasymmetric_key_pair.py: RSA key pair generation utilities- Configuration files: YAML client definitions with credentials and permissions
Deployment Components
The simple_oauth_server.start() function creates:
- Lambda functions for token issuance, validation, and JWKS
- API Gateway endpoints with proper routing
- RSA key pair generation and packaging
- IAM roles and policies for Lambda execution
For complete examples and advanced configuration options, see the test files in the tests/ directory.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file simple_oauth_server-0.1.4.tar.gz.
File metadata
- Download URL: simple_oauth_server-0.1.4.tar.gz
- Upload date:
- Size: 20.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aab28327dc40c3c9a2704769dcaf3a5d4bdc962a75f7e262cd618b1766444a5f
|
|
| MD5 |
77efc64f5488b0a7a04f6037096988e6
|
|
| BLAKE2b-256 |
3638960ecde2f4ee1582b49faa6f4f94880286a19eaeb912ee2c3ef02a798a25
|
File details
Details for the file simple_oauth_server-0.1.4-py3-none-any.whl.
File metadata
- Download URL: simple_oauth_server-0.1.4-py3-none-any.whl
- Upload date:
- Size: 26.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.28.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a5dd244a4e1c87679c48834c355cef5e387419c49b7779d8bc776f7b79f275b
|
|
| MD5 |
de078ae564db01e73494128d9c7bb04a
|
|
| BLAKE2b-256 |
db20dd4e665b3b96ccccd2e464c8495886dc428f5e2766549e0f9f5bfd6950d9
|