atproto_oauth_aip/lib.rs
1//! # AT Protocol OAuth AIP (Identity Provider) Implementation
2//!
3//! This crate provides a comprehensive OAuth 2.0 workflow implementation for AT Protocol
4//! Identity Providers (AIPs). It handles the complete OAuth flow including Pushed
5//! Authorization Requests (PAR), token exchange, and session management according to
6//! AT Protocol specifications.
7//!
8//! ## Key Features
9//!
10//! - **OAuth 2.0 Authorization Code Flow**: Complete implementation with PKCE support
11//! - **Pushed Authorization Requests (PAR)**: Enhanced security through server-side request storage
12//! - **Token Exchange**: Secure token issuance and refresh capabilities
13//! - **Session Management**: AT Protocol session establishment and validation
14//! - **Resource Validation**: OAuth protected resource and authorization server validation
15//!
16//! ## Usage
17//!
18//! The primary entry point is the workflow module which provides functions for each
19//! stage of the OAuth flow:
20//!
21//! ```rust,no_run
22//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
23//! use atproto_oauth_aip::workflow::{oauth_init, oauth_complete, session_exchange, OAuthClient};
24//! use atproto_oauth::resources::AuthorizationServer;
25//! use atproto_oauth::workflow::OAuthRequestState;
26//!
27//! let http_client = reqwest::Client::new();
28//! let oauth_client = OAuthClient {
29//! redirect_uri: "https://redirect.example.com/callback".to_string(),
30//! client_id: "client123".to_string(),
31//! client_secret: "secret456".to_string(),
32//! };
33//!
34//! let authorization_server = AuthorizationServer {
35//! issuer: "https://auth.example.com".to_string(),
36//! authorization_endpoint: "https://auth.example.com/authorize".to_string(),
37//! token_endpoint: "https://auth.example.com/token".to_string(),
38//! pushed_authorization_request_endpoint: "https://auth.example.com/par".to_string(),
39//! introspection_endpoint: "".to_string(),
40//! scopes_supported: vec!["atproto".to_string(), "transition:generic".to_string()],
41//! response_types_supported: vec!["code".to_string()],
42//! grant_types_supported: vec!["authorization_code".to_string(), "refresh_token".to_string()],
43//! token_endpoint_auth_methods_supported: vec!["none".to_string(), "private_key_jwt".to_string()],
44//! token_endpoint_auth_signing_alg_values_supported: vec!["ES256".to_string()],
45//! require_pushed_authorization_requests: true,
46//! request_parameter_supported: false,
47//! code_challenge_methods_supported: vec!["S256".to_string()],
48//! authorization_response_iss_parameter_supported: true,
49//! dpop_signing_alg_values_supported: vec!["ES256".to_string()],
50//! client_id_metadata_document_supported: true,
51//! };
52//!
53//! let oauth_request_state = OAuthRequestState {
54//! state: "random-state".to_string(),
55//! nonce: "random-nonce".to_string(),
56//! code_challenge: "code-challenge".to_string(),
57//! scope: "atproto transition:generic".to_string(),
58//! };
59//!
60//! // Initialize OAuth flow with PAR
61//! let par_response = oauth_init(
62//! &http_client,
63//! &oauth_client,
64//! Some("user_handle"),
65//! &authorization_server,
66//! &oauth_request_state
67//! ).await?;
68//!
69//! // Complete OAuth flow with authorization code
70//! # let oauth_request = atproto_oauth::workflow::OAuthRequest {
71//! # oauth_state: "state".to_string(),
72//! # issuer: "https://auth.example.com".to_string(),
73//! # did: "did:plc:example".to_string(),
74//! # nonce: "nonce".to_string(),
75//! # signing_public_key: "public_key".to_string(),
76//! # pkce_verifier: "verifier".to_string(),
77//! # dpop_private_key: "private_key".to_string(),
78//! # created_at: chrono::Utc::now(),
79//! # expires_at: chrono::Utc::now() + chrono::Duration::hours(1),
80//! # };
81//! let token_response = oauth_complete(
82//! &http_client,
83//! &oauth_client,
84//! &authorization_server,
85//! "authorization_code",
86//! &oauth_request
87//! ).await?;
88//!
89//! // Exchange tokens for AT Protocol session
90//! # let protected_resource = atproto_oauth::resources::OAuthProtectedResource {
91//! # resource: "https://pds.example.com".to_string(),
92//! # scopes_supported: vec!["atproto".to_string()],
93//! # bearer_methods_supported: vec!["header".to_string()],
94//! # authorization_servers: vec!["https://auth.example.com".to_string()],
95//! # };
96//! let session = session_exchange(
97//! &http_client,
98//! &protected_resource,
99//! &token_response.access_token
100//! ).await?;
101//! # Ok(())
102//! # }
103//! ```
104//!
105//! ## Error Handling
106//!
107//! All operations use structured error types with descriptive messages following
108//! the project's error convention format.
109
110#![forbid(unsafe_code)]
111#![warn(missing_docs)]
112
113/// Error types for OAuth workflow operations.
114pub mod errors;
115/// Resource definitions for OAuth operations.
116pub mod resources;
117/// OAuth workflow implementation.
118pub mod workflow;