JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Update for auth

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨3ef0383

⁨giterated-daemon/src/connection/authentication.rs⁩ - ⁨5245⁩ bytes
Raw
1 use anyhow::Error;
2 use thiserror::Error;
3 use tokio::{fs::File, io::AsyncReadExt};
4
5 use crate::message::{AuthenticatedInstance, Message, MessageHandler, NetworkMessage, State};
6 use giterated_models::{
7 messages::authentication::{
8 AuthenticationTokenRequest, AuthenticationTokenResponse, RegisterAccountRequest,
9 TokenExtensionRequest,
10 },
11 model::authenticated::InstanceAuthenticator,
12 };
13
14 use super::wrapper::ConnectionState;
15
16 pub async fn authentication_handle(
17 message_type: &str,
18 message: &NetworkMessage,
19 state: &ConnectionState,
20 ) -> Result<bool, Error> {
21 match message_type {
22 "giterated_models::messages::authentication::RegisterAccountRequest" => {
23 register_account_request
24 .handle_message(&message, state)
25 .await?;
26
27 Ok(true)
28 }
29 "giterated_models::messages::authentication::AuthenticationTokenRequest" => {
30 authentication_token_request
31 .handle_message(&message, state)
32 .await?;
33
34 Ok(true)
35 }
36 "giterated_models::messages::authentication::TokenExtensionRequest" => {
37 token_extension_request
38 .handle_message(&message, state)
39 .await?;
40
41 Ok(true)
42 }
43 _ => Ok(false),
44 }
45 }
46
47 async fn register_account_request(
48 State(connection_state): State<ConnectionState>,
49 Message(request): Message<RegisterAccountRequest>,
50 instance: AuthenticatedInstance,
51 ) -> Result<(), AuthenticationConnectionError> {
52 if *instance.inner() != connection_state.instance {
53 return Err(AuthenticationConnectionError::SameInstance);
54 }
55
56 let mut user_backend = connection_state.user_backend.lock().await;
57
58 let response = user_backend
59 .register(request.clone())
60 .await
61 .map_err(|e| AuthenticationConnectionError::Registration(e))?;
62 drop(user_backend);
63
64 connection_state
65 .send(response)
66 .await
67 .map_err(|e| AuthenticationConnectionError::Sending(e))?;
68
69 Ok(())
70 }
71
72 async fn authentication_token_request(
73 State(connection_state): State<ConnectionState>,
74 Message(request): Message<AuthenticationTokenRequest>,
75 instance: AuthenticatedInstance,
76 ) -> Result<(), AuthenticationConnectionError> {
77 if request.instance != connection_state.instance {
78 // We need to perform the authentication request on behalf of
79 // the user. TODO: Oauth-style flow
80 let mut connections = connection_state.instance_connections.lock().await;
81
82 let issued_for = instance.inner().clone();
83
84 let connection = connections.get_or_open(&request.instance).unwrap();
85
86 let private_key = {
87 let mut file = File::open(
88 connection_state.config["giterated"]["keys"]["private"]
89 .as_str()
90 .unwrap(),
91 )
92 .await
93 .unwrap();
94
95 let mut key = String::new();
96 file.read_to_string(&mut key).await.unwrap();
97
98 key
99 };
100
101 info!("Our private key: {}", private_key);
102
103 let authenticator = InstanceAuthenticator {
104 instance: connection_state.instance.clone(),
105 private_key,
106 };
107
108 let request = AuthenticationTokenRequest {
109 issued_for: Some(issued_for),
110 ..request
111 };
112
113 let response = giterated_api::request::request_local(request)
114 .authenticate(authenticator)
115 .execute_expect::<AuthenticationTokenResponse>(&connection)
116 .await
117 .unwrap();
118 drop(connection);
119
120 connection_state
121 .send(response)
122 .await
123 .map_err(|e| AuthenticationConnectionError::Sending(e))?;
124
125 return Ok(());
126 }
127
128 let mut user_backend = connection_state.user_backend.lock().await;
129
130 let response = user_backend.login(request).await.map_err(|e| AuthenticationConnectionError::TokenIssuance(e))?;
131
132 connection_state
133 .send(response)
134 .await
135 .map_err(|e| AuthenticationConnectionError::Sending(e))?;
136
137 Ok(())
138 }
139
140 async fn token_extension_request(
141 State(connection_state): State<ConnectionState>,
142 Message(request): Message<TokenExtensionRequest>,
143 instance: AuthenticatedInstance,
144 ) -> Result<(), AuthenticationConnectionError> {
145 let issued_for = instance.inner().clone();
146
147 let mut token_granter = connection_state.auth_granter.lock().await;
148
149 let response = token_granter
150 .extension_request(&issued_for, &connection_state.key_cache, request.token)
151 .await
152 .map_err(|e| AuthenticationConnectionError::TokenIssuance(e))?;
153
154 connection_state
155 .send(response)
156 .await
157 .map_err(|e| AuthenticationConnectionError::Sending(e))?;
158
159 Ok(())
160 }
161
162 #[derive(Debug, Error)]
163 pub enum AuthenticationConnectionError {
164 #[error("the request was invalid")]
165 InvalidRequest,
166 #[error("request must be from the same instance")]
167 SameInstance,
168 #[error("issue during registration {0}")]
169 Registration(Error),
170 #[error("sending error")]
171 Sending(Error),
172 #[error("error issuing token")]
173 TokenIssuance(Error),
174 }
175