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

ambee/giterated

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

Add Instance Authentication

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨5a042fd

⁨src/authentication.rs⁩ - ⁨5291⁩ bytes
Raw
1 use std::{error::Error, time::SystemTime};
2
3 use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, TokenData, Validation};
4 use serde::{Deserialize, Serialize};
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 struct UserTokenMetadata {
21 user: User,
22 generated_for: Instance,
23 exp: u64,
24 }
25
26 pub struct AuthenticationTokenGranter {
27 pub config: Table,
28 }
29
30 impl AuthenticationTokenGranter {
31 pub async fn token_request(
32 &mut self,
33 raw_request: InstanceAuthenticated<AuthenticationTokenRequest>,
34 ) -> Result<AuthenticationTokenResponse, Box<dyn Error + Send>> {
35 let request = raw_request.inner().await;
36
37 info!("Ensuring token request is from the same instance...");
38 raw_request
39 .validate(&Instance {
40 url: String::from("giterated.dev"),
41 })
42 .await
43 .unwrap();
44
45 let secret_key = self.config["authentication"]["secret_key"]
46 .as_str()
47 .unwrap();
48 let private_key = {
49 let mut file = File::open(self.config["keys"]["private"].as_str().unwrap())
50 .await
51 .unwrap();
52
53 let mut key = vec![];
54 file.read_to_end(&mut key).await.unwrap();
55
56 key
57 };
58
59 if request.secret_key != secret_key {
60 error!("Incorrect secret key!");
61
62 panic!()
63 }
64
65 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
66
67 let claims = UserTokenMetadata {
68 user: User {
69 username: String::from("ambee"),
70 instance: Instance {
71 url: String::from("giterated.dev"),
72 },
73 },
74 generated_for: Instance {
75 url: String::from("giterated.dev"),
76 },
77 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
78 + std::time::Duration::from_secs(24 * 60 * 60))
79 .as_secs(),
80 };
81
82 let token = encode(
83 &jsonwebtoken::Header::new(Algorithm::RS256),
84 &claims,
85 &encoding_key,
86 )
87 .unwrap();
88
89 Ok(AuthenticationTokenResponse { token })
90 }
91
92 pub async fn extension_request(
93 &mut self,
94 raw_request: InstanceAuthenticated<TokenExtensionRequest>,
95 ) -> Result<TokenExtensionResponse, Box<dyn Error + Send>> {
96 let request = raw_request.inner().await;
97
98 // let server_public_key = {
99 // let mut file = File::open(self.config["keys"]["public"].as_str().unwrap())
100 // .await
101 // .unwrap();
102
103 // let mut key = String::default();
104 // file.read_to_string(&mut key).await.unwrap();
105
106 // key
107 // };
108
109 let server_public_key = public_key(&Instance {
110 url: String::from("giterated.dev"),
111 })
112 .await
113 .unwrap();
114
115 println!("Our Public Key:\n{}", server_public_key);
116
117 let verification_key = DecodingKey::from_rsa_pem(server_public_key.as_bytes()).unwrap();
118
119 let data: TokenData<UserTokenMetadata> = decode(
120 &request.token,
121 &verification_key,
122 &Validation::new(Algorithm::RS256),
123 )
124 .unwrap();
125
126 info!("Token Extension Request Token validated");
127
128 let secret_key = self.config["authentication"]["secret_key"]
129 .as_str()
130 .unwrap();
131
132 if request.secret_key != secret_key {
133 error!("Incorrect secret key!");
134
135 panic!()
136 }
137 // Validate request
138 raw_request
139 .validate(&data.claims.generated_for)
140 .await
141 .unwrap();
142 info!("Validated request for key extension");
143
144 let private_key = {
145 let mut file = File::open(self.config["keys"]["private"].as_str().unwrap())
146 .await
147 .unwrap();
148
149 let mut key = vec![];
150 file.read_to_end(&mut key).await.unwrap();
151
152 key
153 };
154
155 let encoding_key = EncodingKey::from_rsa_pem(&private_key).unwrap();
156
157 let claims = UserTokenMetadata {
158 // TODO: Probably exploitable
159 user: data.claims.user,
160 generated_for: data.claims.generated_for,
161 exp: (SystemTime::UNIX_EPOCH.elapsed().unwrap()
162 + std::time::Duration::from_secs(24 * 60 * 60))
163 .as_secs(),
164 };
165
166 let token = encode(
167 &jsonwebtoken::Header::new(Algorithm::RS256),
168 &claims,
169 &encoding_key,
170 )
171 .unwrap();
172
173 Ok(TokenExtensionResponse {
174 new_token: Some(token),
175 })
176 }
177 }
178
179 async fn public_key(instance: &Instance) -> Result<String, Box<dyn Error>> {
180 let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url))
181 .await?
182 .text()
183 .await?;
184
185 Ok(key)
186 }
187