Expand description
§macarunes
This library provides an implementation of Macaroons. For an introduction to macaroons, check out the paper, or the Python README.
§Quick Start
Mint a macaroon with a root secret, attenuate it with caveats, and verify it with the same root secret plus the request context that satisfies those caveats.
use macarunes::{Macaroon, Secret, Verifier};
let secret = Secret::from_bytes([7; macarunes::SIGNATURE_BYTES]);
let mut macaroon = Macaroon::new(
"https://issuer.example",
"alice@example",
secret.clone(),
)?;
macaroon.add_fact("role", "admin")?;
macaroon.add_expires(4_102_444_800)?;
let verifier = Verifier::new()
.with_fact("role", "admin")
.with_current_time(1_700_000_000);
verifier.verify(&macaroon, &secret, &[])?;§Why Macaroons?
Macaroons occupy the same practical space as cookies and bearer tokens: the holder presents the token, and the receiver decides whether the token authorizes the requested action. The difference is that a macaroon can carry restrictions that are added after it is minted. That makes delegation safer. A user can hand a macaroon to another program after adding caveats that narrow it to one account, one action, a short time window, or a proof from an authentication service.
That gives macaroons several useful properties:
- Delegation can be confined to the context in which it should be valid.
- Attenuation is monotonic: holders can add caveats, but cannot remove caveats that have already been signed into the macaroon.
- Authorization proofs travel with the request, so the verifier does not need to keep a server-side copy of every attenuated macaroon.
- Third-party caveats let one service depend on another service’s decision without putting that decision logic into the first service.
- The verifier stays small and reusable. The policy lives in the macaroons that services mint and attenuate, while the verifier checks whether the proof and current request context satisfy that policy.
§Core Ideas
Macaroons are bearer credentials that can be attenuated. A service mints a root macaroon from a root secret and an identifier. Whoever holds that macaroon can add caveats that restrict where, when, or under which application context it verifies. Adding a caveat changes the macaroon signature, so a receiver can detect tampering without keeping a copy of every macaroon it has issued.
macarunes keeps the core language intentionally small:
Macarooncarries a location hint, an identifier, a signature, and caveats.Secretholds 32 bytes of key material and scrubs its storage on drop.Verifierchecks a root macaroon, its first-party caveats, and any discharge macaroons supplied for third-party caveats.ThirdPartySecretlets one service require proof from another service without revealing the discharge service’s root secret.PreparedRequestcarries a root macaroon plus the bound discharge macaroons a client should send with a request.RequestBuilder,AsyncRequestBuilder, and loaders assemble prepared requests from root and discharge locations.
The caveat language has four cases:
- Exact-string caveats require a verifier context string with exactly the same bytes.
- Expiration caveats require a verifier current time and
expiration > current_time; equality is expired. - Not-before caveats require a verifier current time and
current_time >= not_before; equality is valid. - Third-party caveats require a matching discharge macaroon, bound to the root macaroon for this request.
§Installing
Use the crate from this workspace or add it as a normal Rust dependency:
[dependencies]
macarunes = "0.11"Enable the optional base64 feature if you want the to_base64 and
from_base64 convenience helpers:
[dependencies]
macarunes = { version = "0.11", features = ["base64"] }§Secrets
Use Secret::random when minting real credentials. Use Secret::from_base64,
Secret::from_hex, or Secret::try_from_slice when loading configured key
material from a protected storage system. Use Secret::from_bytes for
deterministic tests and lower-level integrations. The Base64 helpers require
the base64 feature.
use macarunes::Secret;
let generated = Secret::random()?;
assert_eq!(43, generated.to_base64().len());
let configured = Secret::from_base64(
"q6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6s",
)?;
assert_eq!(
"abababababababababababababababababababababababababababababababab",
configured.hexdigest(),
);to_base64 and hexdigest return raw key material. Keep them for controlled
configuration, diagnostics, and deterministic tests; do not log them for live
credentials. Debug for Secret is intentionally redacted.
Secret makes a best-effort attempt to scrub its internal memory when dropped.
That does not make logged, cloned, serialized, swapped, or otherwise copied
secrets safe. Treat root secrets and discharge secrets as server-side keys.
The fixed width of Secret is intentional: use all SIGNATURE_BYTES bytes, and
draw them from a cryptographically strong random source. Short, human-readable,
or predictable secrets make it easier to forge macaroons.
§Minting a Root Macaroon
A root macaroon starts with a public location, a public identifier, and a secret known to the service that will later verify it.
use macarunes::{Macaroon, Secret};
let root_secret = Secret::from_bytes([1; macarunes::SIGNATURE_BYTES]);
let macaroon = Macaroon::new(
"https://files.example/macaroons",
"file:alpha",
root_secret,
)?;
assert_eq!("https://files.example/macaroons", macaroon.location());
assert_eq!("file:alpha", macaroon.identifier());
assert!(!macaroon.has_caveats());The location is a routing hint. It is intentionally not protected by the macaroon signature, so do not use it as an authority decision. The identifier is the stable public value the issuing service uses to find or derive the root secret needed for verification. Common identifier strategies include a database key, an encrypted record that only the issuer can open, or a structured name that is enough to deterministically derive the secret. The identifier can be visible to anyone who holds the macaroon; it must not reveal the root secret.
The signature is also present in the macaroon. It changes when caveats are added and becomes the key material used for later attenuation. In application code, treat possession of a macaroon or its signature as possession of the credential.
§First-Party Caveats
First-party caveats are checked directly by the final verifier. They are useful for request facts that the verifier can compute locally, such as method, path, tenant, role, or deadline.
use macarunes::{Error, Macaroon, Secret, Verifier};
let secret = Secret::from_bytes([2; macarunes::SIGNATURE_BYTES]);
let mut macaroon = Macaroon::new("https://issuer.example", "alice", secret.clone())?;
macaroon.add_fact("method", "GET")?;
macaroon.add_fact("path", "/v1/accounts/alice")?;
macaroon.add_expires(1_900_000_000)?;
let accepted = Verifier::new()
.with_fact("method", "GET")
.with_fact("path", "/v1/accounts/alice")
.with_current_time(1_800_000_000);
assert_eq!(Ok(()), accepted.verify(&macaroon, &secret, &[]));
let rejected = Verifier::new()
.with_fact("method", "POST")
.with_fact("path", "/v1/accounts/alice")
.with_current_time(1_800_000_000);
assert_eq!(
Err(Error::ProofInvalid),
rejected.verify(&macaroon, &secret, &[]),
);Exact-string caveats are not parsed by the library. Define your own canonical
format, normalize request facts before adding them to the verifier, and keep
those strings stable across services. For the common name = value shape, use
add_fact and with_fact; the fact name must be &'static str so application
code controls the fact vocabulary.
§Verifier Design
Build the verifier from facts about the request, not by inspecting the macaroon
and trying to make its caveats pass. For example, an HTTP service can add facts
like method = GET, path = /v1/accounts/alice, user = alice,
account = 3735928559, and action = deposit for every request. A macaroon
that mentions any subset of those true facts will verify; a macaroon that adds
an unknown or false fact will not.
This keeps authorization policy decoupled from enforcement. You can mint a new
macaroon with a narrower policy without changing the verifier, provided the
verifier already knows how to state the relevant request facts. This crate does
not expose libmacaroons-style general callback caveats. Use exact strings or
add_fact for canonical request facts, and use add_not_before and add_expires for
verifier-time bounds. If you need a richer predicate, evaluate it in your
application and add the resulting canonical fact to the verifier context; or,
use third-party caveats.
§Expiration Caveats
add_expires takes an unsigned integer timestamp. The verifier accepts the
macaroon only when the expiration is strictly greater than the verifier’s
current time. An expiration caveat fails if verifier time has not been set.
Use add_expires_at when you already have a SystemTime, and use add_ttl
when issuing a macaroon relative to the current system time. add_ttl_from
does the same calculation from an explicit SystemTime, which is useful for
tests and request-scoped clocks.
use macarunes::{Error, Macaroon, Secret, Verifier};
let secret = Secret::from_bytes([3; macarunes::SIGNATURE_BYTES]);
let mut macaroon = Macaroon::new("https://issuer.example", "alice", secret.clone())?;
macaroon.add_expires(1_700_000_000)?;
assert_eq!(
Ok(()),
Verifier::new()
.with_current_time(1_699_999_999)
.verify(&macaroon, &secret, &[]),
);
assert_eq!(
Err(Error::ProofInvalid),
Verifier::new()
.with_current_time(1_700_000_000)
.verify(&macaroon, &secret, &[]),
);Calling add_ttl or add_ttl_from appends a new expiration caveat. It does
not remove or rewrite earlier caveats. Verification requires every expiration
caveat to hold, so the effective expiration is the minimum of all expiration
caveats.
use std::time::{Duration, UNIX_EPOCH};
use macarunes::{Error, Macaroon, Secret, Verifier};
let secret = Secret::from_bytes([13; macarunes::SIGNATURE_BYTES]);
let mut macaroon = Macaroon::new("https://issuer.example", "alice", secret.clone())?;
macaroon.add_expires(200)?;
macaroon.add_ttl_from(
UNIX_EPOCH + Duration::from_secs(100),
Duration::from_secs(50),
)?;
assert_eq!(
Ok(()),
Verifier::new()
.with_current_time(149)
.verify(&macaroon, &secret, &[]),
);
assert_eq!(
Err(Error::ProofInvalid),
Verifier::new()
.with_current_time(150)
.verify(&macaroon, &secret, &[]),
);§Not-Before Caveats
add_not_before takes an unsigned integer timestamp. The verifier accepts the
macaroon only when the verifier’s current time is greater than or equal to that
timestamp. Equality is valid. A not-before caveat fails if verifier time has
not been set.
This is the intrinsic caveat to use when an issued credential should place an
inclusive lower bound on the verification time. Use add_not_before_at to add
the caveat from a SystemTime, and use Verifier::with_current_system_time or
Verifier::with_system_time_now when building a verifier from system time.
use macarunes::{Error, Macaroon, Secret, Verifier};
let secret = Secret::from_bytes([12; macarunes::SIGNATURE_BYTES]);
let mut macaroon = Macaroon::new("https://issuer.example", "alice", secret.clone())?;
macaroon.add_not_before(1_700_000_000)?;
assert_eq!(
Err(Error::ProofInvalid),
Verifier::new()
.with_current_time(1_699_999_999)
.verify(&macaroon, &secret, &[]),
);
assert_eq!(
Ok(()),
Verifier::new()
.with_current_time(1_700_000_000)
.verify(&macaroon, &secret, &[]),
);§What Verification Rejects
Verifier::verify succeeds only when all of these conditions hold:
- The root secret matches the root macaroon identifier.
- Every first-party caveat is satisfied by the verifier context or current time.
- Every third-party caveat has a matching discharge macaroon.
- Every discharge macaroon verifies under the secret hidden in the third-party caveat.
- Every discharge has been bound to the root macaroon for this request.
- The final signatures match after replaying the caveat chain.
The verifier deliberately collapses most proof failures into
Error::ProofInvalid. For authorization decisions, treat ProofInvalid as
“not authorized” rather than trying to distinguish wrong secrets, missing
contexts, expired caveats, tampering, or missing discharges. For controlled
diagnostics, log the Debug output of the macaroon and verifier together:
Macaroon shows public location, identifier, and caveats while redacting the
signature, and Verifier shows the request context and verifier time.
§Third-Party Caveats
A third-party caveat lets the root service require a second service to issue a
discharge macaroon. The root service does not learn the discharge service’s
secret. The discharge service receives the current root macaroon signature,
wraps its discharge secret in a ThirdPartySecret, and gives that value back to
the root service. The root service then embeds the third-party caveat.
The usual flow is:
- The root service decides that a request should require a third-party proof.
- The third party chooses or records the predicate it will enforce, such as
user = alice. - The third party creates a discharge secret and a public identifier that lets it recover the predicate and discharge secret later.
- The root service embeds the public location, public identifier, and
ThirdPartySecretin the root macaroon. - The client presents the location and identifier to the third party.
- The third party checks its predicate and returns a discharge macaroon.
- The client binds the discharge to the root macaroon and sends both to the verifier.
The root macaroon does not need to reveal the predicate that the third party checked. The identifier may be an opaque handle into the third party’s storage. That lets the final verifier accept the third-party proof without knowing the third party’s internal policy, user database, or authentication protocol.
Use ThirdPartySecret::random for production third-party caveats. If a
protocol has to provide nonce material explicitly, use Nonce::from_bytes;
nonce bytes are public, but they must be unique for a given macaroon signature.
use macarunes::{Macaroon, Secret, ThirdPartySecret, Verifier};
const ROOT_LOCATION: &str = "https://files.example/macaroons";
const AUTH_LOCATION: &str = "https://auth.example/discharges";
let root_secret = Secret::from_bytes([4; macarunes::SIGNATURE_BYTES]);
let auth_secret = Secret::from_bytes([5; macarunes::SIGNATURE_BYTES]);
let mut root = Macaroon::new(ROOT_LOCATION, "file:alpha", root_secret.clone())?;
let third_party_secret = ThirdPartySecret::random(root.signature(), &auth_secret)?;
root.add_third_party_caveat(
AUTH_LOCATION,
"authz:alice:file:alpha",
third_party_secret,
)?;
let mut discharge = Macaroon::new(
AUTH_LOCATION,
"authz:alice:file:alpha",
auth_secret,
)?;
discharge.add_exact_string("user = alice")?;
root.bind_discharge(&mut discharge)?;
let verifier = Verifier::new().with_context("user = alice");
verifier.verify(&root, &root_secret, &[discharge])?;Binding matters. A discharge macaroon must be bound to the root macaroon before
verification so that a discharge created for one request cannot be replayed with
another root macaroon. If you assemble discharges manually, call
root.bind_discharge(&mut discharge) for one mutable discharge,
root.bind_discharge_owned(discharge) when you want to consume and return a
bound discharge, or root.bind_discharges(&mut discharges) for a whole slice.
If you use RequestBuilder, it performs this binding for you.
The upstream libmacaroons guide also describes a public-key variant in which the
third-party identifier can carry encrypted caveat material instead of requiring a
round trip to create an identifier. macarunes does not provide that public-key
scheme directly. You can still build a protocol with the same shape by making
the identifier an opaque ciphertext or lookup key understood by your
third-party service, then issuing a normal Macaroon as the discharge.
§Preparing Requests with Loaders
RequestBuilder is the client-side helper for request assembly. Register one
Loader per location. The builder loads the root macaroon, recursively follows
third-party caveats, loads each required discharge macaroon, and binds all
discharges to the root before returning them.
Loader locations are static trusted code capabilities: Loader::location
returns &'static str, and RequestBuilder is keyed by those static strings.
The public locations embedded in macaroons remain untrusted routing hints. They
select among discharge mechanisms already registered in code; they do not create
new mechanisms from macaroon data.
use macarunes::{
Macaroon, RequestBuilder, Secret, StaticLoader, ThirdPartySecret, Verifier,
};
const ROOT_LOCATION: &str = "https://files.example/macaroons";
const AUTH_LOCATION: &str = "https://auth.example/discharges";
let root_secret = Secret::from_bytes([6; macarunes::SIGNATURE_BYTES]);
let auth_secret = Secret::from_bytes([7; macarunes::SIGNATURE_BYTES]);
let mut root = Macaroon::new(ROOT_LOCATION, "file:alpha", root_secret.clone())?;
let third_party_secret = ThirdPartySecret::random(root.signature(), &auth_secret)?;
root.add_third_party_caveat(
AUTH_LOCATION,
"authz:alice:file:alpha",
third_party_secret,
)?;
let mut discharge = Macaroon::new(
AUTH_LOCATION,
"authz:alice:file:alpha",
auth_secret,
)?;
discharge.add_exact_string("user = alice")?;
let builder = RequestBuilder::new()
.with_loader(StaticLoader::new(ROOT_LOCATION, vec![root]))?
.with_loader(StaticLoader::new(AUTH_LOCATION, vec![discharge]))?;
let request = builder.prepare(ROOT_LOCATION, "file:alpha")?;
Verifier::new()
.with_context("user = alice")
.verify_request(&request, &root_secret)?;Production loaders usually wrap an RPC client, local cache, database lookup, or
service-discovery layer. A loader should return macaroons for exactly one
location. RequestBuilder rejects a macaroon if the loader returns a different
location than the one requested, and it rejects duplicate loader registration
for the same static location.
The crate provides small loader affordances for common cases:
StaticLoaderscans a vector and is convenient for examples and tests.MapLoaderstores macaroons by identifier and checks locations on insert.FnLoaderandRequestBuilder::with_lookupadapt a closure into a loader.
RequestBuilder::prepare returns a PreparedRequest with named root and
discharges fields. prepare_request remains available when you want the old
(Macaroon, Vec<Macaroon>) shape.
Use AsyncRequestBuilder with AsyncLoader when a loader naturally performs
RPC, database, or cache work asynchronously. StaticLoader, MapLoader, and
FnLoader also work with AsyncRequestBuilder; for native async closures, use
AsyncFnLoader or AsyncRequestBuilder::with_lookup.
use macarunes::{AsyncRequestBuilder, Macaroon, Secret, StaticLoader};
const ROOT_LOCATION: &str = "https://files.example/macaroons";
let root_secret = Secret::from_bytes([14; macarunes::SIGNATURE_BYTES]);
let root = Macaroon::new(ROOT_LOCATION, "file:alpha", root_secret)?;
let builder = AsyncRequestBuilder::new()
.with_loader(StaticLoader::new(ROOT_LOCATION, vec![root]))?;
let request = builder.prepare(ROOT_LOCATION, "file:alpha").await?;
assert_eq!("file:alpha", request.root.identifier());§Selecting Discharges from a Cache
Use Macaroon::covering_set when a client already has many candidate discharge
macaroons and only needs to select the transitive set referenced by a root
macaroon. Selection uses public location and identifier data only. It does not
verify signatures, decrypt third-party secrets, satisfy caveats, or bind
unbound discharges.
use macarunes::{Macaroon, Secret, ThirdPartySecret, Verifier};
const ROOT_LOCATION: &str = "https://files.example/macaroons";
const AUTH_LOCATION: &str = "https://auth.example/discharges";
let root_secret = Secret::from_bytes([8; macarunes::SIGNATURE_BYTES]);
let auth_secret = Secret::from_bytes([9; macarunes::SIGNATURE_BYTES]);
let mut root = Macaroon::new(ROOT_LOCATION, "file:alpha", root_secret.clone())?;
let third_party_secret = ThirdPartySecret::random(root.signature(), &auth_secret)?;
root.add_third_party_caveat(
AUTH_LOCATION,
"authz:alice:file:alpha",
third_party_secret,
)?;
let mut discharge = Macaroon::new(
AUTH_LOCATION,
"authz:alice:file:alpha",
auth_secret,
)?;
root.bind_discharge(&mut discharge)?;
let noise = Macaroon::new(
"https://other.example/discharges",
"unrelated",
Secret::from_bytes([10; macarunes::SIGNATURE_BYTES]),
)?;
let candidates = vec![noise, discharge];
let selected = root.covering_set(&candidates)?;
assert_eq!(1, selected.len());
Verifier::new().verify(&root, &root_secret, &selected)?;Use covering_set_refs when you want references into the candidate slice
instead of cloned macaroons.
§Serialization
Macaroon, PreparedRequest, Secret, and ThirdPartySecret implement the
repository’s prototk message traits. Use Macaroon::to_bytes and
Macaroon::from_bytes to encode and decode macaroons for structured storage or
transport. from_bytes rejects trailing bytes.
use macarunes::{Macaroon, Secret};
let secret = Secret::from_bytes([11; macarunes::SIGNATURE_BYTES]);
let mut macaroon = Macaroon::new("https://issuer.example", "alice", secret)?;
macaroon.add_exact_string("role = admin")?;
let bytes = macaroon.to_bytes();
let decoded = Macaroon::from_bytes(&bytes)?;
assert_eq!(macaroon, decoded);Use to_base64 and from_base64 for cookies, headers, URLs, email bodies, or
configuration systems that need ASCII text. The encoding is URL-safe Base64
without padding; decoders accept padded URL-safe or standard Base64 input.
These helpers require the base64 feature.
use macarunes::{Macaroon, PreparedRequest, Secret};
let secret = Secret::from_bytes([15; macarunes::SIGNATURE_BYTES]);
let macaroon = Macaroon::new("https://issuer.example", "alice", secret)?;
let encoded = macaroon.to_base64();
let decoded = Macaroon::from_base64(&encoded)?;
assert_eq!(macaroon, decoded);
let request = PreparedRequest::new(macaroon, Vec::new());
let encoded_request = request.to_base64();
assert_eq!(request, PreparedRequest::from_base64(&encoded_request)?);§Verification Checklist
On the service that verifies a request:
- Recover or derive the root secret for the root macaroon identifier.
- Build a
Verifier. - Add every exact-string context or typed fact that should be true for this request.
- Set the verifier time before checking expiration or not-before caveats.
- Pass the root macaroon, root secret, and all bound discharges to
Verifier::verify, or pass aPreparedRequesttoVerifier::verify_request. - Treat every
Error::ProofInvalidas authentication failure.
On the client that prepares a request:
- Start with the root macaroon the target service gave you.
- Fetch every required discharge macaroon, including nested discharges.
- Bind every discharge to the root macaroon, or use
RequestBuilder/AsyncRequestBuilder. - Send the root macaroon and the bound discharge list together, often as a
serialized
PreparedRequest.
§Errors
The public error type is macarunes::Error:
ProofInvalidmeans the proof failed: wrong secret, missing context, expired or not-yet-valid caveat, missing discharge, unbound discharge, tampering, or any other verification failure.Cyclemeans verification detected recursive discharge structure deeper than the supplied discharge set.MissingLoadermeansRequestBuilderhas no loader for a location, or a loader could not find the requested macaroon.LocationMismatchmeans a loader returned a macaroon whose location differs from the requested loader location.MissingMacaroonmeanscovering_setcould not find a candidate with the public location and identifier required by a third-party caveat.DuplicateLoadermeansRequestBuilderalready has a loader registered for that static location.InvalidEncodingmeansMacaroon::from_bytesorPreparedRequest::from_bytescould not decode exactly one value from the provided bytes.RandomGenerationFailedmeans secure random secret generation failed.EncryptionFailedmeans third-party secret encryption failed.CryptoOperationFailedmeans a required cryptographic operation failed.InvalidBase64means a Base64 envelope could not be decoded.InvalidHexmeans a hex-encoded secret could not be decoded.InvalidSecretLengthmeans configured secret material was not exactlySIGNATURE_BYTESbytes.InvalidTimemeans aSystemTimecould not be represented as a macarunes timestamp.
§Assumptions
-
We rely upon the type system to provide memory safety. Secrets are scrubbed after use with libsodium’s memory clearing API, but that does not make logged, cloned, serialized, swapped, or otherwise copied secret material safe.
-
This library relies upon the determinism of the protocol buffers code. This is guaranteed by prototk.
-
Intentionally restrictive language compared to the Python implementation. The only cases you need in the core library are to make exact comparisons (which are born out as format strings), to set verifier-time bounds, or to use a third-party caveat that enforces some arbitrary predicate before the discharge macaroon is granted. Verifier time is the first-party intrinsic that cannot collapse onto stringified exact caveats because the verifier must compare the environment’s current time against a signed bound.
§About Locations
A location is a hint that is not part of the macaroon’s signature. Root macaroon locations, discharge macaroon locations, and third-party caveat locations are all intentionally unsigned. The verifier makes authority decisions from signed cryptographic material: identifiers, third-party identifiers, encrypted verification-key material, and the signature chain.
For that reason, locations should be treated as untrusted routing hints. They can affect request assembly because a client uses them to choose a registered loader, but changing a location does not by itself make a proof valid or invalid.
For each third party, a Loader should be developed that negotiates the
protocol to get discharge macaroons. Loader locations are static strings
registered by application code. A location from untrusted macaroon data only
selects among those registered loaders; unknown locations fail with
MissingLoader.
§Status
Active development.
§Scope
This library should provide a verifier and a client-side library.
§Warts
- This library is under-used and will see active development in the future.
§Documentation
The latest documentation is always available at docs.rs.
Structs§
- Async
FnLoader - An asynchronous loader backed by a closure returning a boxed future.
- Async
Request Builder - AsyncRequestBuilder handles request assembly using asynchronous loaders.
- FnLoader
- A loader backed by a closure.
- Macaroon
- A Macaroon has a location, identifier, signature, and caveats.
- MapLoader
- A simple loader backed by a hash map keyed by macaroon identifier.
- Nonce
- A public nonce for wrapping a ThirdPartySecret.
- Prepared
Request - A root macaroon and the discharge macaroons that should accompany it.
- Request
Builder - RequestBuilder handles assembly of requests, picking the minimal set of discharge macaroons.
- Secret
- A Secret holds SIGNATURE_BYTES that will be scrubbed at the end of its lifetime.
- Static
Loader - A simple loader backed by a vector of macaroons.
- Third
Party Secret - A third party secret. It is intended that this be generated by the server that holds a secret for discharge macaroons.
- Verifier
- Verifier implements the servers-side portion of macaroons. Note that the caveats we’ve chosen require very little logic from the server.
Enums§
Constants§
- NONCE_
BYTES - The number of bytes expected in a third-party secretbox nonce.
- SIGNATURE_
BYTES - The number of bytes expected in a macaroon signature.
Traits§
- Async
Loader - An asynchronous client-side way to get macaroons by identifier.
- Loader
- A Loader is a client-side way to get macaroons by identifier. Used by RequestBuilder.
Type Aliases§
- BoxMacaroon
Future - A boxed macaroon lookup future returned by AsyncLoader.