Go to file
Vincent Prouillet dd642bed1d Use GH actions 2019-11-14 20:02:59 +01:00
.github/workflows Use GH actions 2019-11-14 20:02:59 +01:00
benches Update docs 2019-11-14 19:43:43 +01:00
examples Remove Key approach in favour of &[u8] with pem 2019-11-06 22:32:13 +00:00
src Remove pem encoding for now 2019-11-14 19:48:38 +01:00
tests Update docs 2019-11-14 19:43:43 +01:00
.editorconfig Initial commit 2015-10-31 15:37:15 +00:00
.gitignore Make the `TokenData` struct public 2017-07-02 15:49:14 -06:00
.travis.yml Add example + travis 2015-11-02 20:34:11 +00:00
CHANGELOG.md Remove chrono from deps 2019-11-11 19:47:35 +01:00
Cargo.toml Refactor decoding 2019-11-11 20:16:34 +01:00
LICENSE Move benches to a folder + add license 2015-11-02 21:15:45 +00:00
README.md Update docs 2019-11-14 19:43:43 +01:00
rustfmt.toml rustfmt 2018-10-28 19:58:35 +01:00

README.md

jsonwebtoken

Build Status

API documentation on docs.rs

Installation

Add the following to Cargo.toml:

jsonwebtoken = "7"
serde = {version = "1.0", features = ["derive"] }

How to use

Complete examples are available in the examples directory: a basic one and one with a custom header.

In terms of imports and structs:

use serde::{Serialize, Deserialize};
use jsonwebtoken::{encode, decode, Header, Algorithm, Validation};

/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,
    company: String,
    exp: usize,
}

Header

The default algorithm is HS256.

let token = encode(&Header::default(), &my_claims, "secret".as_ref())?;

Custom headers & changing algorithm

All the parameters from the RFC are supported but the default header only has typ and alg set. If you want to set the kid parameter or change the algorithm for example:

let mut header = Header::new(Algorithm::HS512);
header.kid = Some("blabla".to_owned());
let token = encode(&header, &my_claims, "secret".as_ref())?;

Look at examples/custom_header.rs for a full working example.

Encoding

// HS256
let token = encode(&Header::default(), &my_claims, "secret".as_ref())?;
// RSA
let token = encode(&Header::new(Algorithm::RS256), &my_claims, include_str!("privkey.pem"))?;

Encoding a JWT takes 3 parameters:

  • a header: the Header struct
  • some claims: your own struct
  • a key

When using HS256, HS2384 or HS512, the key is always a shared secret like in the example above. When using RSA/EC, the key should always be the content of the private key in the PEM format.

Decoding

let token = decode::<Claims>(&token, "secret".as_ref(), &Validation::default())?;
// token is a struct with 2 fields: `header` and `claims` and `claims` is your own struct.

decode can error for a variety of reasons:

  • the token or its signature is invalid
  • the token had invalid base64
  • validation of at least one reserved claim failed

As with encoding, when using HS256, HS2384 or HS512, the key is always a shared secret like in the example above. When using RSA/EC, the key should always be the content of the public key in the PEM format.

In some cases, for example if you don't know the algorithm used or need to grab the kid, you can decode only the header:

let header = decode_header(&token)?;

This does not perform any signature verification/validations on the token so it could have been tampered with.

You can also decode a token using the public key components of a RSA key in base64 format. The main use-case is for JWK where your public key is a JSON format like so:

{
   "kty":"RSA",
   "e":"AQAB",
   "kid":"6a7a119f-0876-4f7e-8d0f-bf3ea1391dd8",
   "n":"yRE6rHuNR0QbHO3H3Kt2pOKGVhQqGZXInOduQNxXzuKlvQTLUTv4l4sggh5_CYYi_cvI-SXVT9kPWSKXxJXBXd_4LkvcPuUakBoAkfh-eiFVMh2VrUyWyj3MFl0HTVF9KwRXLAcwkREiS3npThHRyIxuy0ZMeZfxVL5arMhw1SRELB8HoGfG_AtH89BIE9jDBHZ9dLelK9a184zAf8LwoPLxvJb3Il5nncqPcSfKDDodMFBIMc4lQzDKL5gvmiXLXB1AGLm8KBjfE8s3L5xqi-yUod-j8MtvIj812dkS4QMiRVN_by2h3ZY8LYVGrqZXZTcgn2ujn8uKjXLZVD5TdQ"
}
let token = decode_rsa_components::<Claims>(&token, jwk["n"], jwk["e"], &Validation::new(Algorithm::RS256))?;
// token is a struct with 2 fields: `header` and `claims` and `claims` is your own struct.

Convertion .der to .pem

You can use openssl for that:

openssl rsa -inform DER -outform PEM -in mykey.der -out mykey.pem

Validation

This library validates automatically the exp claim. nbf is also validated if present. You can also validate the sub, iss and aud but 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 the leeway field.

Last but not least, you will need to set the algorithm(s) allowed for this token if you are not using HS256.

use jsonwebtoken::{Validation, Algorithm};

// 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 exp and nbf checks
let mut validation = Validation {leeway: 60, ..Default::default()};
// Checking issuer
let mut validation = Validation {iss: Some("issuer".to_string()), ..Default::default()};
// Setting audience
let mut validation = Validation::default();
validation.set_audience(&"Me"); // string
validation.set_audience(&["Me", "You"]); // array of strings

Algorithms

This library currently supports the following:

  • HS256
  • HS384
  • HS512
  • RS256
  • RS384
  • RS512
  • PS256
  • PS384
  • PS512
  • ES256
  • ES384

RSA & ECDSA

By default, the encode/decode functions takes the PEM format since it is the most common. RSA can also use the public key components modulus/exponent in base64 format for decoding.