Skip to content

Commit 1117320

Browse files
authored
Merge pull request #193 from Julien-cpsn/amkarkhi/main
Add JWT token auth by Amkarkhi
2 parents b4d5ec2 + 9e21a95 commit 1117320

File tree

39 files changed

+1643
-267
lines changed

39 files changed

+1643
-267
lines changed

Cargo.lock

Lines changed: 406 additions & 72 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ toml = "=0.9.10"
6868
## Create Javascript runtimes. Used for pre and post request scripts
6969
boa_engine = { version = "=0.21.0", default-features = false }
7070
## Deserialize Postman collection files
71-
parse_postman_collection = "=0.2.3"
71+
parse_postman_collection = "=0.2.4"
7272
## Parse cURL request files
7373
curl-parser = { version = "=0.6.0", default-features = false }
7474
## Parse OpenAPI spec files
@@ -79,6 +79,8 @@ clap = { version = "=4.5.53", features = ["derive", "color", "suggestions"] }
7979
directories = "=6.0.0"
8080
## Copy response body to clipboard
8181
arboard = { version = "=3.6.1", features = ["wayland-data-control"], optional = true }
82+
## Create and decode JSON Web Tokens (JWT)
83+
jsonwebtoken = { version = "10.2.0", features = ["rust_crypto"] }
8284

8385
# Async
8486
## Handle asynchronous requests

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ cargo run -- -h
178178
| Authentication | Partial | :white_check_mark: | :white_check_mark: |
179179
| - Basic auth | :white_check_mark: | :white_check_mark: | :white_check_mark: |
180180
| - Bearer token | :white_check_mark: | :white_check_mark: | :white_check_mark: |
181-
| - JWT, Digest, OAuth1-2, AWS | :x: :soon: | :white_check_mark: | :white_check_mark: |
181+
| - JWT | :white_check_mark: | :white_check_mark: | :white_check_mark: |
182+
| - Digest, OAuth1-2, AWS | :x: :soon: | :white_check_mark: | :white_check_mark: |
182183
| Headers | :white_check_mark: | :white_check_mark: | :white_check_mark: |
183184
| Body | :white_check_mark: | :white_check_mark: | :white_check_mark: |
184185
| - Multipart form | :white_check_mark: | :white_check_mark: | :white_check_mark: |
@@ -329,6 +330,7 @@ You can read more about it here: https://github.com/Julien-cpsn/ATAC/releases/ta
329330
| [clap](https://github.com/clap-rs/clap) | 4.5 | Command Line Argument Parser |
330331
| [directories](https://github.com/soc/directories-rs) | 6.0.0 | Use system files |
331332
| [arboard](https://github.com/1Password/arboard) | 3.6.1 | Copy response body to clipboard |
333+
| [jsonwebtoken](https://github.com/Keats/jsonwebtoken) | 10.2.0 | Encode JSON Web Tokens (JWT) |
332334
| **Async** | | |
333335
| [tokio](https://github.com/tokio-rs/tokio) | 1.47.1 | Handle asynchronous requests |
334336
| [parking_lot](https://github.com/Amanieu/parking_lot) | 0.12.4 | Smaller, faster and more flexible implementation of RwLock and Mutex. Used everywhere. |
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
BASE_URL=https://httpbin.org
2+
FILE_NAME=Cargo.toml
23
ID=15
3-
FILE_NAME=Cargo.toml
4+
IS_ADMIN=true

example_resources/collections/auth.json

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,142 @@
132132
"method": "GET",
133133
"body": "no_body"
134134
}
135+
},
136+
{
137+
"name": "Test JWT auth HS256",
138+
"url": "https://httpbin.org/bearer",
139+
"params": [],
140+
"headers": [
141+
{
142+
"enabled": true,
143+
"data": [
144+
"cache-control",
145+
"no-cache"
146+
]
147+
},
148+
{
149+
"enabled": true,
150+
"data": [
151+
"user-agent",
152+
"ATAC/v0.22.0"
153+
]
154+
},
155+
{
156+
"enabled": true,
157+
"data": [
158+
"accept",
159+
"*/*"
160+
]
161+
},
162+
{
163+
"enabled": true,
164+
"data": [
165+
"accept-encoding",
166+
"gzip, deflate, br"
167+
]
168+
},
169+
{
170+
"enabled": true,
171+
"data": [
172+
"connection",
173+
"keep-alive"
174+
]
175+
}
176+
],
177+
"auth": {
178+
"jwt_token": {
179+
"algorithm": "HS256",
180+
"secret_type": "Text",
181+
"secret": "1234",
182+
"payload": "{\n \"aud\": \"test2\"\n}"
183+
}
184+
},
185+
"scripts": {
186+
"pre_request_script": null,
187+
"post_request_script": null
188+
},
189+
"settings": {
190+
"use_config_proxy": true,
191+
"allow_redirects": true,
192+
"timeout": 30000,
193+
"store_received_cookies": true,
194+
"pretty_print_response_content": true,
195+
"accept_invalid_certs": false,
196+
"accept_invalid_hostnames": false
197+
},
198+
"protocol": {
199+
"type": "http",
200+
"method": "GET",
201+
"body": "no_body"
202+
}
203+
},
204+
{
205+
"name": "Test JWT auth ES256",
206+
"url": "https://httpbin.org/bearer",
207+
"params": [],
208+
"headers": [
209+
{
210+
"enabled": true,
211+
"data": [
212+
"cache-control",
213+
"no-cache"
214+
]
215+
},
216+
{
217+
"enabled": true,
218+
"data": [
219+
"user-agent",
220+
"ATAC/v0.22.0"
221+
]
222+
},
223+
{
224+
"enabled": true,
225+
"data": [
226+
"accept",
227+
"*/*"
228+
]
229+
},
230+
{
231+
"enabled": true,
232+
"data": [
233+
"accept-encoding",
234+
"gzip, deflate, br"
235+
]
236+
},
237+
{
238+
"enabled": true,
239+
"data": [
240+
"connection",
241+
"keep-alive"
242+
]
243+
}
244+
],
245+
"auth": {
246+
"jwt_token": {
247+
"algorithm": "ES256",
248+
"secret_type": "Pem",
249+
"secret": "example_resources/collections/es256_key.pem",
250+
"payload": "{\n \"sub\": \"1234567890\",\n \"name\": \"John Doe\",\n \"admin\": {{IS_ADMIN}},\n \"iat\": 1766848989,\n \"exp\": 1766852589\n}"
251+
}
252+
},
253+
"scripts": {
254+
"pre_request_script": null,
255+
"post_request_script": null
256+
},
257+
"settings": {
258+
"use_config_proxy": true,
259+
"allow_redirects": true,
260+
"timeout": 30000,
261+
"store_received_cookies": true,
262+
"pretty_print_response_content": true,
263+
"accept_invalid_certs": false,
264+
"accept_invalid_hostnames": false
265+
},
266+
"protocol": {
267+
"type": "http",
268+
"method": "GET",
269+
"body": "no_body"
270+
}
135271
}
136272
]
137273
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQglBnO+qn+RecAQ31T
3+
jBklNu+AwiFN5eVHBFbnjecmMryhRANCAARGpVef6j7rMQ6lYSwbDkKwH7B3zM6P
4+
G7S4BIamIY/7Bh9xzW6fIzFxK1sPNSNG45tjwNqVoIn38npSuRCRkG1n
5+
-----END PRIVATE KEY-----

rustfmt.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Try using your hands!
2+
disable_all_formatting = true

src/app/app.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ pub struct App<'a> {
9494
pub auth_basic_username_text_input: TextInput,
9595
pub auth_basic_password_text_input: TextInput,
9696
pub auth_bearer_token_text_input: TextInput,
97+
pub auth_jwt_secret_text_input: TextInput,
98+
pub auth_jwt_payload_text_area: TextArea<'a>,
99+
pub auth_jwt_payload_text_area_vim_emulation: Vim,
97100

98101
pub headers_table: StatefulCustomTable,
99102

@@ -192,6 +195,9 @@ impl App<'_> {
192195
auth_basic_username_text_input: TextInput::default(),
193196
auth_basic_password_text_input: TextInput::default(),
194197
auth_bearer_token_text_input: TextInput::default(),
198+
auth_jwt_secret_text_input: TextInput::default(),
199+
auth_jwt_payload_text_area: TextArea::default(),
200+
auth_jwt_payload_text_area_vim_emulation: Vim::default(),
195201

196202
headers_table: StatefulCustomTable::default(),
197203

src/app/business_logic/request/auth.rs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use tracing::{info};
22
use crate::app::app::App;
3-
use crate::models::auth::Auth;
4-
use crate::models::auth::Auth::{BasicAuth, BearerToken};
3+
use crate::models::auth::auth::Auth;
4+
use crate::models::auth::basic::BasicAuth;
5+
use crate::models::auth::bearer_token::BearerToken;
56

67
impl App<'_> {
78
pub fn modify_request_auth(&mut self, collection_index: usize, request_index: usize, auth: Auth) -> anyhow::Result<()> {
@@ -29,11 +30,11 @@ impl App<'_> {
2930
info!("Auth basic username set to \"{}\"", basic_auth_username);
3031

3132
match &selected_request.auth {
32-
BasicAuth { password, .. } => {
33-
selected_request.auth = BasicAuth {
33+
Auth::BasicAuth(BasicAuth { password, .. }) => {
34+
selected_request.auth = Auth::BasicAuth(BasicAuth {
3435
username: basic_auth_username,
3536
password: password.to_string()
36-
};
37+
});
3738
}
3839
_ => {}
3940
}
@@ -51,11 +52,11 @@ impl App<'_> {
5152
info!("Auth basic password set to \"{}\"", basic_auth_password);
5253

5354
match &selected_request.auth {
54-
BasicAuth { username, .. } => {
55-
selected_request.auth = BasicAuth {
55+
Auth::BasicAuth(BasicAuth { username, .. }) => {
56+
selected_request.auth = Auth::BasicAuth(BasicAuth {
5657
username: username.to_string(),
5758
password: basic_auth_password
58-
};
59+
});
5960
}
6061
_ => {}
6162
}
@@ -73,13 +74,44 @@ impl App<'_> {
7374
info!("Auth bearer token set to \"{}\"", bearer_token);
7475

7576
match &selected_request.auth {
76-
BearerToken { .. } => {
77-
selected_request.auth = BearerToken { token: bearer_token };
77+
Auth::BearerToken(BearerToken { .. }) => {
78+
selected_request.auth = Auth::BearerToken(BearerToken { token: bearer_token });
7879
}
7980
_ => {}
8081
}
8182
}
8283

8384
self.save_collection_to_file(collection_index);
8485
}
85-
}
86+
87+
pub fn modify_request_auth_secret(&mut self, collection_index: usize, request_index: usize, secret: String) {
88+
let local_selected_request = self.get_request_as_local_from_indexes(&(collection_index, request_index));
89+
90+
{
91+
let mut selected_request = local_selected_request.write();
92+
let jwt_token = selected_request.auth.get_jwt_mut();
93+
94+
info!("Auth JWT secret set to \"{}\"", secret);
95+
96+
jwt_token.secret = secret.to_string();
97+
}
98+
99+
self.save_collection_to_file(collection_index);
100+
}
101+
102+
pub fn modify_request_auth_payload(&mut self, collection_index: usize, request_index: usize, payload: String) {
103+
let local_selected_request = self.get_request_as_local_from_indexes(&(collection_index, request_index));
104+
105+
{
106+
let mut selected_request = local_selected_request.write();
107+
let jwt_token = selected_request.auth.get_jwt_mut();
108+
109+
info!("Auth JWT payload set to \"{}\"", payload);
110+
111+
jwt_token.payload = payload;
112+
}
113+
114+
self.save_collection_to_file(collection_index);
115+
}
116+
117+
}

0 commit comments

Comments
 (0)