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

ambee/giterated

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

Change forwarding

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨2556801

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