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

ambee/giterated

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

woo

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨2d48bc0

⁨src/authentication.rs⁩ - ⁨6514⁩ bytes
Raw
1 use anyhow::Error;
2 use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, TokenData, Validation};
3 use serde::{Deserialize, Serialize};
4 use std::time::SystemTime;
5 use tokio::{fs::File, io::AsyncReadExt};
6 use toml::Table;
7
8 use crate::{
9 messages::{
10 authentication::{
11 AuthenticationTokenRequest, AuthenticationTokenResponse, TokenExtensionRequest,
12 TokenExtensionResponse,
13 },
14 InstanceAuthenticated,
15 },
16 model::{instance::Instance, user::User},
17 };
18
19 #[derive(Debug, Serialize, Deserialize)]
20 pub struct UserTokenMetadata {
21 pub user: User,
22 pub generated_for: Instance,
23 exp: u64,
24 }
25
26 pub struct AuthenticationTokenGranter {
27 pub config: Table,
28 }
29
30 impl AuthenticationTokenGranter {
31 async fn private_key(&self) -> Vec<u8> {
32 let _secret_key = self.config["authentication"]["secret_key"]
33 .as_str()
34 .unwrap();
35 let mut file = File::open(
36 self.config["giterated"]["keys"]["private"]
37 .as_str()
38 .unwrap(),
39 )
40 .await
41 .unwrap();
42
43 let mut key = vec![];
44 file.read_to_end(&mut key).await.unwrap();
45
46 key
47 }
48
49 pub(crate) async fn create_token_for(
50 &mut self,
51 user: &User,
52 generated_for: &Instance,
53 ) -> String {
54 let private_key = self.private_key().await;
55
56 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
57
58 let claims = UserTokenMetadata {
59 user: user.clone(),
60 generated_for: generated_for.clone(),
61 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
62 + std::time::Duration::from_secs(24 * 60 * 60))
63 .as_secs(),
64 };
65
66 encode(
67 &jsonwebtoken::Header::new(Algorithm::RS256),
68 &claims,
69 &encoding_key,
70 )
71 .unwrap()
72 }
73
74 pub async fn token_request(
75 &mut self,
76 raw_request: InstanceAuthenticated<AuthenticationTokenRequest>,
77 ) -> Result<AuthenticationTokenResponse, Error> {
78 let request = raw_request.inner().await;
79
80 info!("Ensuring token request is from the same instance...");
81 raw_request
82 .validate(&Instance {
83 url: String::from("giterated.dev"),
84 })
85 .await
86 .unwrap();
87
88 let secret_key = self.config["authentication"]["secret_key"]
89 .as_str()
90 .unwrap();
91 let private_key = {
92 let mut file = File::open(
93 self.config["giterated"]["keys"]["private"]
94 .as_str()
95 .unwrap(),
96 )
97 .await
98 .unwrap();
99
100 let mut key = vec![];
101 file.read_to_end(&mut key).await.unwrap();
102
103 key
104 };
105
106 if request.secret_key != secret_key {
107 error!("Incorrect secret key!");
108
109 panic!()
110 }
111
112 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
113
114 let claims = UserTokenMetadata {
115 user: User {
116 username: String::from("ambee"),
117 instance: Instance {
118 url: String::from("giterated.dev"),
119 },
120 },
121 generated_for: Instance {
122 url: String::from("giterated.dev"),
123 },
124 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
125 + std::time::Duration::from_secs(24 * 60 * 60))
126 .as_secs(),
127 };
128
129 let token = encode(
130 &jsonwebtoken::Header::new(Algorithm::RS256),
131 &claims,
132 &encoding_key,
133 )
134 .unwrap();
135
136 Ok(AuthenticationTokenResponse { token })
137 }
138
139 pub async fn extension_request(
140 &mut self,
141 raw_request: InstanceAuthenticated<TokenExtensionRequest>,
142 ) -> Result<TokenExtensionResponse, Error> {
143 let request = raw_request.inner().await;
144
145 // let server_public_key = {
146 // let mut file = File::open(self.config["keys"]["public"].as_str().unwrap())
147 // .await
148 // .unwrap();
149
150 // let mut key = String::default();
151 // file.read_to_string(&mut key).await.unwrap();
152
153 // key
154 // };
155
156 let server_public_key = public_key(&Instance {
157 url: String::from("giterated.dev"),
158 })
159 .await
160 .unwrap();
161
162 let verification_key = DecodingKey::from_rsa_pem(server_public_key.as_bytes()).unwrap();
163
164 let data: TokenData<UserTokenMetadata> = decode(
165 &request.token,
166 &verification_key,
167 &Validation::new(Algorithm::RS256),
168 )
169 .unwrap();
170
171 info!("Token Extension Request Token validated");
172
173 let secret_key = self.config["authentication"]["secret_key"]
174 .as_str()
175 .unwrap();
176
177 if request.secret_key != secret_key {
178 error!("Incorrect secret key!");
179
180 panic!()
181 }
182 // Validate request
183 raw_request
184 .validate(&data.claims.generated_for)
185 .await
186 .unwrap();
187 info!("Validated request for key extension");
188
189 let private_key = {
190 let mut file = File::open(
191 self.config["giterated"]["keys"]["private"]
192 .as_str()
193 .unwrap(),
194 )
195 .await
196 .unwrap();
197
198 let mut key = vec![];
199 file.read_to_end(&mut key).await.unwrap();
200
201 key
202 };
203
204 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
205
206 let claims = UserTokenMetadata {
207 // TODO: Probably exploitable
208 user: data.claims.user,
209 generated_for: data.claims.generated_for,
210 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
211 + std::time::Duration::from_secs(24 * 60 * 60))
212 .as_secs(),
213 };
214
215 let token = encode(
216 &jsonwebtoken::Header::new(Algorithm::RS256),
217 &claims,
218 &encoding_key,
219 )
220 .unwrap();
221
222 Ok(TokenExtensionResponse {
223 new_token: Some(token),
224 })
225 }
226 }
227
228 async fn public_key(instance: &Instance) -> Result<String, Error> {
229 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url))
230 .await?
231 .text()
232 .await?;
233
234 Ok(key)
235 }
236