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

ambee/giterated

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

Fixes

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨73a5af5

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