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

ambee/giterated

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

Completely refactor project structure

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨ae8ff44

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