localmed/ruby-macaroons — pull request #13 by ecordell (2014-10-17 20:17:24+00:00)
Title: Adds compatibility with python library

Also see: https://github.com/ecordell/pymacaroons/pull/1

Had to make some changes to both libraries, but now you can generate macaroons and discharges in one library and read them in the other.

Generate in Ruby and verify in Python:

```ruby
m = Macaroon.new(
'http://mybank/',
'we used our other secret key',
'this is a different super-secret key; never use the same secret twice'
)
m.add_first_party_caveat('account = 3735928559')
caveat_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/')

discharge = Macaroon.new(
'http://auth.mybank/',
identifier,
caveat_key
)
discharge.add_first_party_caveat('time < 2015-01-01T00:00')
protected_discharge = m.prepare_for_request(discharge)

m.serialize()
=> "MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMmNpZGVudGlmaWVyIHdlIHVzZWQgb3VyIG90aGVyIHNlY3JldCBrZXkKMDAxZGNpZCBhY2NvdW50ID0gMzczNTkyODU1OQowMDMwY2lkIHRoaXMgd2FzIGhvdyB3ZSByZW1pbmQgYXV0aCBvZiBrZXkvcHJlZAowMDY5dmlkIGxHWnlCWHplRFlyMWdpSFYwOWtPeSs1SDFUdGxwV202R3pFYVY4QXlHOTl2bGh0bDN1UjNNckxWUGVWU29SSEdmR0poaDRjZGN6Q2pYYXVnNWVIcFpEVUtCYXRxUTdnMQowMDFiY2wgaHR0cDovL2F1dGgubXliYW5rLwowMDJmc2lnbmF0dXJlIHQawqL-dMf0dfeJwD0M0UsR_KlR1m1ZLTadvJAFWBZRCg=="
protected_discharge.serialize()
=> "MDAyMWxvY2F0aW9uIGh0dHA6Ly9hdXRoLm15YmFuay8KMDAzN2lkZW50aWZpZXIgdGhpcyB3YXMgaG93IHdlIHJlbWluZCBhdXRoIG9mIGtleS9wcmVkCjAwMjBjaWQgdGltZSA8IDIwMTUtMDEtMDFUMDA6MDAKMDAyZnNpZ25hdHVyZSCPazw874VoYSzr3gDTNlPv1vxOUnYKl6suorfffqmLEAo="
```

```python
from macaroons.macaroon import Macaroon
from macaroons.verifier import Verifier
m = Macaroon.from_binary("MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMmNpZGVudGlmaWVyIHdlIHVzZWQgb3VyIG90aGVyIHNlY3JldCBrZXkKMDAxZGNpZCBhY2NvdW50ID0gMzczNTkyODU1OQowMDMwY2lkIHRoaXMgd2FzIGhvdyB3ZSByZW1pbmQgYXV0aCBvZiBrZXkvcHJlZAowMDY5dmlkIGxHWnlCWHplRFlyMWdpSFYwOWtPeSs1SDFUdGxwV202R3pFYVY4QXlHOTl2bGh0bDN1UjNNckxWUGVWU29SSEdmR0poaDRjZGN6Q2pYYXVnNWVIcFpEVUtCYXRxUTdnMQowMDFiY2wgaHR0cDovL2F1dGgubXliYW5rLwowMDJmc2lnbmF0dXJlIHQawqL-dMf0dfeJwD0M0UsR_KlR1m1ZLTadvJAFWBZRCg==")
protected = Macaroon.from_binary("MDAyMWxvY2F0aW9uIGh0dHA6Ly9hdXRoLm15YmFuay8KMDAzN2lkZW50aWZpZXIgdGhpcyB3YXMgaG93IHdlIHJlbWluZCBhdXRoIG9mIGtleS9wcmVkCjAwMjBjaWQgdGltZSA8IDIwMTUtMDEtMDFUMDA6MDAKMDAyZnNpZ25hdHVyZSCPazw874VoYSzr3gDTNlPv1vxOUnYKl6suorfffqmLEAo=")
v = Verifier()
v.satisfy_exact('account = 3735928559')
v.satisfy_exact('time < 2015-01-01T00:00')
verified = v.verify(
m,
'this is a different super-secret key; never use the same secret twice',
discharge_macaroons=[protected]
)
>>>verified
True
```

Generate in Python and Verify in Ruby:

```python
from macaroons.macaroon import Macaroon
m = Macaroon(
location='http://mybank/',
identifier='we used our other secret key',
key='this is a different super-secret key; \
never use the same secret twice'
)
m.add_first_party_caveat('account = 3735928559')
caveat_key = '4; guaranteed random by a fair toss of the dice'
predicate = 'user = Alice'
identifier = 'this was how we remind auth of key/pred'
m.add_third_party_caveat('http://auth.mybank/', caveat_key, identifier)

discharge = Macaroon(
location='http://auth.mybank/',
key=caveat_key,
identifier=identifier
)
discharge.add_first_party_caveat('time < 2015-01-01T00:00')
protected = m.prepare_for_request(discharge)

>>> m.serialize()
'MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMmNpZGVudGlmaWVyIHdlIHVzZWQgb3VyIG90aGVyIHNlY3JldCBrZXkKMDAxZGNpZCBhY2NvdW50ID0gMzczNTkyODU1OQowMDMwY2lkIHRoaXMgd2FzIGhvdyB3ZSByZW1pbmQgYXV0aCBvZiBrZXkvcHJlZAowMDY5dmlkIENCc2p4NWRWU25seVgzclQybVV1WENtRE12Tm8wNFhiV1JiaVI0dVl1U2Fpa3dCWmNKYmJONS9oSWFaQ2xoODE5UERpWUV5eHhtQml6Z2drak1ZbXBkWTRkcStnckJoMgowMDFiY2wgaHR0cDovL2F1dGgubXliYW5rLwowMDJmc2lnbmF0dXJlICwiAemTi6-xXokOUh7dDi7q9AdeUCHo_g_T9-LlYiVfCg=='
>>> protected.serialize()
'MDAyMWxvY2F0aW9uIGh0dHA6Ly9hdXRoLm15YmFuay8KMDAzN2lkZW50aWZpZXIgdGhpcyB3YXMgaG93IHdlIHJlbWluZCBhdXRoIG9mIGtleS9wcmVkCjAwMjBjaWQgdGltZSA8IDIwMTUtMDEtMDFUMDA6MDAKMDAyZnNpZ25hdHVyZSDPOHTRXWgJWj_DlkdvV0thf1EwunfBaxGLQ-03l86spwo='
```

```ruby
m = Macaroon.from_binary("MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMmNpZGVudGlmaWVyIHdlIHVzZWQgb3VyIG90aGVyIHNlY3JldCBrZXkKMDAxZGNpZCBhY2NvdW50ID0gMzczNTkyODU1OQowMDMwY2lkIHRoaXMgd2FzIGhvdyB3ZSByZW1pbmQgYXV0aCBvZiBrZXkvcHJlZAowMDY5dmlkIENCc2p4NWRWU25seVgzclQybVV1WENtRE12Tm8wNFhiV1JiaVI0dVl1U2Fpa3dCWmNKYmJONS9oSWFaQ2xoODE5UERpWUV5eHhtQml6Z2drak1ZbXBkWTRkcStnckJoMgowMDFiY2wgaHR0cDovL2F1dGgubXliYW5rLwowMDJmc2lnbmF0dXJlICwiAemTi6-xXokOUh7dDi7q9AdeUCHo_g_T9-LlYiVfCg==")
protected_discharge = Macaroon.from_binary("MDAyMWxvY2F0aW9uIGh0dHA6Ly9hdXRoLm15YmFuay8KMDAzN2lkZW50aWZpZXIgdGhpcyB3YXMgaG93IHdlIHJlbWluZCBhdXRoIG9mIGtleS9wcmVkCjAwMjBjaWQgdGltZSA8IDIwMTUtMDEtMDFUMDA6MDAKMDAyZnNpZ25hdHVyZSDPOHTRXWgJWj_DlkdvV0thf1EwunfBaxGLQ-03l86spwo=")
v = 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]
)
=> true
```

@petebrowne