Macaroons: sharable tokens
Macaroons are bearer tokens that you use in place of regular OAuth 2.0 access and refresh tokens. They let multiple clients and resource servers share a single token without compromising security.
Coordinating multiple access tokens with different scopes across a set of clients can be complicated.
The idea behind macaroons is to issue a single access token with a broad scope. The client creates as many sharable tokens as needed from the initial token by restricting its scope.
This is useful in a microservice architecture; for example, where a single client delegates tasks to other services that have a limited set of capabilities or are bound by certain restrictions.
To restrict macaroon token scopes, use caveats.
Caveats are restrictions included in the token that must be satisfied when using the token. For example, an expiry time could be set as a caveat. When the expiry time is past, the token is invalid.
Caveats that can be satisfied locally are referred to as first-party caveats. Caveats satisfied by a service external from AM are referred to as third-party caveats.
There is no standard format for caveats in macaroons. AM uses a JSON-based syntax that mirrors the existing JSON Web Token (JWT)-based token restrictions:
Restricts the scope of the token.
The resulting scope is the intersection of the original scopes and any
Restricts the expiry time of the token.
The effective expiry time is the minimum of the original expiry time and any expiry caveats. If you append more than one
expcaveat, the most restrictive one applies.
Binds the access token to a client certificate.
You can only bind one client certificate to a macaroon. AM ignores attempts to bind a new certificate with subsequent caveats.
Restricts the audience of the token.
The effective audience is the intersection of any audience restriction and
AM returns other caveats in a
caveats object in the JSON introspection response.
OpenID Connect clients must ensure the following information is present in the JSON:
Third-party caveats require the client to use a service other than AM to prove they satisfy the condition specified by the caveat. They are useful where services external to AM run authorization checks relevant to the access token.
Consider the case where you have an identity provider service external to AM to query whether the user related to the access token belongs to a particular user group.
Another use case for third-party caveats is transactional authorization, requiring a user to authorize every access to a resource. Consider the case where a payment is tied to a unique transaction. You create a macaroon access token with a third-party caveat requiring the client to obtain a one-time discharge macaroon from an external transactional service.
A third-party caveat has the following parts:
A hint describing where the client can find the third-party service, which is usually a URL.
A unique secret key to sign discharge macaroons, known as the discharge key.
An identifier indicating to the third-party service which condition to check and how to recover the discharge key.
There is no standard format for the identifier.
A third-party service returns proof a condition is satisfied in a discharge macaroon. The client must present both the access token macaroon and the discharge macaroon to access a protected resource.
A discharge macaroon can hold first-party caveats, such as expiry time. This allows for flows where the access token macaroon is long-lived, and the discharge macaroon is not, forcing the client to acquire a new discharge macaroon for each access to a protected resource.
AM treats first-party caveats attached to discharge macaroons like caveats on the access token.
For example, if the discharge macaroon limits the expiry time to five minutes, the introspection response lists the expiry time of the access token as five minutes, even if the access token is valid for longer.
A client appends caveats to a macaroon using a macaroon library. This depends on your client, not AM.
To manage first-party caveats and to inspect the caveats on a macaroon, you can use the /json/token/macaroon endpoint.
AM OAuth 2.0 endpoints that support access tokens also support macaroons without further configuration. AM endpoints reject macaroons whose caveats are not satisfied.
For macaroons with third-party caveats, use the
X-Discharge-Macaroon header to pass discharge macaroons.
AM layers macaroons on top of the existing server-side OAuth 2.0 tokens and client-side OAuth 2.0 tokens. When you enable macaroons, AM issues one of the following:
- Server-side macaroon tokens
AM stores the access token in the CTS and issues macaroons to clients. The macaroon identifier points to the access token in the CTS.
- Client-side macaroon tokens
AM issues signed or encrypted JWTs as access tokens wrapped in a macaroon.
Make sure the resulting token fits in the storage available to the client. If the storage available is limited to the size of a browser cookie, for example, the token may be too large to store. Token size can also impact network performance.
Follow these steps to enable macaroons in the OAuth 2.0 provider service:
In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.
On the Core tab, enable Use Macaroon Access and Refresh Tokens and save your changes.
On the Advanced tab, select the Macaroon Token Format.
If possible, use the default
Macaroons using the older
V1token format are much less efficient. Only use
V1when you require compatibility with older macaroon libraries.
Set the OAuth2 Token Signing Algorithm to
Save your changes.