Python server SDK for OpenKitx403 wallet authentication
Project description
openkitx403 — Python Server SDK
FastAPI middleware for OpenKitx403 wallet-based authentication. Add Solana wallet verification to any API endpoint with one line.
🚀 Installation
pip install openkitx403
# or
poetry add openkitx403
⚡ Quick Start
from fastapi import FastAPI, Depends
from openkitx403 import OpenKit403Middleware, require_openkitx403_user
app = FastAPI(title="My Wallet-Protected API")
# Attach OpenKitx403 middleware
app.add_middleware(
OpenKit403Middleware,
audience="https://api.example.com",
issuer="my-api-v1",
ttl_seconds=60,
bind_method_path=False, # Set True to bind challenges to specific paths
origin_binding=False,
replay_backend="memory"
)
@app.get("/protected")
async def protected(user = Depends(require_openkitx403_user)):
"""Example protected endpoint"""
return {
"message": f"Authenticated as {user.address}",
"wallet": user.address
}
@app.get("/public")
async def public():
"""Public endpoint - no authentication required"""
return {"message": "Hello World"}
🔒 Optional Token Gating
from openkitx403 import OpenKit403Middleware
from solana.rpc.api import Client
from solders.pubkey import Pubkey
solana_client = Client("https://api.mainnet-beta.solana.com")
async def check_token_holder(address: str) -> bool:
"""Example: verify wallet holds specific token"""
try:
pubkey = Pubkey.from_string(address)
resp = solana_client.get_token_accounts_by_owner(
pubkey,
opts={"mint": str(Pubkey.from_string("YOUR_TOKEN_MINT"))}
)
return len(resp.value) > 0
except Exception as e:
print("Token check failed:", e)
return False
app.add_middleware(
OpenKit403Middleware,
audience="https://api.example.com",
issuer="my-api-v1",
token_gate=check_token_holder,
)
🛤️ Exclude Paths from Authentication
app.add_middleware(
OpenKit403Middleware,
audience="https://api.example.com",
issuer="my-api-v1",
excluded_paths=["/health", "/docs", "/openapi.json"]
)
🧩 API Reference
OpenKit403Middleware
FastAPI middleware that adds OpenKitx403 authentication to your routes.
Configuration Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
audience |
str |
required | Expected API audience/origin |
issuer |
str |
required | Server identifier |
ttl_seconds |
int |
60 |
Challenge TTL in seconds |
clock_skew_seconds |
int |
120 |
Allowed clock skew for timestamp validation |
bind_method_path |
bool |
False |
Bind challenge to specific HTTP method/path |
origin_binding |
bool |
False |
Enable origin header validation |
ua_binding |
bool |
False |
Enable user-agent header validation |
replay_backend |
str |
"memory" |
Replay protection backend |
token_gate |
Callable[[str], bool] |
None |
Optional async function for wallet gating |
excluded_paths |
list[str] |
None |
Paths that bypass authentication |
🔐 Token Gate Function Signature
Your token gate function must:
- Accept a single
address: strparameter (base58-encoded public key) - Return
bool(True = allowed, False = denied) - Can be async or sync
async def my_token_gate(address: str) -> bool:
# Your validation logic
return True # or False
🎯 Accessing User Information
Use the require_openkitx403_user dependency to access authenticated user:
from fastapi import Depends
from openkitx403 import require_openkitx403_user, OpenKit403User
@app.get("/profile")
async def profile(user: OpenKit403User = Depends(require_openkitx403_user)):
return {
"address": user.address,
"challenge": user.challenge # Original challenge object
}
🔧 Custom Replay Store
By default, middleware uses in-memory replay protection. For production with multiple servers:
from openkitx403 import ReplayStore
class RedisReplayStore:
"""Example Redis-based replay store"""
def __init__(self, redis_client):
self.redis = redis_client
async def check(self, key: str, ttl_seconds: int) -> bool:
return await self.redis.exists(key)
async def store(self, key: str, ttl_seconds: int) -> None:
await self.redis.setex(key, ttl_seconds, "1")
# Use custom store
app.add_middleware(
OpenKit403Middleware,
audience="https://api.example.com",
issuer="my-api-v1",
replay_store=RedisReplayStore(redis_client)
)
🔑 Dependencies
fastapi- Web frameworkstarlette- ASGI toolkitsolders- Solana SDK (for types)base58- Base58 encodingpynacl- Ed25519 signature verification
📚 Documentation
🪪 License
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 openkitx403-0.1.5.tar.gz.
File metadata
- Download URL: openkitx403-0.1.5.tar.gz
- Upload date:
- Size: 8.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.13.6 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8fd34d5f37b31c4c39ceecca200db5da4d42e2c6f5effd09faf7a4b01207549
|
|
| MD5 |
b236e2afdc3578cabad938993864b023
|
|
| BLAKE2b-256 |
af8f523377cb7ce0afb5e745dc965e45bd71b2acefe4ef5a44f89ffc9696d418
|
File details
Details for the file openkitx403-0.1.5-py3-none-any.whl.
File metadata
- Download URL: openkitx403-0.1.5-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.13.6 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb370f2041b2000d137ac3e3146f82e7564626e991ac5161b05e9d105a32f4a3
|
|
| MD5 |
a0248f761abde1bccc1af3f461f5c205
|
|
| BLAKE2b-256 |
fe6af0faedd0954f28822bacfa03382159ae9a814aff9e4b2325147d6763d729
|