Crate rjwt[][src]

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:


struct Resolver {
    host: String,
    actors: HashMap<String, Actor<String>>,
    peers: HashMap<String, Resolver>,
}
// ...

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

    fn host(&self) -> String {
        self.host.clone()
    }

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

let now = SystemTime::now();

// Say that Bob is a user at 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 retail_app = Actor::new("app".to_string());
let retailer = Resolver::new(
    "retailer.com".to_string(), 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, vec![retailer.clone(), example]);

// 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");
let bobs_token = Token::new(
    example_dot_com.clone(),
    now,
    Duration::from_secs(30),
    actor_bob.id().to_string(),
    bobs_claim);

let bobs_token = actor_bob.sign_token(&bobs_token).unwrap();

// Then, retailer.com consumes the token (validating it in the process).
let retailer_claim = String::from("Bob spent $1 on retailer.com");
let (retailer_token, _) = block_on(
    retailer.consume_and_sign(&retail_app, retailer_claim, bobs_token, now)).unwrap();

// Finally, Bob's bank validates the token to verify that the request came from Bob.
let claims = block_on(bank.validate(&retailer_token, now)).unwrap();
assert!(claims.get(&example_dot_com, &bobs_id).unwrap().starts_with("I am Bob"));

Structs

Actor

An actor with an identifier of type T and an ECDSA keypair used to sign tokens.

Claims

All the claims of a recursive Token.

Error

An error encountered while handling a Token.

Keypair

An ed25519 keypair.

PublicKey

An ed25519 public key.

Signature

Ed25519 signature.

Token

The JSON Web Token wire format.

Enums

ErrorKind

The type of error encountered. Auth means that the token signature failed validation. Fetch means that there was an error fetching the public key of the actor to validate.

Traits

Resolve

Trait which defines how to fetch the PublicKey given a host and actor ID.

Type Definitions

Result

The result of a Token operation.