Crate rjwt

Source
Expand description

Provides an Actor and (de)serializable Token struct which support authenticating JSON Web Tokens with a custom payload. See jwt.io for more information on the JWT spec.

The provided Actor uses the ECDSA algorithm to sign tokens (using the ed25519_dalek crate).

This library differs from other JWT implementations in that it allows for recursive Tokens.

Note that if the same (host, actor) pair is specified multiple times in the token chain, only the latest is returned by Claims::get.

Example:

use rjwt::*;

#[derive(Clone)]
struct Resolver {
    hostname: String,
    actors: HashMap<String, Actor<String>>,
    peers: Vec<Self>,
}
// ...

#[async_trait]
impl Resolve for Resolver {
    type HostId = String;
    type ActorId = String;
    type Claims = String;

    async fn resolve(&self, host: &Self::HostId, actor_id: &Self::ActorId) -> Result<Actor<Self::ActorId>, Error> {
        if host == &self.hostname {
            self.actors.get(actor_id).cloned().ok_or_else(|| Error::fetch(actor_id))
        } else if let Some(peer) = self.peers.iter().filter(|p| &p.hostname == host).next() {
            peer.resolve(host, actor_id).await
        } else {
            Err(Error::fetch(host))
        }
    }
}

let now = SystemTime::now();

// Say that Bob is a user on example.com.
let bobs_id = "bob".to_string();
let example_dot_com = "example.com".to_string();

let actor_bob = Actor::new(bobs_id.clone());
let example = Resolver::new(example_dot_com.clone(), [actor_bob.clone()], vec![]);

// Bob makes a request through the retailer.com app.
let retailer_dot_com = "retailer.com".to_string();
let retail_app = Actor::new("app".to_string());
let retailer = Resolver::new(
    retailer_dot_com.clone(),
    [retail_app.clone()],
    vec![example.clone()]);

// The retailer.com app makes a request to Bob's bank.
let bank_account = Actor::new("bank".to_string());
let bank = Resolver::new(
    "bank.com".to_string(),
    [bank_account.clone()],
    vec![example, retailer.clone()]);

// First, example.com issues a token to authenticate Bob.
let bobs_claim = String::from("I am Bob and retailer.com may debit my bank.com account");

// This requires constructing the token...
let bobs_token = Token::new(
    example_dot_com.clone(),
    now,
    Duration::from_secs(30),
    actor_bob.id().to_string(),
    bobs_claim.clone());

// and signing it with Bob's private key.
let bobs_token = actor_bob.sign_token(bobs_token).expect("signed token");

// Then, retailer.com validates the token...
let bobs_token = block_on(retailer.verify(bobs_token.into_jwt(), now)).expect("claims");
assert!(bobs_token.claims().get(&example_dot_com, &bobs_id).expect("claim").starts_with("I am Bob"));

// and adds its own claim, that Bob owes it $1.
let retailer_claim = String::from("Bob spent $1 on retailer.com");
let retailer_token = retail_app.consume_and_sign(
    bobs_token,
    retailer_dot_com.clone(),
    retailer_claim.clone(),
    now).expect("signed token");

assert_eq!(retailer_token
    .claims()
    .get(&retailer_dot_com, retail_app.id()), Some(&retailer_claim));

assert_eq!(retailer_token
    .claims()
    .get(&example_dot_com, actor_bob.id()), Some(&bobs_claim));

// Finally, Bob's bank verifies the token...
let retailer_token_as_received = block_on(
    bank.verify(retailer_token.jwt().to_string(), now)
).expect("claims");

assert_eq!(retailer_token, retailer_token_as_received);

// to authenticate that the request came from Bob...
assert!(retailer_token_as_received
    .claims()
    .get(&example_dot_com, &bobs_id)
    .expect("claim")
    .starts_with("I am Bob and retailer.com may debit my bank.com account"));

// via retailer.com.
assert!(retailer_token_as_received
    .claims()
    .get(&retailer_dot_com, retail_app.id())
    .expect("claim")
    .starts_with("Bob spent $1"));

Structs§

Actor
An actor with an identifier of type T and an ECDSA keypair used to sign tokens.
Claims
The Claims of a SignedToken
Error
An error returned by a JWT operation
Iter
OsRng
A random number generator that retrieves randomness from the operating system.
Signature
Ed25519 signature.
SignedToken
The data of a JWT including its (inherited) claims and encoded, signed representation.
SigningKey
ed25519 signing key which can be used to produce signatures.
Token
The JSON Web Token wire format
VerifyingKey
An ed25519 public key.

Enums§

ErrorKind
The category of error returned by a JWT operation

Traits§

Resolve
Trait which defines how to fetch an Actor given its host and ID