#jwt #pki #authorization #authz

ucan

Implement UCAN-based authorization with conciseness and ease!

18 releases

0.7.0-alpha.1 Oct 4, 2022
0.6.0-alpha.1 May 19, 2022
0.5.0-alpha.6 Apr 1, 2022
0.5.0-alpha.5 Mar 31, 2022
0.1.0 Nov 29, 2022

#657 in Cryptography

Download history 533/week @ 2023-12-04 559/week @ 2023-12-11 297/week @ 2023-12-18 70/week @ 2023-12-25 388/week @ 2024-01-01 1093/week @ 2024-01-08 1364/week @ 2024-01-15 1288/week @ 2024-01-22 1113/week @ 2024-01-29 1757/week @ 2024-02-05 757/week @ 2024-02-12 807/week @ 2024-02-19 799/week @ 2024-02-26 1190/week @ 2024-03-04 868/week @ 2024-03-11 314/week @ 2024-03-18

3,173 downloads per month
Used in 20 crates (14 directly)

Apache-2.0

105KB
2.5K SLoC

This is the core Rust UCAN implementation.

See https://docs.rs/ucan for documentation.


lib.rs:

Implement UCAN-based authorization with conciseness and ease!

UCANs are an emerging pattern based on JSON Web Tokens (aka JWTs) that facilitate distributed and/or decentralized authorization flows in web applications. Visit https://ucan.xyz for an introduction to UCANs and ideas for how you can use them in your application.

Examples

This crate offers the builder::UcanBuilder abstraction to generate signed UCAN tokens.

To generate a signed token, you need to provide a crypto::SigningKey implementation. For more information on providing a signing key, see the crypto module documentation.

use ucan::{
  builder::UcanBuilder,
  crypto::KeyMaterial,
};

async fn generate_token<'a, K: KeyMaterial>(issuer_key: &'a K, audience_did: &'a str) -> Result<String, anyhow::Error> {
    UcanBuilder::default()
      .issued_by(issuer_key)
      .for_audience(audience_did)
      .with_lifetime(60)
      .build()?
      .sign().await?
      .encode()
}

The crate also offers a validating parser to interpret UCAN tokens and the capabilities they grant via their issuer and/or witnessing proofs: the chain::ProofChain.

Most capabilities are closely tied to a specific application domain. See the capability module documentation to read more about defining your own domain-specific semantics.

use ucan::{
  chain::{ProofChain, CapabilityInfo},
  capability::{CapabilitySemantics, Scope, Action},
  crypto::did::{DidParser, KeyConstructorSlice},
  store::UcanJwtStore
};

const SUPPORTED_KEY_TYPES: &KeyConstructorSlice = &[
    // You must bring your own key support
];

async fn get_capabilities<'a, Semantics, S, A, Store>(ucan_token: &'a str, semantics: &'a Semantics, store: &'a Store) -> Result<Vec<CapabilityInfo<S, A>>, anyhow::Error>
    where
        Semantics: CapabilitySemantics<S, A>,
        S: Scope,
        A: Action,
        Store: UcanJwtStore
{
    let mut did_parser = DidParser::new(SUPPORTED_KEY_TYPES);

    Ok(ProofChain::try_from_token_string(ucan_token, &mut did_parser, store).await?
        .reduce_capabilities(semantics))
}

Note that you must bring your own key support in order to build a ProofChain, via a crypto::did::DidParser. This is so that the core library can remain agnostic of backing implementations for specific key types.

Dependencies

~8–20MB
~313K SLoC