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;