interactive intro to open social at-me.zzstoatzz.io
at ci-setup 100 lines 3.8 kB view raw
1use atrium_identity::{ 2 did::{CommonDidResolver, CommonDidResolverConfig, DEFAULT_PLC_DIRECTORY_URL}, 3 handle::{AtprotoHandleResolver, AtprotoHandleResolverConfig, DnsTxtResolver}, 4}; 5use atrium_oauth::{ 6 AtprotoClientMetadata, AtprotoLocalhostClientMetadata, AuthMethod, DefaultHttpClient, 7 GrantType, KnownScope, OAuthClient, OAuthClientConfig, OAuthResolverConfig, Scope, 8 store::{session::MemorySessionStore, state::MemoryStateStore}, 9}; 10use hickory_resolver::{TokioAsyncResolver, config::{ResolverConfig, ResolverOpts}}; 11use std::sync::Arc; 12 13#[derive(Clone)] 14pub struct HickoryDnsResolver(Arc<TokioAsyncResolver>); 15 16impl DnsTxtResolver for HickoryDnsResolver { 17 async fn resolve( 18 &self, 19 domain: &str, 20 ) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> { 21 Ok(self 22 .0 23 .txt_lookup(domain) 24 .await? 25 .iter() 26 .map(|txt| txt.to_string()) 27 .collect()) 28 } 29} 30 31pub type OAuthClientType = Arc< 32 OAuthClient< 33 MemoryStateStore, 34 MemorySessionStore, 35 CommonDidResolver<DefaultHttpClient>, 36 AtprotoHandleResolver<HickoryDnsResolver, DefaultHttpClient>, 37 >, 38>; 39 40pub fn create_oauth_client() -> OAuthClientType { 41 let http_client = Arc::new(DefaultHttpClient::default()); 42 let dns_resolver = HickoryDnsResolver(Arc::new( 43 TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default()), 44 )); 45 46 let redirect_uri = std::env::var("OAUTH_REDIRECT_URI") 47 .unwrap_or_else(|_| "http://127.0.0.1:8080/oauth/callback".to_string()); 48 49 let is_production = redirect_uri.starts_with("https://"); 50 51 let resolver = OAuthResolverConfig { 52 did_resolver: CommonDidResolver::new(CommonDidResolverConfig { 53 plc_directory_url: DEFAULT_PLC_DIRECTORY_URL.to_string(), 54 http_client: http_client.clone(), 55 }), 56 handle_resolver: AtprotoHandleResolver::new(AtprotoHandleResolverConfig { 57 dns_txt_resolver: dns_resolver, 58 http_client: http_client.clone(), 59 }), 60 authorization_server_metadata: Default::default(), 61 protected_resource_metadata: Default::default(), 62 }; 63 64 if is_production { 65 let base_url = redirect_uri.trim_end_matches("/oauth/callback"); 66 Arc::new( 67 OAuthClient::new(OAuthClientConfig { 68 client_metadata: AtprotoClientMetadata { 69 client_id: format!("{}/oauth-client-metadata.json", base_url), 70 client_uri: Some(base_url.to_string()), 71 redirect_uris: vec![redirect_uri], 72 token_endpoint_auth_method: AuthMethod::None, 73 grant_types: vec![GrantType::AuthorizationCode, GrantType::RefreshToken], 74 scopes: vec![Scope::Known(KnownScope::Atproto)], 75 jwks_uri: None, 76 token_endpoint_auth_signing_alg: None, 77 }, 78 keys: None, 79 resolver, 80 state_store: MemoryStateStore::default(), 81 session_store: MemorySessionStore::default(), 82 }) 83 .expect("failed to create oauth client"), 84 ) 85 } else { 86 Arc::new( 87 OAuthClient::new(OAuthClientConfig { 88 client_metadata: AtprotoLocalhostClientMetadata { 89 redirect_uris: Some(vec![redirect_uri]), 90 scopes: Some(vec![Scope::Known(KnownScope::Atproto)]), 91 }, 92 keys: None, 93 resolver, 94 state_store: MemoryStateStore::default(), 95 session_store: MemorySessionStore::default(), 96 }) 97 .expect("failed to create oauth client"), 98 ) 99 } 100}