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

ambee/giterated

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

Fix authentication

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨cef865c

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