Merge pull request #42 from Keats/next
Make it mandatory to specify algorithm
This commit is contained in:
commit
7a71501798
|
@ -15,6 +15,6 @@ serde_json = "1.0"
|
|||
serde_derive = "1.0"
|
||||
serde = "1.0"
|
||||
ring = { version = "0.12.0", features = ["rsa_signing", "dev_urandom_fallback"] }
|
||||
base64 = "0.6"
|
||||
base64 = "0.7"
|
||||
untrusted = "0.5"
|
||||
chrono = "0.4"
|
||||
|
|
|
@ -76,14 +76,15 @@ those require setting the expected value in the `Validation` struct.
|
|||
Since validating time fields is always a bit tricky due to clock skew,
|
||||
you can add some leeway to the `iat`, `exp` and `nbf` validation by setting a `leeway` parameter.
|
||||
|
||||
Last but not least, if you are not using HS256 for the algorithm, you will need to update the `algorithms` field of the `Validation` struct
|
||||
to the one you are using.
|
||||
Last but not least, you will need to set the algorithm(s) allowed for this token if you are not using `HS256`.
|
||||
|
||||
```rust
|
||||
use jsonwebtoken::{Validation, Algorithm};
|
||||
|
||||
// Default valuation
|
||||
// Default validation: the only algo allowed is HS256
|
||||
let validation = Validation::default();
|
||||
// Quick way to setup a validation where only the algorithm changes
|
||||
let validation = Validation::new(Algorithm::HS512);
|
||||
// Adding some leeway (in seconds) for iat, exp and nbf checks
|
||||
let mut validation = Validation {leeway: 60, ..Default::default()};
|
||||
// Checking issuer
|
||||
|
@ -92,8 +93,6 @@ let mut validation = Validation {iss: Some("issuer".to_string()), ..Default::def
|
|||
let mut validation = Validation::default();
|
||||
validation.set_audience(&"Me"); // string
|
||||
validation.set_audience(&["Me", "You"]); // array of strings
|
||||
// Will error if the token given has an algorithm that isn't HS256
|
||||
let mut validation = Validation {algorithms: Some(vec![Algorithm::HS256]), ..Default::default()};
|
||||
```
|
||||
|
||||
## Algorithms
|
||||
|
|
|
@ -29,7 +29,7 @@ fn main() {
|
|||
};
|
||||
println!("{:?}", token);
|
||||
|
||||
let token_data = match decode::<Claims>(&token, key.as_ref(), &Validation::default()) {
|
||||
let token_data = match decode::<Claims>(&token, key.as_ref(), &Validation::new(Algorithm::HS512)) {
|
||||
Ok(c) => c,
|
||||
Err(err) => match *err.kind() {
|
||||
ErrorKind::InvalidToken => panic!(), // Example on how to handle a specific error
|
||||
|
|
|
@ -23,7 +23,10 @@ fn main() {
|
|||
Err(_) => panic!() // in practice you would return the error
|
||||
};
|
||||
|
||||
let validation = Validation {sub: Some("b@b.com".to_string()), ..Validation::default()};
|
||||
let validation = Validation {
|
||||
sub: Some("b@b.com".to_string()),
|
||||
..Validation::default()
|
||||
};
|
||||
|
||||
let token_data = match decode::<Claims>(&token, key.as_ref(), &validation) {
|
||||
Ok(c) => c,
|
||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -90,7 +90,7 @@ macro_rules! expect_two {
|
|||
/// ```rust,ignore
|
||||
/// #[macro_use]
|
||||
/// extern crate serde_derive;
|
||||
/// use jsonwebtoken::{decode, Validation};
|
||||
/// use jsonwebtoken::{decode, Validation, Algorithm};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize)]
|
||||
/// struct Claims {
|
||||
|
@ -100,7 +100,7 @@ macro_rules! expect_two {
|
|||
///
|
||||
/// let token = "a.jwt.token".to_string();
|
||||
/// // Claims is a struct that implements Deserialize
|
||||
/// let token_data = decode::<Claims>(&token, "secret", &Validation::default());
|
||||
/// let token_data = decode::<Claims>(&token, "secret", &Validation::new(Algorithm::HS256));
|
||||
/// ```
|
||||
pub fn decode<T: DeserializeOwned>(token: &str, key: &[u8], validation: &Validation) -> Result<TokenData<T>> {
|
||||
let (signature, signing_input) = expect_two!(token.rsplitn(2, '.'));
|
||||
|
@ -111,10 +111,8 @@ pub fn decode<T: DeserializeOwned>(token: &str, key: &[u8], validation: &Validat
|
|||
return Err(ErrorKind::InvalidSignature.into());
|
||||
}
|
||||
|
||||
if let Some(ref allowed_algs) = validation.algorithms {
|
||||
if !allowed_algs.contains(&header.alg) {
|
||||
return Err(ErrorKind::InvalidAlgorithm.into());
|
||||
}
|
||||
if !validation.algorithms.contains(&header.alg) {
|
||||
return Err(ErrorKind::InvalidAlgorithm.into());
|
||||
}
|
||||
|
||||
let (decoded_claims, claims_map): (T, _) = from_jwt_part_claims(claims)?;
|
||||
|
|
|
@ -67,14 +67,21 @@ pub struct Validation {
|
|||
///
|
||||
/// Defaults to `None`.
|
||||
pub sub: Option<String>,
|
||||
/// If it contains a value, the validation will check that the `alg` of the header is container
|
||||
/// If it contains a value, the validation will check that the `alg` of the header is contained
|
||||
/// in the ones provided and will error otherwise.
|
||||
///
|
||||
/// Defaults to `None`.
|
||||
pub algorithms: Option<Vec<Algorithm>>,
|
||||
/// Defaults to `vec![Algorithm::HS256]`.
|
||||
pub algorithms: Vec<Algorithm>,
|
||||
}
|
||||
|
||||
impl Validation {
|
||||
/// Create a default validation setup allowing the given alg
|
||||
pub fn new(alg: Algorithm) -> Validation {
|
||||
let mut validation = Validation::default();
|
||||
validation.algorithms = vec![alg];
|
||||
validation
|
||||
}
|
||||
|
||||
/// Since `aud` can be either a String or an array of String in the JWT spec, this method will take
|
||||
/// care of serializing the value.
|
||||
pub fn set_audience<T: Serialize>(&mut self, audience: &T) {
|
||||
|
@ -95,7 +102,7 @@ impl Default for Validation {
|
|||
sub: None,
|
||||
aud: None,
|
||||
|
||||
algorithms: None,
|
||||
algorithms: vec![Algorithm::HS256],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ fn decode_token_invalid_signature() {
|
|||
#[should_panic(expected = "InvalidAlgorithm")]
|
||||
fn decode_token_wrong_algorithm() {
|
||||
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiQGIuY29tIiwiY29tcGFueSI6IkFDTUUifQ.I1BvFoHe94AFf09O6tDbcSB8-jp8w6xZqmyHIwPeSdY";
|
||||
let claims = decode::<Claims>(token, "secret".as_ref(), &Validation {algorithms: Some(vec![Algorithm::RS512]), ..Validation::default()});
|
||||
let claims = decode::<Claims>(token, "secret".as_ref(), &Validation::new(Algorithm::RS512));
|
||||
claims.unwrap();
|
||||
}
|
||||
|
||||
|
@ -102,5 +102,4 @@ fn decode_header_only() {
|
|||
let header = decode_header(token).unwrap();
|
||||
assert_eq!(header.alg, Algorithm::HS256);
|
||||
assert_eq!(header.typ, Some("JWT".to_string()));
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ fn round_trip_claim() {
|
|||
company: "ACME".to_string()
|
||||
};
|
||||
let token = encode(&Header::new(Algorithm::RS256), &my_claims, include_bytes!("private_rsa_key.der")).unwrap();
|
||||
let token_data = decode::<Claims>(&token, include_bytes!("public_rsa_key.der"), &Validation::default()).unwrap();
|
||||
let token_data = decode::<Claims>(&token, include_bytes!("public_rsa_key.der"), &Validation::new(Algorithm::RS256)).unwrap();
|
||||
assert_eq!(my_claims, token_data.claims);
|
||||
assert!(token_data.header.kid.is_none());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue