UCAN Examples
This page contains practical examples of using UCAN for various authorization scenarios.
Note: These examples use the v1.0.0-rc.1 UCAN specification and the
iso-ucan
JavaScript library. The examples show the current API patterns as of the latest specification version.
Implementation Note: UCAN libraries for different languages may be at different specification versions. Always refer to your chosen library’s documentation for the exact API and supported features.
File System Access
Section titled “File System Access”This example demonstrates how to delegate file read permissions using UCANs.
import { Capability } from 'iso-ucan/capability'import { Store } from 'iso-ucan/store'import { MemoryDriver } from 'iso-kv/drivers/memory'import { EdDSASigner } from 'iso-signatures/signers/eddsa.js'import { z } from 'zod'
// Initialize delegation store for tracking capability chains// In production, this might be backed by a database or persistent storageconst store = new Store(new MemoryDriver())
// Define file read capability with path validation schema// The schema ensures all invocations include a valid file pathconst FileReadCap = Capability.from({ schema: z.object({ path: z.string(), // Required: file path to read }), cmd: '/file/read', // UCAN v1 command identifier})
// Create cryptographic identities for resource owner and accessor// In a real system, these would be persistent identity keypairsconst alice = await EdDSASigner.generate() // Resource ownerconst bob = await EdDSASigner.generate() // Requesting access
const nowInSeconds = Math.floor(Date.now() / 1000)
// Alice grants Bob permission to read files// This delegation can be stored, transmitted, or embedded in applicationsconst delegation = await FileReadCap.delegate({ iss: alice, // Alice issues this capability aud: bob, // Bob is authorized to use it sub: alice, // Alice's resources are the subject pol: [], // No additional policy constraints exp: nowInSeconds + 3600, // Expires in 1 hour for security})
// Store delegation to enable later invocation validation// The store enables automatic delegation chain resolutionawait store.set(delegation)
// Bob exercises the delegated capability to read a specific file// This creates a cryptographically verifiable access requestconst invocation = await FileReadCap.invoke({ iss: bob, // Bob is invoking the capability sub: alice, // Alice's system will process the request args: { path: '/documents/report.pdf' // Specific file Bob wants to read }, store, // Store containing the delegation proof exp: nowInSeconds + 300, // Invocation expires in 5 minutes})
Example 2: API Rate Limiting
Section titled “Example 2: API Rate Limiting”Scenario
Section titled “Scenario”A service wants to delegate API access with rate limiting constraints.
Implementation using iso-ucan
Section titled “Implementation using iso-ucan”import { Capability } from 'iso-ucan/capability'import { Store } from 'iso-ucan/store'import { MemoryDriver } from 'iso-kv/drivers/memory'import { EdDSASigner } from 'iso-signatures/signers/eddsa.js'import { z } from 'zod'
// Set up store for delegation managementconst store = new Store(new MemoryDriver())
// Define the API read capability with rate limiting schemaconst ApiReadCap = Capability.from({ schema: z.object({ rate_limit: z.object({ requests_per_hour: z.number(), reset_time: z.string() }) }), cmd: '/api/users/read',})
// Generate keypairs for service and clientconst service = await EdDSASigner.generate()const client = await EdDSASigner.generate()
const nowInSeconds = Math.floor(Date.now() / 1000)
// Service delegates API access to client with rate limitingconst delegation = await ApiReadCap.delegate({ iss: service, aud: client, sub: service, pol: [], exp: nowInSeconds + 86400,})
await store.set(delegation)
// Client can invoke the capability with rate limiting parametersconst invocation = await ApiReadCap.invoke({ iss: client, sub: service, args: { rate_limit: { requests_per_hour: 100, reset_time: "hourly" } }, store, exp: nowInSeconds + 300,})
Real-World Implementation Notes
Section titled “Real-World Implementation Notes”Complete Example with Account Creation
Section titled “Complete Example with Account Creation”Here’s a more comprehensive example following the pattern from the iso-ucan
documentation:
import { Capability } from 'iso-ucan/capability'import { Store } from 'iso-ucan/store'import { MemoryDriver } from 'iso-kv/drivers/memory'import { EdDSASigner } from 'iso-signatures/signers/eddsa.js'import { z } from 'zod'
const store = new Store(new MemoryDriver())
// Define account creation capabilityconst AccountCreateCap = Capability.from({ schema: z.object({ type: z.string(), properties: z.object({ name: z.string(), }).strict(), }), cmd: '/account/create',})
// Define general account capabilityconst AccountCap = Capability.from({ schema: z.never(), cmd: '/account',})
// Generate keypairs for all partiesconst owner = await EdDSASigner.generate()const bob = await EdDSASigner.generate()const invoker = await EdDSASigner.generate()
const nowInSeconds = Math.floor(Date.now() / 1000)
// Owner delegates account capability to Bobconst ownerDelegation = await AccountCap.delegate({ iss: owner, aud: bob, sub: owner, pol: [], exp: nowInSeconds + 1000,})
await store.set(ownerDelegation)
// Bob further delegates to invokerconst bobDelegation = await AccountCap.delegate({ iss: bob, aud: invoker, sub: owner, pol: [], exp: nowInSeconds + 1000,})
await store.set(bobDelegation)
// Invoker can now create an account using the delegation chainconst invocation = await AccountCreateCap.invoke({ iss: invoker, sub: owner, args: { type: 'account', properties: { name: 'John Doe', }, }, store, exp: nowInSeconds + 1000,})
Other UCAN Library Examples
Section titled “Other UCAN Library Examples”While this guide focuses on iso-ucan
, here are examples for other popular implementations:
JavaScript (iso-ucan)
Section titled “JavaScript (iso-ucan)”The examples above demonstrate the current iso-ucan
API. For the latest documentation, refer to the iso-ucan
package documentation.
Rust (ucan)
Section titled “Rust (ucan)”use ucan::builder::UcanBuilder;use ucan::crypto::KeyMaterial;
let ucan = UcanBuilder::default() .issued_by(&issuer_key) .for_audience(&audience_did) .with_lifetime(3600) .claiming_capability(&capability) .build()?;
Go (go-ucan)
Section titled “Go (go-ucan)”import "github.com/ucan-wg/go-ucan"
token, err := ucan.NewBuilder(). IssuedBy(issuerKey). ToAudience(audienceDID). WithLifetime(time.Hour). ClaimCapability(capability). Build()
Transport and Storage
Section titled “Transport and Storage”UCANs in iso-ucan
are handled as structured objects that can be serialized for transport and storage as needed by your application.
Best Practices
Section titled “Best Practices”Security Considerations
Section titled “Security Considerations”-
Principle of Least Authority (PoLA): Only delegate the minimum necessary permissions
// Good: Specific resource and capabilityconst FileReadCap = Capability.from({schema: z.never(),cmd: '/file/read',})// Avoid: Overly broad permissionsconst AllFilesCap = Capability.from({schema: z.never(),cmd: '/file/*',}) -
Short Expiry Times: Use the shortest practical expiration times
// Good: Short-lived for temporary accessexp: nowInSeconds + 3600 // 1 hour// Good: Longer for trusted devicesexp: nowInSeconds + 2592000 // 30 days// Avoid: Very long expiration unless absolutely necessaryexp: nowInSeconds + 31536000 // 1 year -
Specific Capabilities: Be as specific as possible in capability definitions
-
Secure Key Management: Keep private keys secure and never share them
Implementation Guidelines
Section titled “Implementation Guidelines”- Proper Error Handling: Always handle UCAN verification failures gracefully
- Caching and Performance: Cache verification results when appropriate
- Audit Logging: Log UCAN usage for security auditing
Resources and Further Reading
Section titled “Resources and Further Reading”Specification Documents
Section titled “Specification Documents”- UCAN Delegation Specification - Core delegation mechanism
- UCAN Invocation Specification - How to exercise capabilities
- UCAN Policy Language - Detailed policy syntax
- UCAN Revocation Specification - Capability revocation
Implementation Libraries
Section titled “Implementation Libraries”Community and Support
Section titled “Community and Support”- UCAN Working Group - Main GitHub organization
- Specification Repository - Latest specification updates
- Community Discussions - Ask questions and share ideas
Note: UCAN is an evolving specification. Always refer to the latest version of the specifications and library documentation for the most current information.