On-Chain Authorization
Stake-based service registration system using DNS verification and UCAN capabilities for decentralized authentication and authorization
On-Chain Authorization
Scope
This document covers Sonr's service registration and authorization system, including stake-based trust models, DNS verification, UCAN capability delegation, and reputation tracking. It explains technical architecture, integration patterns, and economic incentives. This document does not cover implementation details or pricing comparisons—see the Service Module reference for technical specifications.
Audience
Service developers building authenticated applications. System architects designing authorization systems. Validators participating in service verification. Prerequisites: Understanding of DNS verification, capability-based security, and stake-based economics.
Summary
Sonr implements on-chain service authorization through stake-based registration, DNS verification, and UCAN capabilities. Services stake SNR tokens to register, prove domain ownership via DNS TXT records, and request user permissions through capability tokens. The system builds trust through successful authentication metrics, creating decentralized reputation without central authorities.
Architecture Overview
Core Components
The service authorization system consists of four components:
- Service Registry: On-chain registry of verified services
- DNS Verification: Domain ownership proof via TXT records
- Stake Management: Economic incentives through token staking
- Reputation Tracking: Performance metrics and trust scores
System Flow
Technical Implementation
Service Registration
Services register through staking and domain verification:
// Service registration structure
interface ServiceRegistration {
domain: string; // Verified domain
stakeAmount: number; // SNR tokens staked
capabilities: string[]; // Requested permissions
operator: string; // Service operator DID
}
// Registration process
async function registerService(params: ServiceRegistration) {
// 1. Verify minimum stake
if (params.stakeAmount < MIN_STAKE) {
throw new Error("Insufficient stake");
}
// 2. Verify domain ownership
const verified = await verifyDomain(params.domain);
if (!verified) {
throw new Error("Domain verification failed");
}
// 3. Lock stake
await lockStake(params.operator, params.stakeAmount);
// 4. Register on-chain
return await registry.register(params);
}
Trust Score Calculation
Reputation emerges from authentication metrics:
interface TrustMetrics {
totalAuthentications: number;
successRate: number; // Percentage (0-100)
avgResponseTime: number; // Milliseconds
userSatisfaction: number; // Score (0-10)
timeActive: number; // Days since registration
slashingEvents: number; // Count of penalties
}
function calculateTrustScore(metrics: TrustMetrics, stake: number): number {
// Weight components
const stakeWeight = Math.min(stake / 10000, 1) * 0.25;
const successWeight = (metrics.successRate / 100) * 0.3;
const volumeWeight = Math.min(metrics.totalAuthentications / 100000, 1) * 0.2;
const timeWeight = Math.min(metrics.timeActive / 365, 1) * 0.15;
const satisfactionWeight = (metrics.userSatisfaction / 10) * 0.1;
// Apply penalties
const slashingPenalty = metrics.slashingEvents * 0.1;
// Calculate final score (0-1000)
return Math.max(
0,
(stakeWeight +
successWeight +
volumeWeight +
timeWeight +
satisfactionWeight) *
1000 -
slashingPenalty,
);
}
Slashing Conditions
Staked tokens are slashed for violations:
type SlashingCondition struct {
Type string
Severity string // minor, major, severe
Penalty sdk.Dec // Percentage of stake
}
var slashingConditions = []SlashingCondition{
// Minor violations (1-5%)
{"slow_response", "minor", sdk.NewDec(1)},
{"user_complaint", "minor", sdk.NewDec(2)},
{"downtime", "minor", sdk.NewDec(3)},
// Major violations (10-30%)
{"data_breach", "major", sdk.NewDec(25)},
{"privacy_violation", "major", sdk.NewDec(30)},
// Severe violations (50-100%)
{"malicious_behavior", "severe", sdk.NewDec(75)},
{"fraud", "severe", sdk.NewDec(100)},
}
DNS Verification
Registration Process
Services prove domain ownership through DNS TXT records:
# 1. Initiate verification
sonrd tx svc initiate-domain-verification example.com --from alice
# 2. Add TXT record to DNS provider
TXT: sonr-verification=a1b2c3d4e5f6789...
# 3. Verify ownership
sonrd tx svc verify-domain example.com --from alice
# 4. Register service
sonrd tx svc register-service my-app example.com \
--capabilities="dwn:read,dwn:write,payment:request" \
--stake-amount=5000 \
--from alice
Verification Implementation
DNS verification uses standard TXT record lookup:
func (k Keeper) VerifyDomainOwnership(
ctx context.Context,
domain string,
) error {
// Get verification token
verification, err := k.DomainVerifications.Get(ctx, domain)
if err != nil {
return err
}
// Lookup DNS TXT records
expectedRecord := fmt.Sprintf(
"sonr-verification=%s",
verification.VerificationToken,
)
txtRecords, err := net.LookupTXT(domain)
if err != nil {
return fmt.Errorf("DNS lookup failed: %w", err)
}
// Check for verification record
for _, record := range txtRecords {
if strings.TrimSpace(record) == expectedRecord {
verification.Status = VERIFIED
return k.DomainVerifications.Save(ctx, verification)
}
}
return fmt.Errorf("verification record not found")
}
DNS Provider Compatibility
Works with any DNS provider:
# Example DNS configuration
example.com. TXT "sonr-verification=a1b2c3d4e5f6789abcdef"
example.com. A 192.168.1.1
www.example.com CNAME example.com
Supported providers include:
- Cloudflare
- AWS Route53
- Google Cloud DNS
- GoDaddy
- Namecheap
- Any RFC-compliant DNS service
UCAN Authorization
Capability Requests
Services request permissions through UCAN tokens:
interface CapabilityRequest {
service: string; // Verified domain
user: string; // User DID
capabilities: {
resource: string; // Target resource
actions: string[]; // Requested actions
constraints?: {
amount?: string; // Spending limits
frequency?: string; // Time restrictions
expires?: number; // Expiration timestamp
};
}[];
}
// Request data access
const dataRequest: CapabilityRequest = {
service: "app.example.com",
user: "did:sonr:alice123",
capabilities: [
{
resource: "sonr://vault/alice123/data",
actions: ["dwn:read", "dwn:write"],
constraints: {
dataTypes: ["profile", "settings"],
expires: Date.now() + 30 * 24 * 60 * 60 * 1000,
},
},
],
};
// Request payment capability
const paymentRequest: CapabilityRequest = {
service: "pay.example.com",
user: "did:sonr:bob456",
capabilities: [
{
resource: "sonr://vault/bob456/wallet",
actions: ["payment:send"],
constraints: {
amount: "100.00",
frequency: "daily",
expires: Date.now() + 7 * 24 * 60 * 60 * 1000,
},
},
],
};
Permission Presentation
Users see human-readable permission requests:
// Convert capability to user dialog
function presentCapability(request: CapabilityRequest): UserDialog {
const capability = request.capabilities[0];
const action = capability.actions[0];
switch (action) {
case "dwn:read":
return {
title: `${request.service} wants to read your data`,
description: `Access to ${capability.constraints.dataTypes.join(", ")}`,
icon: "📖",
risk: "low",
};
case "payment:send":
return {
title: `${request.service} wants to send payments`,
description: `Up to $${capability.constraints.amount} ${capability.constraints.frequency}`,
icon: "💸",
risk: "medium",
};
}
}
Token Generation
UCAN tokens encode delegated permissions:
// Generate UCAN token after user approval
async function generateUCAN(
issuer: DID,
audience: string,
capabilities: Capability[],
): Promise<string> {
const header = {
alg: "EdDSA",
typ: "JWT",
ucv: "0.10.0",
};
const payload = {
iss: issuer.did,
aud: audience,
exp: Math.floor(Date.now() / 1000) + 3600,
nnc: generateNonce(),
att: capabilities.map((cap) => ({
with: cap.resource,
can: cap.actions,
})),
};
return signJWT(header, payload, issuer.privateKey);
}
Economic Model
Staking Requirements
Services stake SNR tokens for registration:
Service Tier | Minimum Stake | Capabilities | Daily Limit |
---|---|---|---|
Basic | 1,000 SNR | Read operations | 10,000 requests |
Standard | 5,000 SNR | Read/Write operations | 50,000 requests |
Premium | 10,000 SNR | All operations | Unlimited |
Enterprise | 25,000 SNR | Custom capabilities | Unlimited |
Reward Distribution
Services earn rewards for successful operations:
interface RewardParameters {
baseRate: number; // SNR per authentication
trustMultiplier: number; // 1.0-3.0x based on score
volumeBonus: number; // Additional % for volume
}
function calculateMonthlyRewards(
authentications: number,
trustScore: number,
successRate: number,
): number {
const base = authentications * 0.1; // 0.1 SNR per auth
const multiplier = 1 + (trustScore / 1000) * 2;
const bonus = Math.log10(authentications) * 0.01;
return base * multiplier * (successRate / 100) + bonus;
}
// Example calculation
const rewards = calculateMonthlyRewards(
50000, // 50k authentications
900, // Trust score
99.5, // Success rate
);
// Result: ~2,835 SNR/month
Fee Structure
Transparent pricing for operations:
Operation | Fee | Distribution |
---|---|---|
Authentication | 0.01 SNR | 70% validators, 20% service, 10% protocol |
Capability Request | 0.001 SNR | 60% validators, 30% service, 10% protocol |
Data Operation | 0.005 SNR | 65% validators, 25% service, 10% protocol |
Payment Request | 0.1% of amount | 50% validators, 40% service, 10% protocol |
Integration Patterns
SDK Implementation
Services integrate using the Sonr SDK:
import { SonrService } from "@sonr/service-sdk";
// Initialize service
const service = new SonrService({
domain: "app.example.com",
did: "did:sonr:service123",
capabilities: ["dwn:read", "dwn:write", "payment:request"],
});
// Request authentication
const auth = await service.requestAuth({
user: "alice@example.com",
capabilities: {
"dwn:read": {
resources: ["profile", "settings"],
expires: "30d",
},
},
});
// Use capabilities
if (auth.success) {
const profile = await service.vault.read("profile");
await service.vault.write("settings", newSettings);
}
Web Integration
HTML forms with progressive enhancement:
<!-- Basic form -->
<form action="/api/sonr/auth" method="POST">
<input type="email" name="user" required />
<button type="submit">Authenticate</button>
</form>
<!-- Enhanced with HTMX -->
<form hx-post="/api/sonr/auth" hx-target="#result" hx-indicator="#loading">
<input type="email" name="user" required />
<select name="capabilities">
<option value="read">Read Only</option>
<option value="write">Read/Write</option>
</select>
<button type="submit">
Authenticate
<span id="loading" class="htmx-indicator">⏳</span>
</button>
</form>
<div id="result"></div>
Mobile Integration
Native SDKs for iOS and Android:
// iOS Swift
import SonrSDK
let service = SonrService(domain: "app.example.com")
await service.requestAuth(
capabilities: [.read, .write],
onSuccess: { token in
KeychainService.store(token)
self.navigateToMain()
}
)
// Android Kotlin
import io.sonr.sdk.SonrService
val service = SonrService("app.example.com")
service.requestAuth(
capabilities = listOf(Capability.READ, Capability.WRITE),
onSuccess = { token ->
secureStorage.putString("auth_token", token)
startActivity(Intent(this, MainActivity::class.java))
}
)
Service Discovery
Query Interface
Users find services by capabilities and reputation:
interface ServiceQuery {
category?: string;
capabilities?: string[];
minTrustScore?: number;
sortBy?: "trust" | "volume" | "age";
}
// Find payment services
const services = await registry.query({
category: "payment",
capabilities: ["payment:send"],
minTrustScore: 800,
sortBy: "trust",
});
// Service result
interface ServiceInfo {
domain: string;
did: string;
trustScore: number;
capabilities: string[];
metrics: {
totalAuthentications: number;
successRate: number;
avgResponseTime: number;
userSatisfaction: number;
};
}
Service Categories
Standardized capability categories:
enum ServiceCategory {
IDENTITY = "identity", // Authentication services
PAYMENT = "payment", // Financial operations
STORAGE = "storage", // Data management
COMPUTE = "compute", // Processing services
SOCIAL = "social", // Social features
DEFI = "defi", // DeFi protocols
}
// Standard capabilities per category
const categoryCapabilities = {
[ServiceCategory.IDENTITY]: ["auth:login", "auth:verify", "auth:2fa"],
[ServiceCategory.PAYMENT]: [
"payment:send",
"payment:receive",
"payment:exchange",
],
[ServiceCategory.STORAGE]: ["dwn:read", "dwn:write", "dwn:delete"],
};
Compliance Features
Audit Trail
All operations are recorded on-chain:
interface AuthEvent {
eventId: string;
timestamp: number;
service: string; // Service domain
user: string; // User DID
action: string; // Operation type
result: "success" | "failure";
metadata: {
ipAddress?: string;
userAgent?: string;
location?: string;
};
}
// Query audit logs
const auditLogs = await registry.queryAuditLogs({
service: "app.example.com",
startTime: Date.now() - 86400000, // Last 24 hours
endTime: Date.now(),
});
Privacy Protection
Zero-knowledge proofs for compliance:
// Prove compliance without revealing details
pub struct ComplianceProof {
pub has_valid_license: bool,
pub meets_capital_requirements: bool,
pub passed_security_audit: bool,
pub proof: Vec<u8> // ZK proof
}
impl ComplianceProof {
pub fn generate(
license: &License,
capital: &Capital,
audit: &SecurityAudit
) -> Self {
// Generate ZK proof
let proof = zk_prove(&[
license.is_valid(),
capital.meets_minimum(),
audit.passed()
]);
Self {
has_valid_license: true,
meets_capital_requirements: true,
passed_security_audit: true,
proof
}
}
}
Migration Guide
Migration Strategy
Phased approach for existing systems:
interface MigrationPhase {
duration: string;
tasks: string[];
validation: string[];
}
const migrationPlan: MigrationPhase[] = [
{
duration: "Week 1-2",
tasks: [
"Register service domain",
"Add DNS verification",
"Deploy Sonr SDK",
"Configure dual-auth",
],
validation: [
"DNS record verified",
"SDK integration tested",
"Fallback working",
],
},
{
duration: "Week 3-6",
tasks: [
"Migrate 10% users",
"Monitor metrics",
"Gather feedback",
"Train support team",
],
validation: [
"Success rate >99%",
"User satisfaction maintained",
"Support tickets handled",
],
},
{
duration: "Week 7-12",
tasks: [
"Complete migration",
"Deprecate legacy auth",
"Archive old data",
"Update documentation",
],
validation: [
"All users migrated",
"Legacy system decommissioned",
"Cost savings realized",
],
},
];
Compatibility Layer
Support both systems during transition:
class DualAuthProvider {
async authenticate(request: AuthRequest): Promise<AuthResponse> {
// Check if user has migrated
const migrated = await this.checkMigrationStatus(request.userId);
if (migrated) {
// Use Sonr authentication
return await this.sonrAuth.authenticate(request);
} else {
// Use legacy authentication
const result = await this.legacyAuth.authenticate(request);
// Prompt for migration
result.migrationPrompt = {
message: "Upgrade to passwordless authentication?",
benefits: [
"No more passwords",
"Biometric security",
"Cross-device sync"
]
};
return result;
}
}
}
## Best Practices
### For Service Developers
1. **Start with minimal capabilities**: Request only necessary permissions
2. **Implement proper error handling**: Gracefully handle denials and revocations
3. **Monitor trust metrics**: Track success rates and response times
4. **Maintain high stake**: Higher stakes signal commitment
5. **Document capabilities clearly**: Help users understand requests
### For Validators
1. **Verify DNS records promptly**: Ensure quick service onboarding
2. **Monitor service behavior**: Flag suspicious activities
3. **Participate in slashing votes**: Maintain network integrity
4. **Update trust scores**: Keep reputation metrics current
### For Users
1. **Review capability requests**: Understand what services access
2. **Check trust scores**: Prefer high-reputation services
3. **Revoke unused permissions**: Maintain security hygiene
4. **Report bad behavior**: Help improve the ecosystem
## Next Steps
<Callout title="Ready to Register?" type="success">
**Service Developers**: Start with the [Service Registration Guide](/docs/guides/service-registration) to register your domain.
**Validators**: Learn about [Service Verification](/docs/validators/service-verification) responsibilities.
**Users**: Understand [Permission Management](/docs/users/permissions) in your Vault.
</Callout>
<Cards>
<Card title="Service Module" href="/docs/reference/modules/x-svc">
Technical specifications for service registry
</Card>
<Card title="UCAN Module" href="/docs/reference/modules/x-ucan">
Capability delegation implementation
</Card>
<Card title="DWN Integration" href="/docs/reference/modules/x-dwn">
Vault interaction patterns
</Card>
<Card title="Migration Examples" href="/docs/examples/auth-migration">
Real-world migration case studies
</Card>
</Cards>
Personal Identity
Learn about Sonr's decentralized identity system using DID documents and WebAuthn for secure user identification
Web Browser APIs (W3C)
Revolutionary client integration patterns using HTMX, Cross-Origin iFrames, and Browser APIs to solve crypto UX problems across maximum devices with seamless ease of control