A library for ATProtocol identities.
1//! Axum state management for OAuth configuration. 2//! 3//! Request extractors and HTTP client wrappers for OAuth 4//! client configuration injection in handlers. 5 6use atproto_identity::key::KeyData; 7use axum::extract::{FromRef, FromRequestParts}; 8use http::request::Parts; 9use std::convert::Infallible; 10 11#[cfg(feature = "zeroize")] 12use zeroize::{Zeroize, ZeroizeOnDrop}; 13 14/// OAuth client configuration for Axum handlers. 15/// 16/// Contains the essential configuration needed for OAuth client operations. 17#[derive(Clone, Default)] 18#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))] 19pub struct OAuthClientConfig { 20 /// OAuth client identifier 21 #[cfg_attr(feature = "zeroize", zeroize(skip))] 22 pub client_id: String, 23 24 /// Allowed OAuth redirect URIs 25 #[cfg_attr(feature = "zeroize", zeroize(skip))] 26 pub redirect_uris: String, 27 28 /// JSON Web Key Set URI for public keys 29 #[cfg_attr(feature = "zeroize", zeroize(skip))] 30 pub jwks_uri: Option<String>, 31 32 /// Signing keys for JWT operations 33 pub signing_keys: Vec<KeyData>, 34 35 /// OAuth scope, defaults to "atproto transition:generic" 36 #[cfg_attr(feature = "zeroize", zeroize(skip))] 37 pub scope: Option<String>, 38 39 /// Optional human-readable client name 40 #[cfg_attr(feature = "zeroize", zeroize(skip))] 41 pub client_name: Option<String>, 42 43 /// Optional client website URI 44 #[cfg_attr(feature = "zeroize", zeroize(skip))] 45 pub client_uri: Option<String>, 46 47 /// Optional client logo URI 48 #[cfg_attr(feature = "zeroize", zeroize(skip))] 49 pub logo_uri: Option<String>, 50 51 /// Optional terms of service URI 52 #[cfg_attr(feature = "zeroize", zeroize(skip))] 53 pub tos_uri: Option<String>, 54 55 /// Optional privacy policy URI 56 #[cfg_attr(feature = "zeroize", zeroize(skip))] 57 pub policy_uri: Option<String>, 58} 59 60impl OAuthClientConfig { 61 /// Returns the OAuth scope, using the default "atproto transition:generic" if not set. 62 pub fn scope(&self) -> &str { 63 self.scope 64 .as_deref() 65 .unwrap_or("atproto transition:generic") 66 } 67} 68 69impl<S> FromRequestParts<S> for OAuthClientConfig 70where 71 OAuthClientConfig: FromRef<S>, 72 S: Send + Sync, 73{ 74 type Rejection = Infallible; 75 76 /// Extracts OAuth client configuration from Axum application state. 77 async fn from_request_parts(_parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { 78 let oauth_client_config = OAuthClientConfig::from_ref(state); 79 Ok(oauth_client_config) 80 } 81} 82 83/// HTTP client wrapper for dependency injection. 84/// 85/// Wraps a reqwest::Client for use in Axum extractors. 86#[derive(Clone)] 87pub struct HttpClient(pub reqwest::Client); 88 89impl std::ops::Deref for HttpClient { 90 type Target = reqwest::Client; 91 92 /// Provides direct access to the underlying reqwest::Client. 93 fn deref(&self) -> &Self::Target { 94 &self.0 95 } 96} 97 98impl<S> FromRequestParts<S> for HttpClient 99where 100 reqwest::Client: FromRef<S>, 101 S: Send + Sync, 102{ 103 type Rejection = Infallible; 104 105 /// Extracts HTTP client from Axum application state. 106 async fn from_request_parts(_parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { 107 let client = reqwest::Client::from_ref(state); 108 Ok(HttpClient(client)) 109 } 110}