A library for ATProtocol identities.
1# atproto-xrpcs
2
3XRPC service framework for AT Protocol applications.
4
5## Overview
6
7Build AT Protocol services with JWT authorization, DID resolution, and cryptographic identity verification middleware.
8
9## Features
10
11- **JWT authorization**: Comprehensive JWT token validation with DID-based issuer verification
12- **DID resolution integration**: Automatic DID document resolution and key verification for authorization
13- **Identity verification**: Cryptographic verification of JWT signatures using DID documents
14- **Axum extractors**: Ready-to-use authorization extractors for Axum web handlers
15- **Structured errors**: Specialized error types for authorization and XRPC operations
16
17## CLI Tools
18
19This crate does not provide standalone CLI tools. It serves as a foundational library for building XRPC services. See `atproto-xrpcs-helloworld` for a complete example service implementation.
20
21## Usage
22
23### Basic XRPC Service
24
25```rust
26use atproto_xrpcs::authorization::Authorization;
27use axum::{Json, Router, extract::Query, routing::get};
28use serde::Deserialize;
29use serde_json::json;
30
31#[derive(Deserialize)]
32struct HelloParams {
33 name: Option<String>,
34}
35
36async fn handle_hello(
37 params: Query<HelloParams>,
38 authorization: Option<Authorization>,
39) -> Json<serde_json::Value> {
40 let name = params.name.as_deref().unwrap_or("World");
41
42 let message = if authorization.is_some() {
43 format!("Hello, authenticated {}!", name)
44 } else {
45 format!("Hello, {}!", name)
46 };
47
48 Json(json!({ "message": message }))
49}
50
51let app = Router::new()
52 .route("/xrpc/com.example.hello", get(handle_hello))
53 .with_state(your_web_context);
54```
55
56### JWT Authorization
57
58```rust
59use atproto_xrpcs::authorization::Authorization;
60
61async fn handle_secure_endpoint(
62 authorization: Authorization, // Required authorization
63) -> Json<serde_json::Value> {
64 // The Authorization extractor automatically:
65 // 1. Validates the JWT token
66 // 2. Resolves the caller's DID document
67 // 3. Verifies the signature against the DID document
68 // 4. Provides access to caller identity information
69
70 let caller_did = authorization.subject();
71 Json(json!({"caller": caller_did, "status": "authenticated"}))
72}
73```
74
75### Error Handling
76
77```rust
78use atproto_xrpcs::errors::AuthorizationError;
79use axum::{response::IntoResponse, http::StatusCode};
80
81async fn protected_handler(
82 authorization: Result<Authorization, AuthorizationError>,
83) -> impl IntoResponse {
84 match authorization {
85 Ok(auth) => (StatusCode::OK, "Access granted").into_response(),
86 Err(AuthorizationError::InvalidJWTFormat) => {
87 (StatusCode::UNAUTHORIZED, "Invalid token").into_response()
88 }
89 Err(AuthorizationError::SubjectResolutionFailed { .. }) => {
90 (StatusCode::FORBIDDEN, "Identity verification failed").into_response()
91 }
92 Err(_) => {
93 (StatusCode::INTERNAL_SERVER_ERROR, "Authorization error").into_response()
94 }
95 }
96}
97```
98
99## Authorization Flow
100
101The `Authorization` extractor implements:
102
1031. JWT extraction from HTTP Authorization headers
1042. Token validation (signature and claims structure)
1053. DID resolution for the token issuer
1064. Signature verification against DID document public keys
1075. Identity confirmation and authorization scope validation
108
109## License
110
111MIT License