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 |
|
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 |
|