Rust

The Rust version of Biscuit can be found on Github, crates.io and on docs.rs.

Install

In Cargo.toml:

biscuit-auth = "3.1"

Create a root key

#![allow(unused)]
fn main() {
use biscuit_auth::KeyPair;

let root_keypair = KeyPair::new();
}

Create a token

#![allow(unused)]

fn main() {
use biscuit_auth::{error, macros::*, Biscuit, KeyPair};

fn create_token(root: &KeyPair) -> Result<Biscuit, error::Token> {
    let user_id = "1234";
    // the authority block can be built from a datalog snippet
    // the snippet is parsed at compile-time, efficient building
    // code is generated
    let mut authority = biscuit!(
      r#"
      // parameters can directly reference in-scope variables
      user({user_id});

      // parameters can be manually supplied as well
      right({user_id}, "file1", {operation});
      "#,
      operation = "read",
    );

    // it is possible to modify a builder by adding a datalog snippet
    biscuit_merge!(
      &mut authority,
      r#"check if operation("read");"#
    );

    authority.build(&root)
}
}

Create an authorizer

#![allow(unused)]
fn main() {
use biscuit_auth::{builder_ext::AuthorizerExt, error, macros::*, Biscuit};

fn authorize(token: &Biscuit) -> Result<(), error::Token> {
    let operation = "read";

    // same as the `biscuit!` macro. There is also a `authorizer_merge!`
    // macro for dynamic authorizer construction
    let mut authorizer = authorizer!(
      r#"operation({operation});"#
    );

    // register a fact containing the current time for TTL checks
    authorizer.set_time();

    // add a `allow if true;` policy
    // meaning that we are relying entirely on checks carried in the token itself
    authorizer.add_allow_all();

    // link the token to the authorizer
    authorizer.add_token(token)?;

    authorizer.authorize()?;

    Ok(())
}
}

Attenuate a token

#![allow(unused)]
fn main() {
use biscuit_auth::{builder_ext::BuilderExt, error, macros::*, Biscuit};
use std::time::{Duration, SystemTime};

fn attenuate(token: &Biscuit) -> Result<Biscuit, error::Token> {
    let res = "file1";
    // same as `biscuit!` and `authorizer!`, a `block_merge!` macro is available
    let mut builder = block!(r#"check if resource({res});"#);

    builder.check_expiration_date(SystemTime::now() + Duration::from_secs(60));

    token.append(builder)
}
}

Seal a token

#![allow(unused)]
fn main() {
let sealed_token = token.seal()?;
}

Reject revoked tokens

The Biscuit::revocation_identifiers method returns the list of revocation identifiers as byte arrays. Don't forget to parse them from a textual representation (for instance hexadecimal) if you store them as text values.

#![allow(unused)]
fn main() {
let identifiers: Vec<Vec<u8>> = token.revocation_identifiers();
}

Query data from the authorizer

The Authorizer::query method takes a rule as argument and extract the data from generated facts as tuples.

#![allow(unused)]
fn main() {
let res: Vec<(String, i64)> =
    authorizer.query("data($name, $id) <- user($name, $id)").unwrap();
}