Macaroons as Access and Refresh Tokens
Macaroons are a type of bearer token that can be used when issuing OAuth 2.0 access and refresh tokens. They can be used in place of regular access or refresh tokens, as they allow the sharing of a single token with multiple clients and resource servers without compromising security.
The idea behind it is that, rather than issuing multiple access tokens with different scopes for a set of clients, AM issues a macaroon access token with a broad scope to a client. The client then creates as many macaroons as needed from the single macaroon access token, restricting their scopes as required by using caveats. This is very useful, for example, in a microservice architecture where a single client can delegate tasks to other services, with a limited set of capabilities or bound by certain restrictions.
Caveats are restrictions placed on a macaroon that must be satisfied before using the token. Meaning, for example, that if the expiry time is past, the token is invalid.
Caveats that can be satisfied locally are referred to as first-party caveats, and caveats satisfied by a service external from AM are referred to as third-party caveats. Support for third-party caveats and discharge macaroons in AM is evolving.
Third-party caveats are those that require the client to use a service other than AM to get proof that the condition specified by the caveat is satisfied. They are useful in situations where you have services external to AM that can make additional authorization checks relevant to the access token.
For example, consider a case where you have a service external to AM, akin to an IDP in a SAML v2.0 architecture, that you can query to know if the user related to the access token belongs to a particular user group.
The proof that the condition is satisfied is returned by the third party in a discharge macaroon, and the client must present both the access token macaroon and the discharge macaroon to get access to the resource.
The discharge macaroon can also have first-party caveats attached to it, such as expiry time. This allows for flows where the access token macaroon is long-lived and the discharge macaroon is not, which forces the client to acquire a new discharge macaroon to access the resource.
Any first-party caveats attached to the discharge macaroons will be treated as if they were caveats on the access token itself. For example, if the discharge macaroon limits the expiry time to five minutes, the introspection response will list the expiry time of the access token as five minutes even if the access token was valid for longer.
Another possible use case is related to transactional authorization. Consider a case where a payment is tied to a unique transaction; you could create a macaroon access token containing a third-party caveat that requires 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 for the third-party service to know which condition needs to be checked, and how to recover the discharge key.
There is no standard format for the identifier part.
There is no standard format for caveats in Macaroons, so AM has adopted a JSON-based syntax that mirrors the existing JWT-based token restrictions:
Restricts the scope of the token. The returned scope will be the intersection of the original token scope 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 added to the token. If you have appended more than one
expcaveat, the most restrictive one applies.
Binds the access token to a client certificate. This means that a client can be issued with a regular access token and then can later bind it to their client certificate. You can only bind one client certificate to the macaroon. Any attempt to bind a new certificate with subsequent caveats is ignored.
Restricts the audience of the token. The effective audience is the intersection of any audience restriction and any
AM returns any other caveats in a
caveats object on the JSON introspection response.
OpenID Connect clients must ensure that the following information is present in the JSON:
openidscope. For example,
"scopes": ["profile", "openid"].
id_tokenresponse type. For example,
"response_types": ["code", "id_token code"].
Appending Caveats to Macaroons
You append caveats to a macaroon through a macaroon library of your choosing. AM provides the
/json/token/macaroon endpoint to add first-party caveats to a macaroon. You can also use this endpoint to inspect the caveats already appended.
You can also add caveats to the macaroon before AM issues it using access token modification scripts. AM can append third-party caveats by using access token modification scripts only.
Using OAuth 2.0 Endpoints with Macaroons
AM endpoints that support access tokens also support macaroons without further configuration. Endpoints will reject macaroons whose caveats are not satisfied.
When dealing with macaroons containing third-party caveats, use the
X-Discharge-Macaroon header to pass a discharge macaroon.
Macaroons and CTS-Based and Client-Based Tokens
Macaroons are layered on top of the existing CTS-Based OAuth 2.0 tokens and Client-Based OAuth 2.0 tokens. When you enable macaroons, AM will issue one of the following:
CTS-Based Macaroon Tokens: the access token is stored in the CTS, and macaroons are the tokens issued to clients, where the identifier of the Macaroon is the pointer to the access token in the CTS.
Client-Based Macaroon Tokens: the access token is a signed and/or encrypted JWT, which is then wrapped in a Macaroon. Note that the resulting size of the token may impact your deployment. If client storage is limited, such as when using browser cookies, the token may be too large to store. Token size may also impact network performance.
Follow these steps to enable macaroons in the OAuth 2.0 Provider Service:
In the AM console, go to Realms > Realm Name > Services > OAuth2 Provider.
On the Core tab, enable Use Macaroon Access and Refresh Tokens.
On the Advanced tab, select the Macaroon Token Format.
It is recommended that you use the default
V2. Configuring Macaroons to use the older token format
V1is much less efficient. It should only be used when compatibility with older Macaroon libaries is required.
Set the OAuth2 Token Signing Algorithm to
HS256, or higher.
Save your changes.
Ensure that the
am.services.oauth2.jwt.authenticity.signingsecret ID is mapped either in the realm, or globally. AM uses this secret ID mapping to sign and verify macaroon access and refresh tokens.
For information about secret stores, see "Configuring Secret Stores".