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

ambee/giterated

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

Check if requesting user is allowed to see the repository

Type: Fix

emilia - ⁨2⁩ years ago

parent: tbd commit: ⁨1b40c1d

⁨src/authentication.rs⁩ - ⁨5076⁩ 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 {
111 token: UserAuthenticationToken::from(token),
112 })
113 }
114
115 pub async fn extension_request(
116 &mut self,
117 issued_for: &Instance,
118 token: UserAuthenticationToken,
119 ) -> Result<TokenExtensionResponse, Error> {
120 let server_public_key = public_key(&self.instance).await.unwrap();
121
122 let verification_key = DecodingKey::from_rsa_pem(server_public_key.as_bytes()).unwrap();
123
124 let data: TokenData<UserTokenMetadata> = decode(
125 token.as_ref(),
126 &verification_key,
127 &Validation::new(Algorithm::RS256),
128 )
129 .unwrap();
130
131 if data.claims.generated_for != *issued_for {
132 panic!()
133 }
134
135 info!("Token Extension Request Token validated");
136
137 let private_key = {
138 let mut file = File::open(
139 self.config["giterated"]["keys"]["private"]
140 .as_str()
141 .unwrap(),
142 )
143 .await
144 .unwrap();
145
146 let mut key = vec![];
147 file.read_to_end(&mut key).await.unwrap();
148
149 key
150 };
151
152 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
153
154 let claims = UserTokenMetadata {
155 // TODO: Probably exploitable
156 user: data.claims.user,
157 generated_for: issued_for.clone(),
158 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
159 + std::time::Duration::from_secs(24 * 60 * 60))
160 .as_secs(),
161 };
162
163 let token = encode(
164 &jsonwebtoken::Header::new(Algorithm::RS256),
165 &claims,
166 &encoding_key,
167 )
168 .unwrap();
169
170 Ok(TokenExtensionResponse {
171 new_token: Some(token),
172 })
173 }
174 }
175
176 async fn public_key(instance: &Instance) -> Result<String, Error> {
177 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url))
178 .await?
179 .text()
180 .await?;
181
182 Ok(key)
183 }
184