Skip to content
View openkitx403's full-sized avatar

Block or report openkitx403

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Maximum 250 characters. Please don't include any personal information such as legal names or email addresses. Markdown supported. This note will be visible to only you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
openkitx403/README.md

OpenKitx403

HTTP-native wallet authentication protocol for Solana.

OpenKitx403 is an open-source, TypeScript-first protocol that standardizes HTTP 403 as the semantic "prove you control this wallet" challenge for Solana wallet authentication.

npm client npm server PyPI server PyPI client License: MIT

HTTP-native wallet authentication for Solana

Features

  • HTTP-native: Uses standard HTTP 403 challenges
  • Stateless: No server-side sessions required
  • Secure: Ed25519 signature verification with replay protection
  • Easy to use: Drop-in middleware for Express, Fastify, and FastAPI
  • Production-ready: Full TypeScript and Python SDKs
  • AI-friendly: LangChain integration and agent support
  • Token-gating ready: Built-in support for NFT/token requirements

πŸ“¦ Installation

TypeScript Client (Browser/Node)

npm install @openkitx403/client

TypeScript Server (Express/Fastify)

npm install @openkitx403/server

Python Server (FastAPI)

pip install openkitx403

or
poetry add openkitx403

πŸš€ Quick Start

Browser Client

import { OpenKit403Client } from '@openkitx403/client';

const client = new OpenKit403Client();

// Connect wallet
await client.connect('phantom');

// Authenticate with API
const response = await client.authenticate({
    resource: 'https://api.example.com/protected',
    method: 'GET'
});

if (response.ok) {
    const data = await response.json();
    console.log('βœ… Authenticated as:', client.getAddress());
    console.log('Data:', data);
} else {
    console.error('❌ Authentication failed:', response.status);
}

Express Server

import express from 'express';
import { createOpenKit403, inMemoryLRU } from '@openkitx403/server';

const app = express();

const openkit = createOpenKit403({
    issuer: 'my-api-v1',
    audience: 'https://api.example.com',
    ttlSeconds: 60,
    bindMethodPath: true,
    replayStore: inMemoryLRU()
});

app.use(openkit.middleware());

app.get('/protected', (req, res) => {
const user = req.openkitx403User;
res.json({ message: 'Hello!', wallet: user.address });
});

app.listen(3000);

FastAPI Server

from fastapi import FastAPI, Depends
from openkitx403 import OpenKit403Middleware, require_openkitx403_user

app = FastAPI()

app.add_middleware(
OpenKit403Middleware,
    audience="https://api.example.com",
    issuer="my-api-v1",
    ttl_seconds=60,
    bind_method_path=True,
    replay_backend="memory"
)

@app.get("/protected")
async def protected(user=Depends(require_openkitx403_user)):
    return {"message": "Hello!", "wallet": user.address}

🎯 How It Works

  1. Client requests a protected resource β†’ 403 Forbidden
  2. Server responds with WWW-Authenticate: OpenKitx403 ... header containing a challenge
  3. Client asks user's Solana wallet (Phantom/Backpack/Solflare) to sign the challenge
  4. Client re-sends request with Authorization: OpenKitx403 ... header
  5. Server verifies signature and grants access β†’ 200 OK

Client Server | | | GET /protected | |----------------------------->| | | | 403 + Challenge | |<-----------------------------| | | | [User signs with wallet] | | | | GET /protected + Auth | |----------------------------->| | | | 200 OK + Data | |<-----------------------------|

Security Features

  • Short-lived challenges (60s default TTL)
  • Replay protection via nonce store
  • Method/path binding prevents cross-endpoint replay
  • Origin/User-Agent binding (optional)
  • Clock skew tolerance (Β±120s default)
  • Token-gating support for NFT/SPL token requirements

Documentation

Wallet Compatibility

Wallet Browser Mobile Status
Phantom βœ… ⚠️ Via WalletConnect Supported
Backpack βœ… ❌ Supported
Solflare βœ… ⚠️ Via WalletConnect Supported

AI Agent & LangChain Integration

OpenKitx403 supports autonomous agents and LangChain tools:

import { SolanaWalletAuthTool } from '@openkitx403/langchain';
import { initializeAgentExecutorWithOptions } from 'langchain/agents';

const tools = [new SolanaWalletAuthTool()];
const executor = await initializeAgentExecutorWithOptions(tools, model, {
    agentType: "zero-shot-react-description"
});

const result = await executor.call({
    input: "Connect my wallet and fetch my NFT collection"
});

See USAGE_EXAMPLES.md for complete examples.

πŸ“Š Package Structure

openkitx403/ β”œβ”€β”€ packages/ β”‚ β”œβ”€β”€ ts-client/ # Browser & Node.js SDK β”‚ β”œβ”€β”€ ts-server/ # Express & Fastify middleware β”‚ β”œβ”€β”€ py-server/ # FastAPI middleware β”‚ └── examples/ # Demo applications β”œβ”€β”€ docs/ # Protocol specification β”œβ”€β”€ tests/ # Test suites └── USAGE_EXAMPLES.md # Complete usage guide

πŸ§ͺ Testing

Install dependencies
npm install

Build all packages
npm run build

Run tests
npm run test
npm run test --workspace=packages/ts-client
npm run test --workspace=packages/ts-server

Python tests
cd packages/py-server
pytest

Advanced Features

Token Gating

const openkit = createOpenKit403({
    issuer: 'my-api',
    audience: 'https://api.example.com',
    tokenGate: async (address: string) => {
        // Check if wallet holds required NFT/token
        const hasToken = await checkTokenHolding(address);
        return hasToken;
    }
});

Custom Replay Store

class RedisReplayStore implements ReplayStore {
    async check(key: string, ttl: number): Promise<boolean> {
        return await redis.exists(key);
    }

    async store(key: string, ttl: number): Promise<void> {
        await redis.setex(key, ttl, '1');
    }
}

const openkit = createOpenKit403({
    replayStore: new RedisReplayStore()
});

Contributing

Contributions welcome! Please read CONTRIBUTING.md first.

πŸ“„ License

MIT License - see LICENSE

Acknowledgments

Inspired by the "HTTP-native + wallet + open" philosophy, OpenKitx403 is built from scratch with:

  • Different header names and message format
  • Enhanced security model
  • Production-grade implementations
  • Comprehensive documentation

Links

Support


Built with ❀️ for the Solana ecosystem

Popular repositories Loading

  1. openkitx403-docs openkitx403-docs Public

    $ HTTP-native wallet authentication for Solana. Uses HTTP 403 as the primitive. Wallets sign challenges. No custom protocols. No account secrets.

    HTML 1

  2. openkitx403 openkitx403 Public

    HTTP-native wallet authentication for Solana. Uses HTTP 403 as the primitive. Wallets sign challenges. No custom protocols. No account secrets.

    TypeScript 1 1

  3. openkitx403-demo-apps openkitx403-demo-apps Public

    demo apps using openkitx403. in action

    Python

  4. openkit403-go openkit403-go Public

    Production-ready Openkitx403 Go SDK

    Go

  5. openkit403-rust openkit403-rust Public

    Production-ready Openkitx403 Rust SDK

    Rust