This document details how third-party merchants can integrate BTSBots Decentralized Identity (DID) authentication using BitShares blockchain accounts and ECDSA signatures.
[ User Browser / PC ] ------ (1) Initiate Login / Show QR -------> [ Merchant Web Site ]
| |
(2) Redirect to OAuth (3) Poll Login Status
or Scan with Mobile App |
v v
[ BTSBots Client / Web ] - (4) Sign Intent via WebCrypto -> [ BTSBots DDP Cloud Server ]
|
(5) Fetch & Verify Signature v
[ Merchant BizBots Daemon ] <---- (6) HTTP POST Push Signed Proof --------+
Crucial Note: When using biz_proxy, merchants MUST STILL configure biz_rules.json to point the oauth_endpoint URL directly to the /biz-proxy/sync-login endpoint provided by biz_proxy.py:
{
"description": "BTSBots OAuth Rules",
"updated_at": "2026-08-12 19:54:52",
"oauth_endpoint": {
"my-shop.com": "https://my-shop.com/biz-proxy/sync-login"
}
}
uv run python biz_proxy.py \
--host 127.0.0.1 \
--port 9000 \
<merchant_bts_account> \
<merchant_bts_pubkey>
{
"description": "Merchant App OAuth Rules",
"updated_at": "2026-08-12 20:00:00",
"oauth_endpoint": {
"my-shop.com": "https://api.my-shop.com/v1/auth/bts-callback"
}
}
import json
import time
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from btsbots.graphene_light import verify_message as bts_verify_message
app = FastAPI()
TRUSTED_BIZ_BOT_PUBKEY = "BTS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
class OAuthCallbackPayload(BaseModel):
data: str
pubkey: str
signature: str
@app.post("/v1/auth/bts-callback")
async def bts_oauth_callback(payload: OAuthCallbackPayload):
if payload.pubkey != TRUSTED_BIZ_BOT_PUBKEY:
raise HTTPException(status_code=403, detail="Untrusted public key source")
if not bts_verify_message(payload.data, payload.signature, payload.pubkey):
raise HTTPException(status_code=400, detail="Invalid cryptographic signature")
auth_info = json.loads(payload.data)
username = auth_info.get("username")
token = auth_info.get("token")
auth_time = auth_info.get("time")
if abs(time.time() - auth_time) > 300:
raise HTTPException(status_code=400, detail="Authorization request expired")
print(f"π User {username} logged in successfully via BitShares DID! Token: {token}")
return {"status": "success", "username": username}