Skip to content

Commit a470ed0

Browse files
authored
JWK hmac keys are base64url encoded not standard (#316)
* JWK hmac keys are base64url encoded not standard DecodingKey::from_base64_secret uses standard decoding, while "k" field of a jwk is expected to be in base64url instead. Signed-off-by: Sjoerd Simons <sjoerd@collabora.com> * Test validating HMAC SHA-256 example from RFC7517 Use the example form RFC7517 Appendix A.1 to validate correct handling of JWK's containing hmac keys for decoding Signed-off-by: Sjoerd Simons <sjoerd@collabora.com> --------- Signed-off-by: Sjoerd Simons <sjoerd@collabora.com>
1 parent cfd1f1c commit a470ed0

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

src/decoding.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,13 @@ impl DecodingKey {
183183
DecodingKey::from_ec_components(&params.x, &params.y)
184184
}
185185
AlgorithmParameters::OctetKeyPair(params) => DecodingKey::from_ed_components(&params.x),
186-
AlgorithmParameters::OctetKey(params) => DecodingKey::from_base64_secret(&params.value),
186+
AlgorithmParameters::OctetKey(params) => {
187+
let out = b64_decode(&params.value)?;
188+
Ok(DecodingKey {
189+
family: AlgorithmFamily::Hmac,
190+
kind: DecodingKeyKind::SecretOrDer(out),
191+
})
192+
}
187193
}
188194
}
189195

tests/hmac.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use jsonwebtoken::errors::ErrorKind;
2+
use jsonwebtoken::jwk::Jwk;
23
use jsonwebtoken::{
34
crypto::{sign, verify},
45
decode, decode_header, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation,
@@ -183,3 +184,22 @@ fn dangerous_insecure_decode_token_with_validation_wrong_algorithm() {
183184
let err = claims.unwrap_err();
184185
assert_eq!(err.kind(), &ErrorKind::ExpiredSignature);
185186
}
187+
188+
#[test]
189+
fn verify_hs256_rfc7517_appendix_a1() {
190+
#[derive(Debug, PartialEq, Eq, Clone, Deserialize)]
191+
struct C {
192+
iss: String,
193+
}
194+
let token = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
195+
let jwk = r#"{"kty":"oct",
196+
"k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow"
197+
}"#;
198+
let jwk: Jwk = serde_json::from_str(jwk).unwrap();
199+
let key = DecodingKey::from_jwk(&jwk).unwrap();
200+
let mut validation = Validation::new(Algorithm::HS256);
201+
// The RFC example signed jwt has expired
202+
validation.validate_exp = false;
203+
let c = decode::<C>(token, &key, &validation).unwrap();
204+
assert_eq!(c.claims.iss, "joe");
205+
}

0 commit comments

Comments
 (0)