This is a Ruby implementation of macaroons. The implementation is stable but could still be subject to change, pending any standardization attempts around macaroons.
Macaroons, like cookies, are a form of bearer credential. Unlike opaque tokens, macaroons embed caveats that define specific authorization requirements for the target service, the service that issued the root macaroon and which is capable of verifying the integrity of macaroons it recieves.
Macaroons allow for delegation and attenuation of authorization. They are simple and fast to verify, and decouple authorization policy from the enforcement of that policy.
Simple examples are outlined below. For more in-depth examples check out the functional tests and references.
The macaroon implementation is pure Ruby, but relies on rbnacl to provide strong cryptographic primitives.
Install with:
gem install macaroons
And then import it into your Ruby program:
require'macaroons'key=>Verysecretkeyusedtosignthemacaroonidentifier=>Anidentifier,toremindyouwhichkeywasusedtosignthemacaroonlocation=>Thelocationatwhichthemacarooniscreated# Construct a Macaroon.m=Macaroon.new(key: key,identifier: identifier,location: 'http://foo.com')# Add first party caveatm.add_first_party_caveat('caveat_1')# List all first party caveatsm.first_party_caveats# Add third party caveatm.add_third_party_caveat('caveat_key','caveat_id','http://foo.com')# List all third party caveatsm.third_party_caveats# Create macaroon. Sign with a key and identifier (a way to remember which key was used)m=Macaroon.new(location: 'http://mybank/',identifier: 'we used our other secret key',key: 'this is a different super-secret key; never use the same secret twice')# Add a first party caveatm.add_first_party_caveat('account = 3735928559')# Add a third party caveatcaveat_key='4; guaranteed random by a fair toss of the dice'identifier='this was how we remind auth of key/pred'm.add_third_party_caveat(caveat_key,identifier,'http://auth.mybank/')# User collects a discharge macaroon (likely from a separate service), that proves the claims in the third-party caveat and which may add additional caveats of its owndischarge=Macaroon.new(location: 'http://auth.mybank/',identifier: identifier,key: caveat_key)discharge.add_first_party_caveat('time < 2015-01-01T00:00')# discharge macaroons are bound to the root macaroon so they cannot be reusedprotected_discharge=m.prepare_for_request(discharge)# The user sends their macaroon along with their discharge macaroons, and we verify themv=Macaroon::Verifier.new()v.satisfy_exact('account = 3735928559')v.satisfy_exact('time < 2015-01-01T00:00')verified=v.verify(macaroon: m,key: 'this is a different super-secret key; never use the same secret twice',discharge_macaroons: [protected_discharge])PyMacaroons is available for Python. PyMacaroons and Ruby-Macaroons are completely compatible (they can be used interchangibly within the same target service).
The libmacaroons library comes with Python and Go bindings.
PyMacaroons, libmacaroons, and Ruby-Macaroons all use the same underlying cryptographic library (libsodium).