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

ambee/giterated

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

Add docs

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨51aad53

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