Skip to content
A rust implementation of Json Web Tokens
Rust
Branch: master
Clone or download
rib Enable matching feature by default
(also fixes build issue with matching enabled)
Latest commit db53927 Jan 18, 2020
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
tests
.travis.yml Adds a Travis CI config Dec 21, 2019
Cargo.toml
LICENSE Inital implementation Nov 29, 2019
README.md

README.md

jsonwebtokens License: MIT Build Status

A Rust implementation of Json Web Tokens

Installation

jsonwebtokens = "1"
serde_json = "1"

Then, in your code:

use serde_json::json;
use serde_json::value::Value;

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

Usage

The main two types are Algorithm and Verifier. An Algorithm encapsulates a cryptographic function for signing or verifying tokens, and a Verifier handles checking the signature and claims of a token, given an Algorithm.

Creating an Algorithm separately ensures any parsing of secrets or keys only needs to happen once.

The builder pattern used for describing a Verifier keeps code ergonimic no matter if you have simple or elaborate verification requirements.

There is also a low-level (::raw) API available in case you need more control over splitting, decoding, deserializing and verifying tokens.

Signing a token

with a symmetric secret:

let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret")?;
let header = json!({ "alg": alg.name() });
let claims = json!({ "foo": "bar" });
let token = encode(&header, &claims, &alg)?;

or if your secret is base64 encoded:

let alg = Algorithm::new_hmac_b64(AlgorithmID::HS256, secret_data)?;

with an RSA private key:

let alg = Algorithm::new_rsa_pem_signer(AlgorithmID::RS256, pem_data)?;
let header = json!({ "alg": alg.name() });
let claims = json!({ "foo": "bar" });
let token = encode(&header, &claims, &alg)?;

Verifying tokens

with a symmetric secret:

let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret")?;
let verifier = Verifier::create()
    .issuer("http://some-auth-service.com")
    .audience("application_id")
    .build()?;
let claims: Value = verifier.verify(&token_str, &alg)?;

with an RSA private key:

let alg = Algorithm::new_rsa_pem_verifier(AlgorithmID::RS256, pem_data)?;
let verifier = Verifier::create()
    .issuer("http://some-auth-service.com")
    .audience("application_id")
    .build()?;
let claims: Value = verifier.verify(&token_str, &alg)?;

Verifying standard claims

let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret")?;
let verifier = Verifier::create()
    .issuer("http://some-auth-service.com")
    .audience("application_id")
    .subject("subject")
    .nonce("9837459873945093845")
    .leeway(5) // give this much leeway (in seconds) when validating exp, nbf and iat claims
    .build()?;
let claims: Value = verifier.verify(&token_str, &alg)?;

Verifying custom claims

let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret")?;
let verifier = Verifier::create()
    .string_equals("my_claim0", "value")
    .string_matches("my_claim1", "value[0-9]")
    .string_equals_one_of("my_claim2", &["value0", "value1"])
    .string_matches_one_of("my_claim3", &[regex0, regex1])
    .claim_callback("my_claim4", |v| v.is_u64() && v.as_u64().unwrap() == 1234)
    .build()?;
let claims: Value = verifier.verify(&token_str, &alg)?;

Verifying timestamps (or not)

let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret")?;
let verifier = Verifier::create()
    .leeway(5)    // give this much leeway when validating exp, nbf and iat claims
    .ignore_exp() // ignore expiry
    .ignore_nbf() // ignore 'not before time'
    .ignore_iat() // ignore issue time
    .build()?;
let claims: Value = verifier.verify(&token_str, &alg)?;

Low-level Usage

In case you need even more fine-grained control than is possible with the above APIs, many of the lower-level details are exposed through the ::raw module to allow you to manually split, decode and verify a JWT token.

Just split a token into component parts

let TokenSlices {message, signature, header, claims } = raw::split_token(token)?;

Just parse the header

use serde_json::value::Value;
let header: Value = raw::decode_header_only(token);

Base64 decode header or claims and deserialize JSON

Equivalent to raw::decode_header_only():

let TokenSlices {header, .. } = raw::split_token(token)?;
let header = raw::decode_json_token_slice(header)?;

Or, decode and deserialize just the claims:

let TokenSlices {claims, .. } = raw::split_token(token)?;
let claims = raw::decode_json_token_slice(claims)?;

Manually split, decode and verify a token

let alg = Algorithm::new_hmac(AlgorithmID::HS256, "secret")?;
let verifier = Verifier::create()
    // snip
    .build()?;

let TokenSlices {message, signature, header, claims } = raw::split_token(token)?;
let header = raw::decode_json_token_slice(header)?;
raw::verify_signature_only(&header, message, signature, &alg)?;
let claims = raw::decode_json_token_slice(claims)?;
verifier.verify_claims_only(&claims, time_now)?;

Algorithms Supported

Array of supported algorithms. The following algorithms are currently supported.

alg Parameter Value Digital Signature or MAC Algorithm
HS256 HMAC using SHA-256 hash algorithm
HS384 HMAC using SHA-384 hash algorithm
HS512 HMAC using SHA-512 hash algorithm
RS256 RSASSA-PKCS1-v1_5 using SHA-256 hash algorithm
RS384 RSASSA-PKCS1-v1_5 using SHA-384 hash algorithm
RS512 RSASSA-PKCS1-v1_5 using SHA-512 hash algorithm
PS256 RSASSA-PSS using SHA-256 hash algorithm
PS384 RSASSA-PSS using SHA-384 hash algorithm
PS512 RSASSA-PSS using SHA-512 hash algorithm
ES256 ECDSA using P-256 curve and SHA-256 hash algorithm (only PKCS#8 format PEM)
ES384 ECDSA using P-384 curve and SHA-384 hash algorithm (only PKCS#8 format PEM)
none No digital signature or MAC value included

Based on

Originally this project started as a few small changes to jsonwebtoken (without an 's'), to meet the needs I had while building jsonwebtokens-cognito but eventually the design and implementation became substantially different with the creation of the Algorithm API and the customizable Verifier API.

The project borrows design ideas from a variety of pre-existing Json Web Token libraries. In particular it shamelessly steals ideas from node-jsonwebtoken and java-jwt.

You can’t perform that action at this time.