1# PyMacaroons 2 3[![Build Status](https://travis-ci.org/ecordell/pymacaroons.svg?branch=master)](https://travis-ci.org/ecordell/pymacaroons) [![Coverage Status](https://coveralls.io/repos/ecordell/pymacaroons/badge.png)](https://coveralls.io/r/ecordell/pymacaroons) [![Downloads](https://img.shields.io/pypi/dd/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Latest Version](https://img.shields.io/pypi/v/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Supported Python versions](https://img.shields.io/pypi/pyversions/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Supported Python implementations](https://img.shields.io/pypi/implementation/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Development Status](https://img.shields.io/pypi/status/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![Wheel Status](https://img.shields.io/pypi/wheel/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) [![License](https://img.shields.io/pypi/l/pymacaroons.svg)](https://pypi.python.org/pypi/pymacaroons/) 4 5This is a Python implementation of Macaroons. It is still under active development but is in a useable state - please report any bugs in the issue tracker. 6 7## What is a Macaroon? 8Macaroons, 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. 9 10Macaroons allow for delegation and attenuation of authorization. They are simple and fast to verify, and decouple authorization policy from the enforcement of that policy. 11 12For a simple example, see the [Quickstart Guide](#quickstart). For more in-depth examples check out the [functional tests](https://github.com/ecordell/pymacaroons/blob/master/tests/functional_tests/functional_tests.py) and [references](#references-and-further-reading). 13 14## Installing 15 16PyMacaroons requires a sodium library like libsodium or tweetnacl to be installed on the host system. 17 18To install libsodium on mac, simply run: 19 20 brew install libsodium 21 22For other systems, see the [libsodium documentation](http://doc.libsodium.org/). 23 24To install PyMacaroons: 25 26 pip install pymacaroons 27 28 29## Quickstart 30 31### Create a Macaroon 32 33```python 34from pymacaroons import Macaroon, Verifier 35 36# Keys for signing macaroons are associated with some identifier for later 37# verification. This could be stored in a database, key value store, 38# memory, etc. 39keys = { 40 'key-for-bob': 'asdfasdfas-a-very-secret-signing-key' 41} 42 43# Construct a Macaroon. The location and identifier will be visible after 44# construction, and identify which service and key to use to verify it. 45m = Macaroon( 46 location='cool-picture-service.example.com', 47 identifier='key-for-bob', 48 key=keys['key-for-bob'] 49) 50 51# Add a caveat for the target service 52m.add_first_party_caveat('picture_id = bobs_cool_cat.jpg') 53 54# Inspect Macaroon (useful for debugging) 55print(m.inspect()) 56# location cool-picture-service.example.com 57# identifier key-for-bob 58# cid picture_id = bobs_cool_cat.jpg 59# signature 83d8fa280b09938d3cffe045634f544ffaf712ff2c51ac34828ae8a42b277f8f 60 61# Serialize for transport in a cookie, url, OAuth token, etc 62serialized = m.serialize() 63 64print(serialized) 65# MDAyZWxvY2F0aW9uIGNvb2wtcGljdHVyZS1zZXJ2aWNlLmV4YW1wbGUuY29tCjAwMWJpZGVudGlmaWVyIGtleS1mb3ItYm9iCjAwMjdjaWQgcGljdHVyZV9pZCA9IGJvYnNfY29vbF9jYXQuanBnCjAwMmZzaWduYXR1cmUgg9j6KAsJk408_-BFY09UT_r3Ev8sUaw0goropCsnf48K 66``` 67 68### Verifying Macaroon 69```python 70# Some time later, the service recieves the macaroon and must verify it 71n = Macaroon.deserialize("MDAyZWxvY2F0aW9uIGNvb2wtcGljdHVyZS1zZXJ2aWNlLmV4YW1wbGUuY29tCjAwMWJpZGVudGlmaWVyIGtleS1mb3ItYm9iCjAwMjdjaWQgcGljdHVyZV9pZCA9IGJvYnNfY29vbF9jYXQuanBnCjAwMmZzaWduYXR1cmUgg9j6KAsJk408_-BFY09UT_r3Ev8sUaw0goropCsnf48K") 72 73v = Verifier() 74 75# General caveats are verified by arbitrary functions 76# that return True only if the caveat is understood and met 77def picture_access_validator(predicate): 78 # in this case, predicate = 'picture_id = bobs_cool_cat.jpg' 79 if predicate.split(' = ')[0] != 'picture_id': 80 return False 81 return predicate.split(' = ')[1] == 'bobs_cool_cat.jpg' 82 83# The verifier is informed of all relevant contextual information needed 84# to verify incoming macaroons 85v.satisfy_general(picture_access_validator) 86 87# Note that in this case, the picture_access_validator() is just checking 88# equality. This is equivalent to a satisfy_exact call, which just checks for 89# string equality 90v.satisfy_exact('picture_id = bobs_cool_cat.jpg') 91 92# Verify the macaroon using the key matching the macaroon identifier 93verified = v.verify( 94 n, 95 keys[n.identifier] 96) 97 98# if verified is True, the macaroon was untampered (signatures matched) AND 99# all caveats were met 100``` 101 102## Documentation 103 104The latest documentation can always be found on [ReadTheDocs](http://pymacaroons.readthedocs.org/en/latest/). 105 106## Python notes 107 108Compatible with Python 2 and 3. CI builds are generated for 2.6, 2.7, 3.3 and 3.4, as well as PyPy and PyPy3. May be compatible with other versions (or may require tweaking - feel free to contribute!) 109 110## Running Tests 111 112To run the tests: 113 114`tox` 115 116To run against a specific version of Python: 117 118`tox -e py34` 119 120[tox](https://tox.readthedocs.org/en/latest/index.html) is used for running tests locally against multiple versions of Python. Tests will only run against versions available to tox. 121 122## More Macaroons 123 124The [libmacaroons library](https://github.com/rescrv/libmacaroons) comes with Python and Go bindings, but PyMacaroons is implemented directly in Python for further portability and ease of installation. Benchmarks coming, but some speed tradeoffs are expected. 125 126The [Ruby-Macaroons](https://github.com/localmed/ruby-macaroons) library is available for Ruby. PyMacaroons and Ruby-Macaroons are completely compatible (they can be used interchangibly within the same target service). 127 128PyMacaroons, libmacaroons, and Ruby-Macaroons all use the same underlying cryptographic library (libsodium). 129 130## References and Further Reading 131 132- [The Macaroon Paper](http://research.google.com/pubs/pub41892.html) 133- [Mozilla Macaroon Tech Talk](https://air.mozilla.org/macaroons-cookies-with-contextual-caveats-for-decentralized-authorization-in-the-cloud/) 134- [libmacaroons](https://github.com/rescrv/libmacaroons) 135- [Ruby-Macaroons](https://github.com/localmed/ruby-macaroons) 136- [libnacl](https://github.com/saltstack/libnacl) 137 138