jsonwebtokens 1.2.0

A Json Web Token implementation for Rust
Documentation
use serde_json::json;

use jsonwebtokens as jwt;
use jwt::{error::Error, Algorithm, AlgorithmID, Verifier};

mod common;

const REFERENCE_TIME: u64 = 1575057015u64;

#[test]
fn token_just_expired() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "exp": REFERENCE_TIME });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    // "requires that the current date/time MUST be before the expiration
    //  date/time listed in the "exp" claim."
    // So being equal should be considered expired...
    let verifier = Verifier::create().build().unwrap();
    let result = verifier.verify_for_time(token_str, &alg, REFERENCE_TIME);
    match result {
        Err(Error::TokenExpiredAt(at)) => {
            assert_eq!(at, REFERENCE_TIME);
        }
        _ => unreachable!("Token not expired"),
    }
}

#[test]
fn token_expired() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "exp": REFERENCE_TIME });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().build().unwrap();
    let result = verifier.verify_for_time(token_str, &alg, REFERENCE_TIME + 100);
    match result {
        Err(Error::TokenExpiredAt(at)) => {
            assert_eq!(at, REFERENCE_TIME);
        }
        _ => unreachable!("Token not expired"),
    }
}

#[test]
fn ignore_token_expired() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "exp": REFERENCE_TIME });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().ignore_exp().build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME + 100)
        .unwrap();
}

#[test]
fn token_recently_expired_with_leeway() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "exp": REFERENCE_TIME });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().leeway(5).build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME + 1)
        .unwrap();
}

#[test]
fn token_used_exactly_at_nbf_time() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "nbf": REFERENCE_TIME });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    // "The "nbf" (not before) claim identifies the time before which the JWT
    //  MUST NOT be accepted for processing.  The processing of the "nbf"
    //  claim requires that the current date/time MUST be after or equal to
    //  the not-before date/time listed in the "nbf" claim."
    //
    let verifier = Verifier::create().build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME)
        .unwrap();
}

#[test]
#[should_panic(expected = "MalformedToken")]
fn token_used_early() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "nbf": REFERENCE_TIME + 100 });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    // "The "nbf" (not before) claim identifies the time before which the JWT
    //  MUST NOT be accepted for processing.  The processing of the "nbf"
    //  claim requires that the current date/time MUST be after or equal to
    //  the not-before date/time listed in the "nbf" claim."
    //
    let verifier = Verifier::create().build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME)
        .unwrap();
}

#[test]
fn ignore_token_used_early() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "nbf": REFERENCE_TIME + 100 });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().ignore_nbf().build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME)
        .unwrap();
}

#[test]
fn token_used_slightly_early_with_leeway() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "nbf": REFERENCE_TIME + 1 });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().leeway(5).build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME)
        .unwrap();
}

#[test]
#[should_panic(expected = "MalformedToken")]
fn token_used_before_issue() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "iat": REFERENCE_TIME + 100 });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME)
        .unwrap();
}

#[test]
fn token_used_before_just_before_issue_with_leeway() {
    let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret").unwrap();
    let header = json!({ "alg": "HS256" });
    let claims = json!({ "iat": REFERENCE_TIME + 1 });
    let token_str = jwt::encode(&header, &claims, &alg).unwrap();

    let verifier = Verifier::create().leeway(5).build().unwrap();
    let _token_data = verifier
        .verify_for_time(token_str, &alg, REFERENCE_TIME)
        .unwrap();
}