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

ambee/giterated

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

Create `NetworkedSubstack`.

# giterated-protocol - Create `NetworkedSubstack` which will handle all networked operations giterated needs - Add support for `NetworkedSubstack` for both the daemon and client - Pipe everything through but leave APIs temp # `giterated-daemon` - Remove a bunch of random old code, dead code, and files that aren't needed. - Moved all connection handling to `client.rs`, simplified connection logic with new types

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨202bb12

⁨giterated-daemon/src/authentication.rs⁩ - ⁨5154⁩ bytes
Raw
1 use anyhow::Error;
2 use giterated_models::authenticated::{UserAuthenticationToken, UserTokenMetadata};
3
4 use giterated_models::instance::Instance;
5
6 use giterated_models::user::User;
7
8 use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, TokenData, Validation};
9 use std::collections::HashMap;
10 use std::{sync::Arc, time::SystemTime};
11 use tokio::{fs::File, io::AsyncReadExt, sync::Mutex};
12 use toml::Table;
13
14 pub struct AuthenticationTokenGranter {
15 pub config: Table,
16 pub instance: Instance,
17 }
18
19 impl AuthenticationTokenGranter {
20 async fn private_key(&self) -> Vec<u8> {
21 let mut file = File::open(
22 self.config["giterated"]["keys"]["private"]
23 .as_str()
24 .unwrap(),
25 )
26 .await
27 .unwrap();
28
29 let mut key = vec![];
30 file.read_to_end(&mut key).await.unwrap();
31
32 key
33 }
34
35 pub(crate) async fn create_token_for(
36 &mut self,
37 user: &User,
38 generated_for: &Instance,
39 ) -> String {
40 let private_key = self.private_key().await;
41
42 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
43
44 let claims = UserTokenMetadata {
45 user: user.clone(),
46 generated_for: generated_for.clone(),
47 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
48 + std::time::Duration::from_secs(24 * 60 * 60))
49 .as_secs(),
50 };
51
52 encode(
53 &jsonwebtoken::Header::new(Algorithm::RS256),
54 &claims,
55 &encoding_key,
56 )
57 .unwrap()
58 }
59
60 pub async fn token_request(
61 &mut self,
62 issued_for: impl ToOwned<Owned = Instance>,
63 username: String,
64 _password: String,
65 ) -> Result<UserAuthenticationToken, Error> {
66 let private_key = {
67 let mut file = File::open(
68 self.config["giterated"]["keys"]["private"]
69 .as_str()
70 .unwrap(),
71 )
72 .await
73 .unwrap();
74
75 let mut key = vec![];
76 file.read_to_end(&mut key).await.unwrap();
77
78 key
79 };
80
81 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
82
83 let claims = UserTokenMetadata {
84 user: User {
85 username,
86 instance: self.instance.clone(),
87 },
88 generated_for: issued_for.to_owned(),
89 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
90 + std::time::Duration::from_secs(24 * 60 * 60))
91 .as_secs(),
92 };
93
94 let token = encode(
95 &jsonwebtoken::Header::new(Algorithm::RS256),
96 &claims,
97 &encoding_key,
98 )
99 .unwrap();
100
101 Ok(UserAuthenticationToken::from(token))
102 }
103
104 pub async fn extension_request(
105 &mut self,
106 issued_for: &Instance,
107 key_cache: &Arc<Mutex<PublicKeyCache>>,
108 token: UserAuthenticationToken,
109 ) -> Result<Option<UserAuthenticationToken>, Error> {
110 let mut key_cache = key_cache.lock().await;
111 let server_public_key = key_cache.get(issued_for).await?;
112 drop(key_cache);
113
114 let verification_key = DecodingKey::from_rsa_pem(server_public_key.as_bytes()).unwrap();
115
116 let data: TokenData<UserTokenMetadata> = decode(
117 token.as_ref(),
118 &verification_key,
119 &Validation::new(Algorithm::RS256),
120 )
121 .unwrap();
122
123 if data.claims.generated_for != *issued_for {
124 panic!()
125 }
126
127 let private_key = {
128 let mut file = File::open(
129 self.config["giterated"]["keys"]["private"]
130 .as_str()
131 .unwrap(),
132 )
133 .await
134 .unwrap();
135
136 let mut key = vec![];
137 file.read_to_end(&mut key).await.unwrap();
138
139 key
140 };
141
142 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
143
144 let claims = UserTokenMetadata {
145 // TODO: Probably exploitable
146 user: data.claims.user,
147 generated_for: issued_for.clone(),
148 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
149 + std::time::Duration::from_secs(24 * 60 * 60))
150 .as_secs(),
151 };
152
153 let token = encode(
154 &jsonwebtoken::Header::new(Algorithm::RS256),
155 &claims,
156 &encoding_key,
157 )
158 .unwrap();
159
160 Ok(Some(UserAuthenticationToken::from(token)))
161 }
162 }
163
164 #[derive(Default)]
165 pub struct PublicKeyCache {
166 pub keys: HashMap<Instance, String>,
167 }
168
169 impl PublicKeyCache {
170 pub async fn get(&mut self, instance: &Instance) -> Result<String, Error> {
171 if let Some(key) = self.keys.get(instance) {
172 Ok(key.clone())
173 } else {
174 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance))
175 .await?
176 .text()
177 .await?;
178
179 self.keys.insert(instance.clone(), key);
180
181 Ok(self.keys.get(instance).unwrap().clone())
182 }
183 }
184 }
185