Skip to content

Commit 98b2d38

Browse files
committed
remove base64 dependency
1 parent bd5fbc4 commit 98b2d38

File tree

7 files changed

+69
-66
lines changed

7 files changed

+69
-66
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ tui-textarea = { version = "0.4.0", default-features = false, features = [
4545
] }
4646
backtrace = "0.3"
4747
human-panic = "1.1"
48-
base64 = "0.21"
4948
jsonwebtoken = "9.2.0"
5049
chrono = "0.4"
5150

src/app/jwt_decoder.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use serde_derive::{Deserialize, Serialize};
88
use serde_json::{to_string_pretty, Value};
99

1010
use super::{
11-
jwt_utils::{decoding_key_from_jwks_secret, get_secret, JWTError, JWTResult, SecretFileType},
11+
jwt_utils::{decoding_key_from_jwks_secret, get_secret, JWTError, JWTResult, SecretType},
1212
models::{ScrollableTxt, TabRoute, TabsState},
1313
ActiveBlock, App, Route, RouteId, TextInput,
1414
};
@@ -227,6 +227,7 @@ fn decode_token(
227227
let mut secret_validator = Validation::new(algorithm);
228228

229229
secret_validator.leeway = 1000;
230+
secret_validator.validate_aud = false;
230231

231232
if arguments.ignore_exp {
232233
secret_validator
@@ -255,31 +256,41 @@ fn decoding_key_from_secret(
255256
let (secret, file_type) = get_secret(alg, secret_string);
256257
let secret = secret?;
257258
match alg {
258-
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => Ok(DecodingKey::from_secret(&secret)),
259+
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => match file_type {
260+
SecretType::Plain => Ok(DecodingKey::from_secret(&secret)),
261+
SecretType::Jwks => decoding_key_from_jwks_secret(&secret, header),
262+
SecretType::B64 => {
263+
DecodingKey::from_base64_secret(std::str::from_utf8(&secret)?).map_err(Error::into)
264+
}
265+
_ => Err(JWTError::Internal(format!(
266+
"Invalid secret file type for {alg:?}"
267+
))),
268+
},
259269
Algorithm::RS256
260270
| Algorithm::RS384
261271
| Algorithm::RS512
262272
| Algorithm::PS256
263273
| Algorithm::PS384
264274
| Algorithm::PS512 => match file_type {
265-
SecretFileType::Pem => DecodingKey::from_rsa_pem(&secret).map_err(Error::into),
266-
SecretFileType::Der => Ok(DecodingKey::from_rsa_der(&secret)),
267-
SecretFileType::Jwks => decoding_key_from_jwks_secret(&secret, header),
275+
SecretType::Pem => DecodingKey::from_rsa_pem(&secret).map_err(Error::into),
276+
SecretType::Der => Ok(DecodingKey::from_rsa_der(&secret)),
277+
SecretType::Jwks => decoding_key_from_jwks_secret(&secret, header),
268278
_ => Err(JWTError::Internal(format!(
269279
"Invalid secret file type for {alg:?}"
270280
))),
271281
},
272282
Algorithm::ES256 | Algorithm::ES384 => match file_type {
273-
SecretFileType::Pem => DecodingKey::from_ec_pem(&secret).map_err(Error::into),
274-
SecretFileType::Der => Ok(DecodingKey::from_ec_der(&secret)),
275-
SecretFileType::Jwks => decoding_key_from_jwks_secret(&secret, header),
283+
SecretType::Pem => DecodingKey::from_ec_pem(&secret).map_err(Error::into),
284+
SecretType::Der => Ok(DecodingKey::from_ec_der(&secret)),
285+
SecretType::Jwks => decoding_key_from_jwks_secret(&secret, header),
276286
_ => Err(JWTError::Internal(format!(
277287
"Invalid secret file type for {alg:?}"
278288
))),
279289
},
280290
Algorithm::EdDSA => match file_type {
281-
SecretFileType::Pem => DecodingKey::from_ed_pem(&secret).map_err(Error::into),
282-
SecretFileType::Der => Ok(DecodingKey::from_ed_der(&secret)),
291+
SecretType::Pem => DecodingKey::from_ed_pem(&secret).map_err(Error::into),
292+
SecretType::Der => Ok(DecodingKey::from_ed_der(&secret)),
293+
SecretType::Jwks => decoding_key_from_jwks_secret(&secret, header),
283294
_ => Err(JWTError::Internal(format!(
284295
"Invalid secret file type for {alg:?}"
285296
))),

src/app/jwt_encoder.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use jsonwebtoken::{errors::Error, Algorithm, EncodingKey, Header};
22

33
use super::{
44
jwt_decoder::Payload,
5-
jwt_utils::{get_secret, JWTError, JWTResult, SecretFileType},
5+
jwt_utils::{get_secret, JWTError, JWTResult, SecretType},
66
models::{ScrollableTxt, TabRoute, TabsState},
77
ActiveBlock, App, Route, RouteId, TextAreaInput, TextInput,
88
};
@@ -112,29 +112,37 @@ pub fn encoding_key_from_secret(alg: &Algorithm, secret_string: &str) -> JWTResu
112112
let secret = secret?;
113113

114114
match alg {
115-
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => Ok(EncodingKey::from_secret(&secret)),
115+
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => match file_type {
116+
SecretType::Plain => Ok(EncodingKey::from_secret(&secret)),
117+
SecretType::B64 => {
118+
EncodingKey::from_base64_secret(std::str::from_utf8(&secret)?).map_err(Error::into)
119+
}
120+
_ => Err(JWTError::Internal(format!(
121+
"Invalid secret file type for {alg:?}"
122+
))),
123+
},
116124
Algorithm::RS256
117125
| Algorithm::RS384
118126
| Algorithm::RS512
119127
| Algorithm::PS256
120128
| Algorithm::PS384
121129
| Algorithm::PS512 => match file_type {
122-
SecretFileType::Pem => EncodingKey::from_rsa_pem(&secret).map_err(Error::into),
123-
SecretFileType::Der => Ok(EncodingKey::from_rsa_der(&secret)),
130+
SecretType::Pem => EncodingKey::from_rsa_pem(&secret).map_err(Error::into),
131+
SecretType::Der => Ok(EncodingKey::from_rsa_der(&secret)),
124132
_ => Err(JWTError::Internal(format!(
125133
"Invalid secret file type for {alg:?}"
126134
))),
127135
},
128136
Algorithm::ES256 | Algorithm::ES384 => match file_type {
129-
SecretFileType::Pem => EncodingKey::from_ec_pem(&secret).map_err(Error::into),
130-
SecretFileType::Der => Ok(EncodingKey::from_ec_der(&secret)),
137+
SecretType::Pem => EncodingKey::from_ec_pem(&secret).map_err(Error::into),
138+
SecretType::Der => Ok(EncodingKey::from_ec_der(&secret)),
131139
_ => Err(JWTError::Internal(format!(
132140
"Invalid secret file type for {alg:?}"
133141
))),
134142
},
135143
Algorithm::EdDSA => match file_type {
136-
SecretFileType::Pem => EncodingKey::from_ed_pem(&secret).map_err(Error::into),
137-
SecretFileType::Der => Ok(EncodingKey::from_ed_der(&secret)),
144+
SecretType::Pem => EncodingKey::from_ed_pem(&secret).map_err(Error::into),
145+
SecretType::Der => Ok(EncodingKey::from_ed_der(&secret)),
138146
_ => Err(JWTError::Internal(format!(
139147
"Invalid secret file type for {alg:?}"
140148
))),

src/app/jwt_utils.rs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::fmt;
1+
use std::{fmt, str::Utf8Error};
22

3-
use base64::{engine::general_purpose::STANDARD as base64_engine, Engine as _};
43
use jsonwebtoken::{
54
errors::{Error, ErrorKind},
65
jwk, Algorithm, DecodingKey, Header,
@@ -23,14 +22,14 @@ impl From<jsonwebtoken::errors::Error> for JWTError {
2322
}
2423
}
2524

26-
impl From<serde_json::Error> for JWTError {
27-
fn from(value: serde_json::Error) -> Self {
25+
impl From<Utf8Error> for JWTError {
26+
fn from(value: Utf8Error) -> Self {
2827
JWTError::Internal(value.to_string())
2928
}
3029
}
3130

32-
impl From<base64::DecodeError> for JWTError {
33-
fn from(value: base64::DecodeError) -> Self {
31+
impl From<serde_json::Error> for JWTError {
32+
fn from(value: serde_json::Error) -> Self {
3433
JWTError::Internal(value.to_string())
3534
}
3635
}
@@ -56,46 +55,41 @@ impl fmt::Display for JWTError {
5655
}
5756
}
5857

59-
pub enum SecretFileType {
58+
pub enum SecretType {
6059
Pem,
6160
Der,
6261
Jwks,
63-
Na,
62+
B64,
63+
Plain,
6464
}
6565

66-
pub fn get_secret(alg: &Algorithm, secret_string: &str) -> (JWTResult<Vec<u8>>, SecretFileType) {
66+
pub fn get_secret(alg: &Algorithm, secret_string: &str) -> (JWTResult<Vec<u8>>, SecretType) {
6767
return match alg {
6868
Algorithm::HS256 | Algorithm::HS384 | Algorithm::HS512 => {
6969
if secret_string.starts_with('@') {
7070
(
7171
slurp_file(&secret_string.chars().skip(1).collect::<String>()).map_err(JWTError::from),
72-
SecretFileType::Na,
72+
if secret_string.ends_with(".json") {
73+
SecretType::Jwks
74+
} else {
75+
SecretType::Plain
76+
},
7377
)
7478
} else if secret_string.starts_with("b64:") {
7579
(
76-
base64_engine
77-
.decode(secret_string.chars().skip(4).collect::<String>())
78-
.map_err(JWTError::from),
79-
SecretFileType::Na,
80+
Ok(
81+
secret_string
82+
.chars()
83+
.skip(4)
84+
.collect::<String>()
85+
.as_bytes()
86+
.to_owned(),
87+
),
88+
SecretType::B64,
8089
)
8190
} else {
82-
(Ok(secret_string.as_bytes().to_owned()), SecretFileType::Na)
83-
}
84-
}
85-
Algorithm::EdDSA => {
86-
if !&secret_string.starts_with('@') {
87-
return (
88-
Err(JWTError::Internal(format!(
89-
"Secret for {alg:?} must be a file path starting with @",
90-
))),
91-
SecretFileType::Na,
92-
);
91+
(Ok(secret_string.as_bytes().to_owned()), SecretType::Plain)
9392
}
94-
95-
(
96-
slurp_file(&secret_string.chars().skip(1).collect::<String>()).map_err(JWTError::from),
97-
get_secret_file_type(secret_string),
98-
)
9993
}
10094
_ => {
10195
if secret_string.starts_with('@') {
@@ -105,7 +99,7 @@ pub fn get_secret(alg: &Algorithm, secret_string: &str) -> (JWTResult<Vec<u8>>,
10599
)
106100
} else {
107101
// allows to read JWKS from argument (e.g. output of 'curl https://auth.domain.com/jwks.json')
108-
(Ok(secret_string.as_bytes().to_vec()), SecretFileType::Jwks)
102+
(Ok(secret_string.as_bytes().to_vec()), SecretType::Jwks)
109103
}
110104
}
111105
};
@@ -145,15 +139,7 @@ fn decoding_key_from_jwks(jwks: jwk::JwkSet, header: &Header) -> JWTResult<Decod
145139
}
146140
};
147141

148-
match &jwk.algorithm {
149-
jwk::AlgorithmParameters::RSA(rsa) => {
150-
DecodingKey::from_rsa_components(&rsa.n, &rsa.e).map_err(Error::into)
151-
}
152-
jwk::AlgorithmParameters::EllipticCurve(ec) => {
153-
DecodingKey::from_ec_components(&ec.x, &ec.y).map_err(Error::into)
154-
}
155-
_ => Err(JWTError::Internal("Unsupported alg".to_string())),
156-
}
142+
DecodingKey::from_jwk(jwk).map_err(Error::into)
157143
}
158144

159145
fn parse_jwks(secret: &[u8]) -> Option<jwk::JwkSet> {
@@ -163,13 +149,13 @@ fn parse_jwks(secret: &[u8]) -> Option<jwk::JwkSet> {
163149
}
164150
}
165151

166-
fn get_secret_file_type(secret_string: &str) -> SecretFileType {
152+
fn get_secret_file_type(secret_string: &str) -> SecretType {
167153
if secret_string.ends_with(".pem") {
168-
SecretFileType::Pem
154+
SecretType::Pem
169155
} else if secret_string.ends_with(".json") {
170-
SecretFileType::Jwks
156+
SecretType::Jwks
171157
} else {
172-
SecretFileType::Der
158+
SecretType::Der
173159
}
174160
}
175161

src/ui/decoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn draw_secret_block(f: &mut Frame<'_>, app: &App, area: Rect) {
7070
vertical_chunks_with_margin(vec![Constraint::Length(1), Constraint::Min(2)], area, 1);
7171

7272
let mut text = Text::from(
73-
"Prepend 'b64:' for base64 encoded secret. Prepend '@' for file path (.pem, .pk8, .der)",
73+
"Prepend 'b64:' for base64 encoded secret. Prepend '@' for file path (.pem, .pk8, .der, .json)",
7474
);
7575
text.patch_style(style_default(app.light_theme));
7676
let paragraph = Paragraph::new(text).block(Block::default());

src/ui/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn draw_secret_block(f: &mut Frame<'_>, app: &App, area: Rect) {
8282
vertical_chunks_with_margin(vec![Constraint::Length(1), Constraint::Min(2)], area, 1);
8383

8484
let mut text = Text::from(
85-
"Prepend 'b64:' for base64 encoded secret. Prepend '@' for file path (.pem, .pk8, .der)",
85+
"Prepend 'b64:' for base64 encoded secret. Prepend '@' for file path (.pem, .pk8, .der, .json)",
8686
);
8787
text.patch_style(style_default(app.light_theme));
8888
let paragraph = Paragraph::new(text).block(Block::default());

0 commit comments

Comments
 (0)