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

ambee/giterated

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

Major post-refactor cleanup

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨f90d7fb

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