AT Protocol Identity Rust Components#
A comprehensive collection of Rust components for creating AT Protocol applications. This workspace provides essential building blocks for identity management, record operations, OAuth 2.0 authentication flows, HTTP client operations, XRPC services, and real-time event streaming.
Origin: Parts of this project were extracted from the open-source smokesignal.events project, an AT Protocol event and RSVP management application. This library is released under the MIT license to enable broader AT Protocol ecosystem development.
Components#
This workspace contains 10 specialized crates that work together to provide complete AT Protocol application development capabilities:
Identity & Cryptography#
atproto-identity- Core identity management with multi-method DID resolution (plc, web, key), DNS/HTTP handle resolution, and P-256/P-384/K-256 cryptographic operations. Includes 4 CLI tools.atproto-attestation- CID-first attestation utilities for creating and verifying cryptographic signatures on AT Protocol records, supporting both inline and remote attestation workflows. Includes 2 CLI tools.atproto-record- Record utilities including TID generation, AT-URI parsing, datetime formatting, and CID generation using IPLD DAG-CBOR serialization. Includes 1 CLI tool.atproto-lexicon- Lexicon schema resolution and validation for AT Protocol, supporting recursive resolution, NSID validation, and DNS-based lexicon discovery. Includes 1 CLI tool.
Authentication & Authorization#
atproto-oauth- Complete OAuth 2.0 implementation with AT Protocol security extensions including DPoP (RFC 9449), PKCE (RFC 7636), JWT operations, and secure storage abstractions. Includes 1 CLI tool.atproto-oauth-aip- OAuth AIP (Identity Provider) implementation providing complete authorization code flow with PAR, token exchange, and AT Protocol session management.atproto-oauth-axum- Production-ready Axum web handlers for OAuth endpoints including authorization callbacks, JWKS endpoints, and client metadata. Includes 1 CLI tool.
Client & Service Development#
atproto-client- HTTP client library supporting multiple authentication methods (DPoP, Bearer tokens, sessions) with native XRPC protocol operations and repository management. Includes 3 CLI tools.atproto-xrpcs- XRPC service framework providing JWT authorization extractors, DID resolution integration, and Axum middleware for building AT Protocol services.atproto-xrpcs-helloworld- Complete example XRPC service demonstrating DID:web identity, service document generation, and JWT authentication patterns. Includes 1 service binary.
Real-time Event Processing#
atproto-jetstream- WebSocket consumer for AT Protocol Jetstream events with Zstandard compression, automatic reconnection, and configurable event filtering. Includes 1 CLI tool.
Quick Start#
Add the crates to your Cargo.toml:
[dependencies]
atproto-identity = "0.13.0"
atproto-attestation = "0.13.0"
atproto-record = "0.13.0"
atproto-lexicon = "0.13.0"
atproto-oauth = "0.13.0"
atproto-oauth-aip = "0.13.0"
atproto-client = "0.13.0"
# Add others as needed
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(&[]);
let did = resolve_subject(&http_client, &dns_resolver, "alice.bsky.social").await?;
println!("Resolved DID: {}", did);
Ok(())
}
Lexicon Resolution#
use atproto_lexicon::resolve::{DefaultLexiconResolver, LexiconResolver};
use atproto_identity::resolve::HickoryDnsResolver;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let http_client = reqwest::Client::new();
let dns_resolver = HickoryDnsResolver::create_resolver(&[]);
let resolver = DefaultLexiconResolver::new(http_client, dns_resolver);
// Resolve a lexicon schema
let lexicon = resolver.resolve("app.bsky.feed.post").await?;
println!("Lexicon schema: {}", serde_json::to_string_pretty(&lexicon)?);
Ok(())
}
Record Signing#
use atproto_identity::key::{identify_key, to_public};
use atproto_attestation::{
create_inline_attestation, verify_all_signatures, VerificationStatus,
input::{AnyInput, PhantomSignature}
};
use serde_json::json;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let private_key = identify_key("did:key:zQ3shNzMp4oaaQ1gQRzCxMGXFrSW3NEM1M9T6KCY9eA7HhyEA")?;
let public_key = to_public(&private_key)?;
let key_reference = format!("{}", &public_key);
let repository_did = "did:plc:repo123";
let record = json!({
"$type": "app.bsky.feed.post",
"text": "Hello AT Protocol!",
"createdAt": "2024-01-01T00:00:00.000Z"
});
let sig_metadata = json!({
"$type": "com.example.inlineSignature",
"key": &key_reference,
"issuer": "did:plc:issuer123",
"issuedAt": "2024-01-01T00:00:00.000Z"
});
let signed_record = create_inline_attestation::<PhantomSignature, PhantomSignature>(
AnyInput::Json(record),
AnyInput::Json(sig_metadata),
repository_did,
&private_key
)?;
let reports = verify_all_signatures(&signed_record, repository_did, None).await?;
assert!(reports.iter().all(|report| matches!(report.status, VerificationStatus::Valid { .. })));
Ok(())
}
XRPC Service#
use atproto_xrpcs::authorization::Authorization;
use axum::{Json, Router, extract::Query, routing::get};
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize)]
struct HelloParams {
subject: Option<String>,
}
async fn handle_hello(
params: Query<HelloParams>,
authorization: Option<Authorization>,
) -> Json<serde_json::Value> {
let subject = params.subject.as_deref().unwrap_or("World");
let message = if let Some(auth) = authorization {
format!("Hello, authenticated {}! (caller: {})", subject, auth.subject())
} else {
format!("Hello, {}!", subject)
};
Json(json!({ "message": message }))
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let app = Router::new()
.route("/xrpc/com.example.hello", get(handle_hello))
.with_state(your_web_context);
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?;
axum::serve(listener, app).await?;
Ok(())
}
OAuth Client Flow#
use atproto_oauth_aip::{OAuthClient, oauth_init, oauth_complete, session_exchange};
use atproto_oauth::storage::MemoryStorage;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = OAuthClient::new(
"https://your-app.com/client-id".to_string(),
Some("your-client-secret".to_string()),
"https://your-app.com/callback".to_string(),
);
let storage = MemoryStorage::new();
// Start OAuth flow
let (authorization_url, state) = oauth_init(
&client,
"alice.bsky.social",
&storage,
).await?;
println!("Visit: {}", authorization_url);
// After callback with code...
let access_token = oauth_complete(
&client,
"auth-code",
"state",
&storage,
).await?;
// Get AT Protocol session
let session = session_exchange(&client, &access_token, &storage).await?;
println!("Authenticated as: {} ({})", session.handle, session.did);
Ok(())
}
Command Line Tools#
The workspace includes 13 command-line tools across multiple crates, providing ready-to-use utilities for AT Protocol development and testing. All CLI tools require the clap feature:
# Build with CLI support
cargo build --features clap --bins
# Identity operations (atproto-identity crate)
cargo run --features clap --bin atproto-identity-resolve -- alice.bsky.social
cargo run --features clap --bin atproto-identity-key -- generate p256
cargo run --features clap --bin atproto-identity-sign -- did:key:... data.json
cargo run --features clap --bin atproto-identity-validate -- did:key:... data.json signature
# Attestation operations (atproto-attestation crate)
cargo run --package atproto-attestation --features clap,tokio --bin atproto-attestation-sign -- inline record.json did:key:... metadata.json
cargo run --package atproto-attestation --features clap,tokio --bin atproto-attestation-verify -- signed_record.json
# Record operations (atproto-record crate)
cat record.json | cargo run --features clap --bin atproto-record-cid
# Lexicon operations (atproto-lexicon crate)
cargo run --features clap,hickory-dns --bin atproto-lexicon-resolve -- app.bsky.feed.post
# Client operations (atproto-client crate)
cargo run --features clap --bin atproto-client-auth -- login alice.bsky.social password123
cargo run --features clap --bin atproto-client-app-password -- alice.bsky.social access_token /xrpc/com.atproto.repo.listRecords
cargo run --features clap --bin atproto-client-dpop -- alice.bsky.social did:key:... access_token /xrpc/com.atproto.repo.listRecords
# OAuth operations (atproto-oauth crate)
cargo run --features clap --bin atproto-oauth-service-token -- [service-token-args]
# OAuth operations (atproto-oauth-axum crate)
cargo run --features clap --bin atproto-oauth-tool -- login did:key:... alice.bsky.social
# XRPC service (atproto-xrpcs-helloworld crate)
cargo run --bin atproto-xrpcs-helloworld
# Event streaming (atproto-jetstream crate)
cargo run --features clap --bin atproto-jetstream-consumer -- jetstream1.us-east.bsky.network dictionary.zstd
Development#
# Build all crates
cargo build
# Run all tests
cargo test
# Format and lint
cargo fmt && cargo clippy
# Generate documentation
cargo doc --workspace --open
License#
This project is licensed under the MIT License - see the LICENSE file for details.
Architecture#
These components are designed to work together as building blocks for AT Protocol applications:
- Identity Layer:
atproto-identityprovides the foundation for DID resolution and cryptographic operations - Authentication Layer:
atproto-oauth*crates handle complete OAuth 2.0 flows with AT Protocol security extensions - Application Layer:
atproto-clientandatproto-xrpcs*enable client applications and service development - Data Layer:
atproto-recordhandles record signing and verification with proper IPLD serialization - Event Layer:
atproto-jetstreamprovides real-time event processing capabilities
Use Cases#
This workspace enables development of:
- AT Protocol Identity Providers (AIPs) - Complete OAuth servers with DID-based authentication
- Personal Data Servers (PDS) - XRPC services with JWT authorization and repository management
- AT Protocol Clients - Applications that authenticate and interact with AT Protocol services
- Event Processing Systems - Real-time processors for AT Protocol repository events
- Development Tools - CLI utilities for testing, debugging, and managing AT Protocol identities
Contributing#
Contributions are welcome! This project follows standard Rust development practices:
- Fork this repository
- Create a feature branch
- Run tests:
cargo test - Run linting:
cargo fmt && cargo clippy - Submit a pull request
Acknowledgments#
Parts of this project were extracted from the smokesignal.events project, an open-source AT Protocol event and RSVP management application. This extraction enables broader community use and contribution to AT Protocol tooling in Rust.