1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//! # `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
//!
//! ```rust
//! use skyauth::dpop::{DPoPKey, DPoPVerifier, compute_access_token_hash};
//! use skyauth::pkce::PkcePair;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // 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");
//! # Ok(())
//! # }
//! ```
//!
//! ### OAuth Client Lifecycle
//!
//! ```rust,no_run
//! use skyauth::client::{AtprotoOAuthClient, CallbackParams, OAuthClientMetadata};
//! use skyauth::store::OAuthStateStore;
//! use std::sync::Arc;
//! use std::time::Duration;
//!
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! 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?;
//! # Ok(())
//! # }
//! ```
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use OAuthSession;
pub use ;
pub use ;
pub use ;