A library for ATProtocol identities.
Rust 99.4%
Dockerfile 0.6%
25 1 26

Clone this repository

https://tangled.org/smokesignal.events/atproto-identity-rs
git@tangled.org:smokesignal.events/atproto-identity-rs

For self-hosted knots, clone URLs may differ based on your setup.

README.md

AT Protocol Identity & Record Library#

A comprehensive Rust library for AT Protocol identity management, record signing, verification, and OAuth operations. This library provides full functionality for DID resolution, handle resolution, identity document management, cryptographic record operations, and OAuth 2.0 flows across multiple DID methods.

This project was extracted from the open-sourced Smokesignal project and is released under the MIT license.

Project Overview#

This workspace provides a complete toolkit for AT Protocol operations including identity resolution, record signing/verification, OAuth 2.0 flows, HTTP client operations, and web server integration. The library is designed to be modular, secure, and fully compliant with AT Protocol specifications.

Crates#

This workspace contains five specialized crates:

atproto-identity#

Core identity management and cryptographic operations

  • DID Resolution: Support for did:plc, did:web, and did:key methods
  • Handle Resolution: DNS and HTTP-based handle resolution with validation
  • Identity Documents: Complete DID document parsing and management
  • Cryptographic Operations: P-256 and K-256 elliptic curve support with signing/verification
  • Key Management: DID key identification, conversion, and JWK generation
  • Validation: Input validation for handles and DIDs
  • Configuration: Environment-based configuration with DNS and certificate customization

atproto-record#

AT Protocol record signature operations

  • Record Signing: Create cryptographic signatures for AT Protocol records with proper $sig object handling
  • Signature Verification: Verify existing signatures against records and public keys
  • IPLD Integration: Proper IPLD DAG-CBOR serialization for consistent signature generation
  • Multi-curve Support: Support for P-256 and K-256 elliptic curves via atproto-identity
  • Repository Context: Include repository and collection context in signatures

atproto-oauth#

Complete OAuth 2.0 operations with AT Protocol extensions

  • JWT Operations: Complete JSON Web Token minting, verification, and validation with ES256/ES256K support
  • JWK Management: JSON Web Key generation and management for P-256 and K-256 curves
  • PKCE Implementation: RFC 7636 Proof Key for Code Exchange for secure OAuth flows
  • DPoP Support: RFC 9449 Demonstration of Proof-of-Possession with automatic retry middleware
  • OAuth Resource Discovery: RFC 8414 OAuth 2.0 authorization server and protected resource metadata discovery
  • AT Protocol Validation: Comprehensive validation of OAuth servers against AT Protocol requirements

atproto-client#

HTTP client library for AT Protocol services

  • HTTP Client Operations: Authenticated and unauthenticated HTTP GET/POST requests with JSON support
  • DPoP Authentication: RFC 9449 Demonstration of Proof-of-Possession with automatic retry middleware
  • Repository Operations: Complete CRUD operations for AT Protocol repository records
  • URL Building: Flexible URL construction with parameter encoding and query string generation
  • OAuth Integration: Seamless integration with atproto-oauth for DPoP authentication

atproto-oauth-axum#

Axum web handlers for OAuth 2.0 authorization server endpoints

  • Complete OAuth Server Handlers: Ready-to-use Axum handlers for all required OAuth 2.0 endpoints
  • Client Metadata Endpoint: RFC 7591 compliant client metadata for dynamic client registration
  • JWKS Endpoint: JSON Web Key Set serving for JWT signature verification
  • Authorization Callback Handler: Complete OAuth callback processing with token exchange
  • OAuth Login CLI Tool: Full-featured command-line tool for testing and development OAuth flows

Command Line Tools#

The library includes 7 command-line utilities across the crates:

Identity Operations (atproto-identity)#

  • atproto-identity-resolve - Resolve AT Protocol handles and DIDs to identity documents
  • atproto-identity-sign - Sign JSON data with DID keys using IPLD DAG-CBOR serialization
  • atproto-identity-validate - Verify cryptographic signatures of JSON data
  • atproto-identity-key - Generate and manage cryptographic keys (P-256/K-256)

Record Operations (atproto-record)#

  • atproto-record-sign - Sign AT Protocol records with embedded signature metadata
  • atproto-record-verify - Verify AT Protocol record signatures with issuer authentication

OAuth Operations (atproto-oauth-axum)#

  • atproto-oauth-tool - Complete OAuth client flow with local server and token acquisition

Quick Start#

Add the crates to your Cargo.toml:

[dependencies]
atproto-identity = "0.4.1"
atproto-record = "0.4.1" 
atproto-oauth = "0.4.1"
atproto-client = "0.4.1"
atproto-oauth-axum = "0.4.1"

Basic Identity Resolution#

use atproto_identity::resolve::{resolve_subject, create_resolver};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let http_client = reqwest::Client::new();
    let dns_resolver = create_resolver(&[]);
    
    // Resolve a handle to a DID
    let did = resolve_subject(&http_client, &dns_resolver, "alice.bsky.social").await?;
    println!("Resolved DID: {}", did);
    
    Ok(())
}

Record Signing and Verification#

use atproto_identity::key::identify_key;
use atproto_record::signature;
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Parse DID key for signing operations
    let signing_key = identify_key("did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA")?;
    
    // Create a record to sign
    let record = json!({
        "$type": "app.bsky.feed.post",
        "text": "Hello AT Protocol!",
        "createdAt": "2024-01-01T00:00:00.000Z"
    });
    
    // Create signature object with issuer and timestamp
    let signature_object = json!({
        "issuer": "did:plc:issuer123",
        "issuedAt": "2024-01-01T00:00:00.000Z"
    });
    
    // Sign the record
    let signed_record = signature::create(
        &signing_key,
        &record,
        "did:plc:user123",     // repository
        "app.bsky.feed.post",  // collection
        signature_object,
    ).await?;
    
    // Verify the signature
    signature::verify(
        "did:plc:issuer123",   // issuer
        &signing_key,          // verification key
        signed_record,         // signed record
        "did:plc:user123",     // repository
        "app.bsky.feed.post",  // collection
    ).await?;
    
    println!("Signature verification successful");
    
    Ok(())
}

OAuth Operations#

use atproto_oauth::jwt::{mint, Header, Claims, JoseClaims};
use atproto_oauth::pkce;
use atproto_identity::key::identify_key;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let key_data = identify_key("did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA")?;
    
    // Generate PKCE parameters
    let (code_verifier, code_challenge) = pkce::generate();
    println!("PKCE Challenge: {}", code_challenge);
    
    // Create and sign JWT
    let header = Header::default();
    let claims = Claims::new(JoseClaims {
        issuer: Some("did:plc:issuer123".to_string()),
        subject: Some("did:plc:subject456".to_string()),
        audience: Some("https://pds.example.com".to_string()),
        ..Default::default()
    });
    
    let token = mint(&key_data, &header, &claims)?;
    println!("JWT: {}", token);
    
    Ok(())
}

CLI Usage Examples#

# Resolve a handle or DID to identity document
cargo run --bin atproto-identity-resolve alice.bsky.social

# Get full DID document with verification methods
cargo run --bin atproto-identity-resolve --did-document did:plc:user123

# Generate a new P-256 private key
cargo run --bin atproto-identity-key generate p256

# Sign a record from file with all required context
cargo run --bin atproto-record-sign \
  did:key:zQ3shNzMp4oaaQ1... \
  did:plc:issuer123 \
  record.json \
  repository=did:plc:user123 \
  collection=app.bsky.feed.post

# Verify a signed record
cargo run --bin atproto-record-verify \
  did:plc:issuer123 \
  did:key:zQ3shNzMp4oaaQ1... \
  signed_record.json \
  repository=did:plc:user123 \
  collection=app.bsky.feed.post

# Start OAuth login flow (requires EXTERNAL_BASE environment variable)  
EXTERNAL_BASE=localhost:8080 cargo run --bin atproto-oauth-tool login \
  did:key:zQ3shNzMp4oaaQ1... \
  alice.bsky.social

Features#

  • Async/Await: Built with modern Rust async patterns using Tokio
  • Error Handling: Comprehensive structured error types using thiserror with standardized error codes
  • Security: Forbids unsafe code, follows security best practices, and implements all required OAuth security extensions
  • Standards Compliance: Full AT Protocol, RFC 7636 (PKCE), RFC 9449 (DPoP), and RFC 8414 (OAuth Discovery) compliance
  • Logging: Structured logging with tracing for debugging and monitoring
  • Multi-platform: Works on all major platforms with configurable DNS and HTTP settings
  • Modular Design: Clean separation of concerns allowing selective usage of components

Architecture#

The library follows a layered architecture with clear separation of concerns:

┌─────────────────────────────────────────────────────────────┐
│                     Application Layer                       │
│                 (CLI Tools & Web Handlers)                  │
├─────────────────────────────────────────────────────────────┤
│                    Protocol Layer                           │
│              (atproto-client, atproto-record)               │
├─────────────────────────────────────────────────────────────┤
│                     OAuth Layer                             │
│             (atproto-oauth, atproto-oauth-axum)             │
├─────────────────────────────────────────────────────────────┤
│                   Foundation Layer                          │
│              (atproto-identity - Core Services)             │
└─────────────────────────────────────────────────────────────┘
  • Foundation Layer: Core identity, cryptographic, and DID operations
  • OAuth Layer: Complete OAuth 2.0 flows with AT Protocol extensions
  • Protocol Layer: Higher-level AT Protocol operations (records, client)
  • Application Layer: Ready-to-use tools and web framework integration

Development#

Building the Project#

# Build all crates
cargo build

# Build specific crate
cargo build -p atproto-identity

# Build with all features
cargo build --all-features

Running Tests#

# Run all tests
cargo test

# Run tests for specific crate  
cargo test -p atproto-oauth

# Run with output
cargo test -- --nocapture

Code Quality#

# Format code
cargo fmt

# Lint code
cargo clippy

# Check without building
cargo check

# Run all quality checks
cargo fmt && cargo clippy && cargo test

Documentation#

# Generate documentation
cargo doc --open

# Generate documentation for all crates
cargo doc --workspace --open

License#

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing#

Contributions are welcome! Please ensure that:

  1. All tests pass: cargo test
  2. Code is properly formatted: cargo fmt
  3. No linting issues: cargo clippy
  4. New functionality includes appropriate tests and documentation
  5. Error handling follows the project's structured error format

Acknowledgments#

This library was extracted from the Smokesignal project, an open-source event and RSVP management and discovery application. We thank the Smokesignal contributors for their foundational work on AT Protocol identity management and record operations.