Skip to main content

Crate skyauth

Crate skyauth 

Source
Expand description

§skyauth

A pure safe Rust (#![forbid(unsafe_code)]), zero-panic OAuth 2.1 client library for the AT Protocol (Bluesky).

§Overview

skyauth provides production-grade implementations of the foundational security standards mandated by the AT Protocol OAuth 2.1 specification:

  • RFC 9449 DPoP (Demonstrating Proof-of-Possession): Ephemeral ECDSA P-256 keypair generation, RFC 7517 JWK formatting, RFC 7638 JWK Thumbprints (jkt), unpadded Base64URL signing input formatting, 64-byte raw IEEE P1363 signatures, access token hashing (ath), inbound proof verification, and transparent auto-nonce retry loops.
  • RFC 7636 PKCE (Proof Key for Code Exchange): Cryptographic S256 verifier/challenge generation and constant-time verification.
  • RFC 9126 PAR (Pushed Authorization Requests): Back-channel parameter pushing with signed DPoP headers and authorization URL generation.
  • OAuth 2.1 Code Exchange & Refresh Token Rotation: DPoP-bound code exchange, strict single-use refresh token rotation semantics, and authenticated OAuthSession management.
  • 64-Shard Partitioned Concurrent State Store: Lock-free scaling state storage across 64 independent parking_lot::RwLock shards with atomic single-use state consumption (OAuthStore::take_state) and drift-free background TTL pruning.
  • Web Framework Integrations: Ready-to-use extractors, response generators, and middleware for Axum, Actix-web, and Tower.
  • Decentralized Identity & Handle Resolution: Handle normalization, DNS TXT resolution (_atproto.<handle>), HTTPS fallback (/.well-known/atproto-did), DID resolution (did:plc, did:web), and bidirectional handle verification against alsoKnownAs.
  • OAuth 2.0 Discovery (RFC 8414 & RFC 9728): Protected Resource Metadata and Authorization Server Metadata discovery with automatic OIDC fallback and capability enforcement.
  • Strict SSRF & DNS Rebinding Security: Full IP boundary filtering blocking RFC 1918 private IPs, loopback, link-local / cloud metadata (169.254.169.254), IPv6 ULA, deprecated 6to4 (2002::/16 blocked when its embedded IPv4 address is restricted) and Teredo (2001::/32) tunneling prefixes, cloud-metadata/internal hostname blocking, and DNS socket pinning.
  • Pure Safe Cryptography: ECDSA P-256 (p256), SHA-256 (sha2), HMAC-SHA256 (hmac), and constant-time equality comparisons (subtle).
  • Zero-Panic Invariant: Every fallible operation returns strongly typed AtprotoOAuthError.

§Quick Start

use skyauth::dpop::{DPoPKey, DPoPVerifier, compute_access_token_hash};
use skyauth::pkce::PkcePair;

// 1. Generate PKCE code challenge
let pkce = PkcePair::generate();
assert_eq!(pkce.verifier.len(), 43);

// 2. Generate ephemeral DPoP keypair
let dpop_key = DPoPKey::generate();
let jkt = dpop_key.jwk_thumbprint();

// 3. Create a DPoP proof for a token request
let proof = dpop_key.create_proof("POST", "https://pds.example.com/oauth/token", None, None)?;

// 4. Verify inbound DPoP proof
let verifier = DPoPVerifier::new();
let (claims, _jwk) = verifier.verify_proof(
    &proof,
    "POST",
    "https://pds.example.com/oauth/token",
    None,
    None,
    None,
)?;
assert_eq!(claims.htm, "POST");

§OAuth Client Lifecycle

use skyauth::client::{AtprotoOAuthClient, CallbackParams, OAuthClientMetadata};
use skyauth::store::OAuthStateStore;
use std::sync::Arc;
use std::time::Duration;

let metadata = OAuthClientMetadata::new(
    "https://my-app.example.com/client-metadata.json",
    "https://my-app.example.com/oauth/callback",
)
.with_client_name("My ATProto App")
.with_scope("atproto transition:generic");

let state_store = Arc::new(OAuthStateStore::new(Duration::from_secs(300)));
let client = AtprotoOAuthClient::builder()
    .metadata(metadata)
    .state_store(state_store)
    .state_ttl(Duration::from_secs(300))
    .build()?;

// Initiate login with user handle or DID
let auth_req = client.authorize("alice.bsky.social").await?;

// Handle callback with code and state (atomically consumed)
let callback_params = CallbackParams::new("auth_code", &auth_req.state)
    .with_iss("https://bsky.social");
let session = client.handle_callback(&callback_params).await?;

Re-exports§

pub use client::AtprotoOAuthClient;
pub use client::AtprotoOAuthClientBuilder;
pub use client::AuthorizationRequest;
pub use client::CallbackParams;
pub use client::OAuthClientMetadata;
pub use client::StoredStateEntry;
pub use client::TokenResponse;
pub use crypto::base64url_decode;
pub use crypto::base64url_decode_fixed;
pub use crypto::base64url_encode;
pub use crypto::constant_time_eq;
pub use crypto::hmac_sha256;
pub use crypto::jwk_thumbprint_ec_p256;
pub use crypto::jwk_thumbprint_rsa;
pub use crypto::sha256_digest;
pub use crypto::sign_p256_raw;
pub use crypto::verify_p256_raw;
pub use crypto::verifying_key_from_coordinates;
pub use crypto::verifying_key_to_coordinates;
pub use discovery::discover_oauth_endpoints;
pub use discovery::fetch_auth_server_metadata;
pub use discovery::fetch_protected_resource_metadata;
pub use discovery::validate_auth_server_capabilities;
pub use discovery::AuthorizationServerMetadata;
pub use discovery::DiscoveredAuthEndpoints;
pub use discovery::ProtectedResourceMetadata;
pub use dpop::compute_access_token_hash;
pub use dpop::extract_dpop_nonce;
pub use dpop::normalize_htu;
pub use dpop::DPoPKey;
pub use dpop::DPoPNonceCache;
pub use dpop::DPoPProofClaims;
pub use dpop::DPoPReplayCache;
pub use dpop::DPoPServerNonceSource;
pub use dpop::DPoPVerifier;
pub use dpop::InMemoryServerNonceSource;
pub use dpop::JwkEc;
pub use dpop::DEFAULT_CLOCK_SKEW_LEEWAY;
pub use dpop::DEFAULT_MAX_PROOF_AGE;
pub use error::AtprotoOAuthError;
pub use error::CryptoError;
pub use error::DPoPError;
pub use error::DiscoveryError;
pub use error::IdentityError;
pub use error::IntegrationError;
pub use error::ParError;
pub use error::PkceError;
pub use error::SsrfError;
pub use error::StoreError;
pub use error::TokenError;
pub use identity::normalize_handle;
pub use identity::validate_did_syntax;
pub use identity::DidDocument;
pub use identity::DidMethod;
pub use identity::DidService;
pub use identity::DnsTxtResolver;
pub use identity::IdentityResolver;
pub use identity::IdentityResolverBuilder;
pub use identity::ResolvedIdentity;
pub use identity::StandardDnsResolver;
pub use identity::VerificationMethod;
pub use identity::DEFAULT_PLC_DIRECTORY;
pub use integrations::AccessTokenValidator;
pub use integrations::AuthenticatedUser;
pub use integrations::CnfClaim;
pub use integrations::InMemoryTokenValidator;
pub use integrations::JwtAccessTokenClaims;
pub use integrations::JwtAccessTokenValidator;
pub use integrations::OAuthCallbackQuery;
pub use integrations::OAuthSessionExtension;
pub use integrations::RegisteredToken;
pub use par::build_authorization_url;
pub use par::execute_par_request;
pub use par::ParParameters;
pub use par::ParResponse;
pub use pkce::derive_s256_challenge;
pub use pkce::validate_verifier;
pub use pkce::verify_pkce;
pub use pkce::PkceMethod;
pub use pkce::PkcePair;
pub use sealed::SealedBox;
pub use sealed::SEALED_ENVELOPE_PREFIX;
pub use session::OAuthSession;
pub use ssrf::is_blocked_hostname;
pub use ssrf::is_restricted_ip;
pub use ssrf::is_restricted_ipv4;
pub use ssrf::is_restricted_ipv6;
pub use ssrf::read_bounded_body;
pub use ssrf::SsrfFilter;
pub use ssrf::MAX_OAUTH_RESPONSE_BYTES;
pub use store::OAuthStateStore;
pub use store::OAuthStore;
pub use store::DEFAULT_STATE_TTL;
pub use store::NUM_SHARDS;
pub use verification::ConstantTimeEqSpec;
pub use verification::DPoPHtuFormalSpec;
pub use verification::OAuthStateTransitionModel;
pub use verification::PkceFormalSpec;
pub use verification::SsrfFormalSpec;
pub use verification::StateTransitionStatus;

Modules§

client
High-Level AT Protocol OAuth 2.1 Client.
crypto
Pure safe Rust cryptographic primitives and helper functions.
discovery
OAuth 2.0 Discovery Engine (RFC 8414 & RFC 9728).
dpop
RFC 9449 Demonstrating Proof-of-Possession (DPoP) at the Application Layer.
error
Strongly-typed error definitions for skyauth.
identity
Decentralized Identity and Handle Resolution Engine.
integrations
Framework integrations and middleware for Axum, Actix-web, and Tower.
kernels
Pure, dependency-light security kernels shared by skyauth and its formal verification layers.
par
RFC 9126 Pushed Authorization Requests (PAR) and Authorization URL Builder.
pkce
RFC 7636 Proof Key for Code Exchange (PKCE) primitives.
sealed
Authenticated encryption at rest for sensitive credentials (AES-256-GCM).
session
Authenticated OAuth Session representation and token management.
ssrf
Server-Side Request Forgery (SSRF) boundary filtering and DNS rebinding defense.
store
Sharded Concurrent OAuth State Store and Storage Abstractions.
verification
Formal Specification & Verification Suite for skyauth.

Macros§

anti_vacuity_cover
Helper macro for recording anti-vacuity reachability under both Kani and standard execution.