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

ambee/giterated

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

Fix authenticated endpoints

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨1400b06

⁨giterated-models/src/model/authenticated.rs⁩ - ⁨5554⁩ bytes
Raw
1 use std::{any::type_name, fmt::Debug};
2
3 use rsa::{
4 pkcs1::DecodeRsaPrivateKey,
5 pss::SigningKey,
6 sha2::Sha256,
7 signature::{RandomizedSigner, SignatureEncoding},
8 RsaPrivateKey,
9 };
10 use serde::{Deserialize, Serialize};
11 use tracing::info;
12
13 use super::{instance::Instance, user::User};
14
15 #[derive(Debug, Serialize, Deserialize)]
16 pub struct UserTokenMetadata {
17 pub user: User,
18 pub generated_for: Instance,
19 pub exp: u64,
20 }
21
22 #[derive(Debug)]
23 pub struct Authenticated<'a, T: Serialize> {
24 pub target_instance: Option<Instance>,
25 pub source: Vec<&'a dyn AuthenticationSourceProvider>,
26 pub message_type: String,
27 pub message: T,
28 }
29
30 #[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
31 pub struct AuthenticatedPayload {
32 pub target_instance: Option<Instance>,
33 pub source: Vec<AuthenticationSource>,
34 pub message_type: String,
35 pub payload: Vec<u8>,
36 }
37
38 impl<'a, T: Serialize> From<Authenticated<'a, T>> for AuthenticatedPayload {
39 fn from(mut value: Authenticated<'a, T>) -> Self {
40 let payload = bincode::serialize(&value.message).unwrap();
41
42 AuthenticatedPayload {
43 target_instance: value.target_instance,
44 source: value
45 .source
46 .drain(..)
47 .map(|provider| provider.authenticate(&payload))
48 .collect::<Vec<_>>(),
49 message_type: value.message_type,
50 payload,
51 }
52 }
53 }
54
55 pub trait AuthenticationSourceProvider: Debug {
56 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource;
57 }
58
59 pub trait AuthenticationSourceProviders: Debug {
60 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource>;
61 }
62
63 impl<A> AuthenticationSourceProviders for A
64 where
65 A: AuthenticationSourceProvider,
66 {
67 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
68 vec![self.authenticate(payload)]
69 }
70 }
71
72 impl<A, B> AuthenticationSourceProviders for (A, B)
73 where
74 A: AuthenticationSourceProvider,
75 B: AuthenticationSourceProvider,
76 {
77 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
78 let (first, second) = self;
79
80 vec![first.authenticate(payload), second.authenticate(payload)]
81 }
82 }
83
84 impl<'a, T: Serialize + Debug> Authenticated<'a, T> {
85 pub fn new(message: T) -> Self {
86 Self {
87 source: vec![],
88 message_type: type_name::<T>().to_string(),
89 message,
90 target_instance: None,
91 }
92 }
93
94 pub fn new_for(instance: impl ToOwned<Owned = Instance>, message: T) -> Self {
95 Self {
96 source: vec![],
97 message_type: type_name::<T>().to_string(),
98 message,
99 target_instance: Some(instance.to_owned()),
100 }
101 }
102
103 pub fn new_empty(message: T) -> Self {
104 Self {
105 source: vec![],
106 message_type: type_name::<T>().to_string(),
107 message,
108 target_instance: None,
109 }
110 }
111
112 pub fn append_authentication(&mut self, authentication: &'a dyn AuthenticationSourceProvider) {
113 let message_payload = serde_json::to_vec(&self.message).unwrap();
114
115 info!(
116 "Verifying payload: {}",
117 std::str::from_utf8(&message_payload).unwrap()
118 );
119
120 self.source.push(authentication);
121 }
122
123 pub fn into_payload(self) -> AuthenticatedPayload {
124 self.into()
125 }
126 }
127
128 mod verified {}
129
130 #[derive(Clone, Debug)]
131 pub struct UserAuthenticator {
132 pub user: User,
133 pub token: UserAuthenticationToken,
134 }
135
136 impl AuthenticationSourceProvider for UserAuthenticator {
137 fn authenticate(&self, _payload: &Vec<u8>) -> AuthenticationSource {
138 AuthenticationSource::User {
139 user: self.user.clone(),
140 token: self.token.clone(),
141 }
142 }
143 }
144
145 #[derive(Debug, Clone)]
146 pub struct InstanceAuthenticator<'a> {
147 pub instance: Instance,
148 pub private_key: &'a str,
149 }
150
151 impl AuthenticationSourceProvider for InstanceAuthenticator<'_> {
152 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource {
153 let mut rng = rand::thread_rng();
154
155 let private_key = RsaPrivateKey::from_pkcs1_pem(self.private_key).unwrap();
156 let signing_key = SigningKey::<Sha256>::new(private_key);
157 let signature = signing_key.sign_with_rng(&mut rng, &payload);
158
159 AuthenticationSource::Instance {
160 instance: self.instance.clone(),
161 // TODO: Actually parse signature from private key
162 signature: InstanceSignature(signature.to_bytes().into_vec()),
163 }
164 }
165 }
166
167 #[repr(transparent)]
168 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
169 pub struct UserAuthenticationToken(String);
170
171 impl From<String> for UserAuthenticationToken {
172 fn from(value: String) -> Self {
173 Self(value)
174 }
175 }
176
177 impl ToString for UserAuthenticationToken {
178 fn to_string(&self) -> String {
179 self.0.clone()
180 }
181 }
182
183 impl AsRef<str> for UserAuthenticationToken {
184 fn as_ref(&self) -> &str {
185 &self.0
186 }
187 }
188
189 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
190 pub struct InstanceSignature(Vec<u8>);
191
192 impl AsRef<[u8]> for InstanceSignature {
193 fn as_ref(&self) -> &[u8] {
194 &self.0
195 }
196 }
197
198 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
199 pub enum AuthenticationSource {
200 User {
201 user: User,
202 token: UserAuthenticationToken,
203 },
204 Instance {
205 instance: Instance,
206 signature: InstanceSignature,
207 },
208 }
209