This page looks best with JavaScript enabled

Using JWT in Rust

 ·  ☕ 2 min read  ·  🤖 Ashish Shekar

I got my Rust service running with JWT and want to share experiences and errors that I got along the way. I hope it would be helpful for other people
writing web services in Rust. I like to keep my post clear with small and concise bits. Let’s start with the journey..

The Crate

After some really long inspection, I went on with this crate - https://github.com/Keats/jsonwebtoken. Compared to other crate this is easier to use and has great documentation.

1
jsonwebtoken = "7.2.0"

The Encoding Part

The encoding is done by a single function called encode. It takes in 3 arguments:

  1. Header: To specify the algorithm to create hash from, and type of JWT .
  2. Claims: The content of your uniquely identifiable token is present in this struct.
  3. EncodingKey: Key to encode your claims, can be a secret, a PEM-encoded key or a DER-encoded key.

We’ll go with the secret for this specific post..

1
2
3
4
5
6
7
8
9
use jsonwebtoken::{encode, errors, Header, EncodingKey};
pub struct Claims {
    uuid: String
}
pub fn get_token(claims: &Claims) -> Result<String, errors::Error> {
    let header = Header::new(Algorithm::HS256);
    let key = EncodingKey::from_secret("secret!!".as_ref());
    encode(&header, claims, &key)
}

The Decoding Part

The decoding is done using a function called decode which has the following signature:

1
2
3
pub fn decode<T>(token: &str, key: &DecodingKey, validation: &Validation) -> Result<TokenData<T>>
where
    T: DeserializeOwned

and is generic over T where T is our Claims struct.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
pub fn uuid_from_token(token: &str) -> Result<String, errors::Error> {
    let mut validation = Validation::new(Algorithm::HS256);
    validation.validate_exp = false;
    let c = decode::<Claims>(
        token,
        &DecodingKey::from_secret("secret".as_ref()),
        &validation,
    )?;
    Ok(c.claims.uuid)
}

JWT gives errors::ErrorKind::ExpiredSignature

It is important that you specify validation.validate_exp = false; so that the decoder does not check for the expiry of the token.

Testing your Impl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#[test]
fn decode_with_invalid_token() {
    let token_res = uuid_from_token("ashish");

    assert_eq!(token_res.is_err(), true);
}

#[test]
fn encode_token() {
    let c = &Claims{ uuid: "ash123" };
    let token_res = get_token(c);

    assert_eq!(token_res.is_ok(), true);
    assert_ne!(token_res.unwrap(), "");
}

#[test]
fn decode_proper_token() {
    let c = &Claims{ uuid: "ash123" };
    let token = get_token(c).unwrap();

    let token_res = uuid_from_token(&token);
    assert_eq!(token_res.is_ok(), true);
    assert_eq!(token_res.unwrap(), "ash123");
}
Share on

Ashish Shekar
WRITTEN BY
Ashish Shekar
Just a guy who writes serious code for fun...