1#![doc = include_str!("../README.md")]
2mod atproto;
3mod constants;
4mod error;
5mod http_client;
6mod jose;
7mod keyset;
8mod oauth_client;
9mod oauth_session;
10mod resolver;
11mod server_agent;
12pub mod store;
13mod types;
14mod utils;
15
16pub use atproto::{
17 AtprotoClientMetadata, AtprotoLocalhostClientMetadata, AuthMethod, GrantType, KnownScope, Scope,
18};
19pub use error::{Error, Result};
20#[cfg(feature = "default-client")]
21pub use http_client::default::DefaultHttpClient;
22pub use http_client::dpop::DpopClient;
23pub use oauth_client::{OAuthClient, OAuthClientConfig};
24pub use oauth_session::OAuthSession;
25pub use resolver::OAuthResolverConfig;
26pub use types::{
27 AuthorizeOptionPrompt, AuthorizeOptions, CallbackParams, OAuthClientMetadata, TokenSet,
28};
29
30#[cfg(test)]
31mod tests {
32 use crate::{
33 resolver::OAuthResolver,
34 types::{
35 OAuthAuthorizationServerMetadata, OAuthClientMetadata, OAuthProtectedResourceMetadata,
36 TryIntoOAuthClientMetadata,
37 },
38 AtprotoLocalhostClientMetadata, OAuthResolverConfig,
39 };
40 use atrium_api::{
41 did_doc::{DidDocument, Service},
42 types::string::{Did, Handle},
43 };
44 use atrium_common::resolver::Resolver;
45 use atrium_xrpc::HttpClient;
46 use jose_jwk::Key;
47 use std::sync::Arc;
48
49 pub struct MockDidResolver;
50
51 impl Resolver for MockDidResolver {
52 type Input = Did;
53 type Output = DidDocument;
54 type Error = atrium_identity::Error;
55 async fn resolve(&self, did: &Self::Input) -> Result<Self::Output, Self::Error> {
56 Ok(DidDocument {
57 context: None,
58 id: did.as_ref().to_string(),
59 also_known_as: None,
60 verification_method: None,
61 service: Some(vec![Service {
62 id: String::from("#atproto_pds"),
63 r#type: String::from("AtprotoPersonalDataServer"),
64 service_endpoint: String::from("https://aud.example.com"),
65 }]),
66 })
67 }
68 }
69
70 pub struct NoopHandleResolver;
71
72 impl Resolver for NoopHandleResolver {
73 type Input = Handle;
74 type Output = Did;
75 type Error = atrium_identity::Error;
76 async fn resolve(&self, _: &Self::Input) -> Result<Self::Output, Self::Error> {
77 unimplemented!()
78 }
79 }
80
81 pub fn oauth_resolver<T>(
82 http_client: Arc<T>,
83 ) -> OAuthResolver<T, MockDidResolver, NoopHandleResolver>
84 where
85 T: HttpClient + Send + Sync,
86 {
87 OAuthResolver::new(
88 OAuthResolverConfig {
89 did_resolver: MockDidResolver,
90 handle_resolver: NoopHandleResolver,
91 authorization_server_metadata: Default::default(),
92 protected_resource_metadata: Default::default(),
93 },
94 http_client,
95 )
96 }
97
98 pub fn dpop_key() -> Key {
99 serde_json::from_str(
100 r#"{
101 "kty": "EC",
102 "crv": "P-256",
103 "x": "NIRNgPVAwnVNzN5g2Ik2IMghWcjnBOGo9B-lKXSSXFs",
104 "y": "iWF-Of43XoSTZxcadO9KWdPTjiCoviSztYw7aMtZZMc",
105 "d": "9MuCYfKK4hf95p_VRj6cxKJwORTgvEU3vynfmSgFH2M"
106 }"#,
107 )
108 .expect("key should be valid")
109 }
110
111 pub fn server_metadata() -> OAuthAuthorizationServerMetadata {
112 OAuthAuthorizationServerMetadata {
113 issuer: String::from("https://iss.example.com"),
114 token_endpoint: String::from("https://iss.example.com/token"),
115 token_endpoint_auth_methods_supported: Some(vec![
116 String::from("none"),
117 String::from("private_key_jwt"),
118 ]),
119 ..Default::default()
120 }
121 }
122
123 pub fn client_metadata() -> OAuthClientMetadata {
124 AtprotoLocalhostClientMetadata::default()
125 .try_into_client_metadata(&None)
126 .expect("client metadata should be valid")
127 }
128
129 pub fn protected_resource_metadata() -> OAuthProtectedResourceMetadata {
130 OAuthProtectedResourceMetadata {
131 resource: String::from("https://aud.example.com"),
132 authorization_servers: Some(vec![String::from("https://iss.example.com")]),
133 ..Default::default()
134 }
135 }
136}