Intent of the "identifier"

116 views
Skip to first unread message

Neil Madden

unread,
Jan 29, 2019, 5:25:40 AM1/29/19
to Macaroons
Hi all,

I have always thought of the “identifier” part of a Macaroon as being a per-Macaroon unique value, serving the same role as the “jti” claim in a JWT (https://tools.ietf.org/html/rfc7519#section-4.1.7) - i.e., something that is unique to that particular Macaroon and could be used to revoke it, for instance, or enforce one-time usage/anti-replay.

However, reading the README for libmacaroons it says:

<quote>
This public portion, known as the macaroon's identifier, can be anything that
enables us to remember our secret. In this example, we know that the string 'we
used our secret key' always refers to this secret. We could just as easily keep
a database mapping public macaroon identities to private secrets, or encrypt the
public portion using a key known only to us. The only requirement here is that
our application be able to remember the secret given the public portion, and
that no one else is able to guess the secret.
</quote>

This seems to correspond more closely to the “kid” header in JOSE (https://tools.ietf.org/html/rfc7515#section-4.1.4) that is used to identify the signing/encryption key that was used, and will often be the same for many JWTs (e.g., it might identify an RSA key stored in a HSM).

Is the intention that a Macaroon identifier be closer to “jti” or closer to “kid”? Or is the intention that a unique key is used for every Macaroon and so these two cases are identical?

Kind regards,

Neil

Robert Escriva

unread,
Jan 29, 2019, 9:10:04 AM1/29/19
to maca...@googlegroups.com
I think it would help to think about macaroons as macaroons rather than
something that borrows concepts from JOSE or jti.

In macaroons, you are proving authorization by presenting a tree of
macaroons with your request. The macaroons tree can only be verified
by passing in the secret used to first create the macaroon at the root
of the tree. The identifier is a non-secret way to recover that secret.

Server-side, you have some collection of secrets and need some way to
pick which secret should be used for a given request.

Many people have begun using the identifier with public key crypto to
generate these secrets, but that's just one way you could use it.
Others include:

- A key-value store that embeds one secret per key-value pair
- A distributed filesystem that uses macaroons to protect raw storage
on the storage nodes to keep them simple and safe
- Put the secret on an object that represents a user's account.

The general pattern comes down to picking the resource you want to
protect (e.g., kv pairs, storage blocks, users, repositories) and having
one secret per instance of that resource. The identifier then acts as a
way to make sure you fetch the right resource (although in many cases
you could probably ignore the identifier and use the only pertinent
secret available).

-Robert

Neil Madden

unread,
Jan 29, 2019, 9:44:46 AM1/29/19
to Macaroons
Thanks for the response.

From your reply it sounds very much like this corresponds to the purpose of the “kid” (key identifier) header in JOSE, which can be used in many of the same ways that you mentioned. In particular, it sounds like there is no requirement for separately created macaroons for the same resource to have different identifiers, whereas there is for the JWT “jti” claim.

By the way, for your examples of storing secrets in k-v stores, user accounts, etc, aren’t these individual secrets going to have to be themselves encrypted with some master secret?

—Neil
> --
> You received this message because you are subscribed to the Google Groups "Macaroons" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to macaroons+...@googlegroups.com.
> To post to this group, send email to maca...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/macaroons/20190129141303.GA21217%40rave.rescrv.net.
> For more options, visit https://groups.google.com/d/optout.

Tony Arcieri

unread,
Jan 29, 2019, 9:45:08 AM1/29/19
to Macaroons
On Tuesday, January 29, 2019 at 2:25:40 AM UTC-8, Neil Madden wrote:
I have always thought of the “identifier” part of a Macaroon as being a per-Macaroon unique value, serving the same role as the “jti” claim in a JWT (https://tools.ietf.org/html/rfc7519#section-4.1.7) - i.e., something that is unique to that particular Macaroon and could be used to revoke it, for instance, or enforce one-time usage/anti-replay.

The concept of an "identifier" comes from SPKI/SDSI, where it is used to bind a principal (identified by a public key) to a local name.

With Macaroons, it can be any information you want to use to identify that particular credential. The paper generally describes the identifier as consisting solely of a nonce (I generally use a UUIDv4 for this purpose), however when used in conjunction with a structured data format (e.g. protobuf) I see them as being useful for claims about a principal, i.e. non-authority carrying identity information:


This could include the name/ID of a user or service to which the Macaroon was originally issued, which is helpful for debugging purposes. If you're using a Macaroon as a session credential, it could include their "common name" for or email address for display purposes.
 
This seems to correspond more closely to the “kid” header in JOSE (https://tools.ietf.org/html/rfc7515#section-4.1.4) that is used to identify the signing/encryption key that was used, and will often be the same for many JWTs (e.g., it might identify an RSA key stored in a HSM).

In my deployments of Macaroons, I've included a key ID in the Macaroon "identifier" section so as to facilitate key rotation.

roger peppe

unread,
Jan 29, 2019, 1:08:26 PM1/29/19
to maca...@googlegroups.com
The macaroon identifier is the only place in a macaroon that allows you to express a positive statement (as opposed to a caveat condition, which is always negative or neutral).

So we are using macaroon identifiers to encode not just an identifier for the secret, but also information about which capabilities are granted by the macaroon. This works well when you wish to protect something a bit more abstract than a set of entities in a database, because you don't need a database that stores a root key per entity. It can also be used to create macaroons that grant capabilities on more than one thing at once without creating a complex caveat language.

With this approach, you can get away with a very small number of root keys (e.g. one) in a service, but still have fine-grained control over macaroon scope.

I'd be interested to hear others' thoughts on this.

  cheers,
    rog.





--
You received this message because you are subscribed to the Google Groups "Macaroons" group.
To unsubscribe from this group and stop receiving emails from it, send an email to macaroons+...@googlegroups.com.
To post to this group, send email to maca...@googlegroups.com.

Tony Arcieri

unread,
Jan 29, 2019, 2:19:42 PM1/29/19
to maca...@googlegroups.com
On Tue, Jan 29, 2019 at 10:08 AM roger peppe <rogp...@gmail.com> wrote:
The macaroon identifier is the only place in a macaroon that allows you to express a positive statement (as opposed to a caveat condition, which is always negative or neutral).

So we are using macaroon identifiers to encode not just an identifier for the secret, but also information about which capabilities are granted by the macaroon [...]
 
I'd be interested to hear others' thoughts on this.

I think it's a good idea, and use an approach along these lines, encoding an initial set of permissions in a section of the identifier I call "authority". So where "claims" confer identity info, "authority" confers AuthZ.

This allows the caveats to restrict the initial authority set, i.e. "authority" provides an initial permissions whitelist which caveats subtract. If nothing else, this feels more familiar as compared to existing access control systems, translates more naturally to comprehensible error messages, and overall better adheres to the principle of least privilege.

It also helps with extensibility of permission/caveat types: with an explicit authority set it's possible to see which permission types weren't initially specified, and therefore they can be handled according to whatever policy makes sense (e.g. use a default value, fail closed, fail open). This prevent a potential attack where a new caveat type is added, and an attacker holding an existing Macaroon can add a "caveat" which amplifies authority by choosing their desired value for that caveat.

It also strategically prevents Kerberos golden ticket-style attacks (a.k.a. "Golden Macaroons").

--
Tony Arcieri

Jason Axley

unread,
Jul 26, 2019, 11:32:04 AM7/26/19
to Macaroons
One issue I'm seeing with macaroons if you use the identifier to communicate structured data is that it breaks down with third-party caveats -- at least how the implementations seem to match discharge macaroons to the right third-party caveat.  Implementations seem to do an exact byte/string match on the identifier to determine which to use during verification.

This breaks if you want to communicate structured information inside the third-party identifier (e.g. claims about a user identity), then you change the identifier so it doesn't match what the third-party caveat that requested it expects.

Perhaps if implementations had flexibility in the predicate match logic for how you determine which discharge to use (e.g. instead of caveat.id == discharge.id, you could specify to deserialize the data structure and match a kid field inside, e.g. caveat['kid'] == discharge["kid"])

How are you handling this in practice?  Or do you instead just use the first caveat to communicate this information in that case to allow using existing macaroon library implementations as-is?

-Jason
To unsubscribe from this group and stop receiving emails from it, send an email to maca...@googlegroups.com.

Tony Arcieri

unread,
Jul 26, 2019, 11:46:26 AM7/26/19
to maca...@googlegroups.com
The short answer is claims shouldn't be used for AuthZ, but of course it isn't that simple.

I do agree this is a problem with Macaroons and the way caveats are generally structured. In the past I've suggested a separation between "authority", and caveats with subtract from that authority. So instead of redundantly specifying authority in the form of a set union of overlapping claims, they can be expressed as a logical disjunction:


Under such a scheme, any claims potentially used in an access control decision would be part of the authority section.

To unsubscribe from this group and stop receiving emails from it, send an email to macaroons+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/macaroons/0bd380a1-940e-4c85-9e33-d2b5afc9a1d1%40googlegroups.com.


--
Tony Arcieri

Jason Axley

unread,
Jul 26, 2019, 12:43:14 PM7/26/19
to Macaroons
I don't feel that I have a choice but to convey trustworthy identity claims (e.g. user's email, etc.) in the first caveat and just skip that when verifying the macaroons.  Want to have the benefits of trustworthy identity information that can be accessed in a self-contained token along with authorization information without additional network round trips.

Looking forward to the outcome of the Biscuit work!  Seems like it will address these shortcomings quite well.

-Jason
To unsubscribe from this group and stop receiving emails from it, send an email to maca...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/macaroons/0bd380a1-940e-4c85-9e33-d2b5afc9a1d1%40googlegroups.com.


--
Tony Arcieri
Reply all
Reply to author
Forward
0 new messages