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

ambee/giterated

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

Add token extension

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨86d028f

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