Skip to main content

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: str parameter (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 framework
  • starlette - ASGI toolkit
  • solders - Solana SDK (for types)
  • base58 - Base58 encoding
  • pynacl - Ed25519 signature verification

📚 Documentation


🪪 License

MIT

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

openkitx403-0.1.5.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openkitx403-0.1.5-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

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

Hashes for openkitx403-0.1.5.tar.gz
Algorithm Hash digest
SHA256 e8fd34d5f37b31c4c39ceecca200db5da4d42e2c6f5effd09faf7a4b01207549
MD5 b236e2afdc3578cabad938993864b023
BLAKE2b-256 af8f523377cb7ce0afb5e745dc965e45bd71b2acefe4ef5a44f89ffc9696d418

See more details on using hashes here.

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

Hashes for openkitx403-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 bb370f2041b2000d137ac3e3146f82e7564626e991ac5161b05e9d105a32f4a3
MD5 a0248f761abde1bccc1af3f461f5c205
BLAKE2b-256 fe6af0faedd0954f28822bacfa03382159ae9a814aff9e4b2325147d6763d729

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page