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

ambee/giterated

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

Major connection refactor base

Type: Refactor

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨8dcc111

⁨src/authentication.rs⁩ - ⁨5150⁩ 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::{authenticated::UserAuthenticationToken, 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 issued_for: impl ToOwned<Owned = Instance>,
78 username: String,
79 password: String,
80 ) -> Result<AuthenticationTokenResponse, Error> {
81 let private_key = {
82 let mut file = File::open(
83 self.config["giterated"]["keys"]["private"]
84 .as_str()
85 .unwrap(),
86 )
87 .await
88 .unwrap();
89
90 let mut key = vec![];
91 file.read_to_end(&mut key).await.unwrap();
92
93 key
94 };
95
96 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
97
98 let claims = UserTokenMetadata {
99 user: User {
100 username,
101 instance: self.instance.clone(),
102 },
103 generated_for: issued_for.to_owned(),
104 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
105 + std::time::Duration::from_secs(24 * 60 * 60))
106 .as_secs(),
107 };
108
109 let token = encode(
110 &jsonwebtoken::Header::new(Algorithm::RS256),
111 &claims,
112 &encoding_key,
113 )
114 .unwrap();
115
116 Ok(AuthenticationTokenResponse { token })
117 }
118
119 pub async fn extension_request(
120 &mut self,
121 issued_for: &Instance,
122 token: UserAuthenticationToken,
123 ) -> Result<TokenExtensionResponse, Error> {
124 let server_public_key = public_key(&self.instance).await.unwrap();
125
126 let verification_key = DecodingKey::from_rsa_pem(server_public_key.as_bytes()).unwrap();
127
128 let data: TokenData<UserTokenMetadata> = decode(
129 token.as_ref(),
130 &verification_key,
131 &Validation::new(Algorithm::RS256),
132 )
133 .unwrap();
134
135 if data.claims.generated_for != *issued_for {
136 panic!()
137 }
138
139 info!("Token Extension Request Token validated");
140
141 let private_key = {
142 let mut file = File::open(
143 self.config["giterated"]["keys"]["private"]
144 .as_str()
145 .unwrap(),
146 )
147 .await
148 .unwrap();
149
150 let mut key = vec![];
151 file.read_to_end(&mut key).await.unwrap();
152
153 key
154 };
155
156 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
157
158 let claims = UserTokenMetadata {
159 // TODO: Probably exploitable
160 user: data.claims.user,
161 generated_for: issued_for.clone(),
162 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
163 + std::time::Duration::from_secs(24 * 60 * 60))
164 .as_secs(),
165 };
166
167 let token = encode(
168 &jsonwebtoken::Header::new(Algorithm::RS256),
169 &claims,
170 &encoding_key,
171 )
172 .unwrap();
173
174 Ok(TokenExtensionResponse {
175 new_token: Some(token),
176 })
177 }
178 }
179
180 async fn public_key(instance: &Instance) -> Result<String, Error> {
181 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url))
182 .await?
183 .text()
184 .await?;
185
186 Ok(key)
187 }
188