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