Key Server OAuth
TheKeyServerClient enables dApps to verify user ownership of GitHub and Discord accounts through the Key Server OAuth flow. Each successful verification produces a DAHR (Demos Attestation Hash Response) attestation - a cryptographic proof that the Key Server performed the verification.
Installation
The KeyServerClient is included in the SDK:Quick Start
API Reference
KeyServerClient
Constructor
getProviders()
Get list of available OAuth providers.initiateOAuth()
Start an OAuth flow and get the authorization URL.pollOAuth()
Check the status of an OAuth flow.verifyOAuth()
Complete OAuth flow with automatic polling (recommended).Types
OAuthUserInfo
User identity information from OAuth provider.WalletBinding
Wallet binding for proving ownership during OAuth verification.demos-oauth-bind:{state} where state is from initiateOAuth().
DAHRAttestation
Cryptographic proof of verification.Attestation Verification
You can cryptographically verify that the Key Server actually signed the attestation:Verification Options
| Option | Type | Default | Description |
|---|---|---|---|
maxAge | number | 3600000 | Max attestation age in ms. Set to 0 to disable. |
expectedNodePubKey | string | - | Validate the attestation came from a specific node |
Error Handling
The client throwsOAuthError for all OAuth-related errors:
Error Codes
| Code | Description |
|---|---|
OAUTH_INVALID_SERVICE | Invalid OAuth provider specified |
OAUTH_NOT_CONFIGURED | OAuth not configured on server |
OAUTH_NOT_AVAILABLE | OAuth service unavailable |
OAUTH_DENIED | User denied authorization |
OAUTH_EXPIRED | OAuth flow expired |
OAUTH_PROVIDER_ERROR | Error from OAuth provider |
OAUTH_STATE_NOT_FOUND | Invalid or expired state |
OAUTH_STATE_MISMATCH | State parameter mismatch |
OAUTH_TIMEOUT | Polling timed out |
NETWORK_ERROR | Network connection error |
INTERNAL_ERROR | Internal server error |
Wallet Binding
Wallet binding allows you to cryptographically prove ownership of a blockchain wallet during OAuth verification. The wallet address and signature are included in the DAHR attestation, creating a verifiable link between the OAuth identity and the wallet.Why Use Wallet Binding?
- Sybil Resistance: Link social accounts to wallets to prevent one person from claiming multiple identities
- Access Control: Gate access based on both wallet and verified social identity
- Attestation Integrity: The wallet binding is part of the signed attestation, tamper-proof
How It Works
- User initiates OAuth flow
- dApp receives the
stateparameter inonAuthUrlcallback - User signs message
demos-oauth-bind:{state}with their wallet - Signature is sent with subsequent poll requests
- Key Server verifies the signature and includes binding in attestation
Usage
You can provide wallet binding as a function that receives the state:Supported Signature Types
| Type | Description | Message Format |
|---|---|---|
evm | Ethereum/EVM personal_sign or eth_sign | UTF-8 string |
solana | Solana signMessage | UTF-8 bytes |
ed25519 | Raw Ed25519 signature | UTF-8 bytes |
Full Example
Complete example with UI feedback and wallet binding:Architecture
The Key Server OAuth flow works as follows:- dApp calls
KeyServerClient.verifyOAuth() - SDK sends request to Node RPC
- Node proxies to Key Server (same host)
- Key Server redirects user to GitHub/Discord
- User authorizes, Key Server receives callback
- Key Server creates DAHR attestation
- Attestation returned through the chain to dApp
The Key Server and Node communicate on the same host, so no signatures are needed for this internal communication. The DAHR attestation provides cryptographic proof to external parties.