OpenID Federation policy guide
How to design metadata policies for protocol and API interoperability between federated entities, such as applications, services or devices? How to enforce a common security profile in a federation? This guide for federation operators explains the principles and operation of the OpenID Federation 1.0 metadata policy language and how to apply it effectively.
1. The purpose of entity metadata
When a federation is formed it is to a create a network of trust for its participants. The participants can then safely do business with one another, using one or more agreed-upon protocols. In a federation set up to authenticate users the protocol can be OpenID Connect. In a federation of verifiable credential (VC) issuers, wallets and verifiers the protocols can be based on the OIDC4VC/VP specs.
A protocol may require certain data about the other entity to be known prior to the transaction. For example, in OpenID Connect the identity provider needs to know at a minimum the redirection URI of the relying party in order to handle a login request from it.
To this end OpenID Federation 1.0 enables an entity
to publish metadata about itself in its entity configuration, so that other
federation participants can readily obtain it, as part of the trust chain
resolution. The metadata is published under an entity type identifier, for
example openid_relying_party
for OpenID relying party metadata. This
guarantees the type safety of metadata and enables entities to potentially
have multiple distinct protocol identities.
Example metadata for an OpenID relying party:
{
"metadata" : {
"openid_relying_party" : {
"redirect_uris" : [ "https://rp.example.com/cb" ],
"client_name" : "XYZ app",
"logo_uri" : "https://rp.example.com/logo.png",
"signed_jwks_uri" : "https://rp.example.com/jwks.jwt",
"token_endpoint_auth_method" : "private_key_jwt",
"token_endpoint_auth_signing_alg" : "RS256"
}
}
}
Here are some commonly occurring purposes of entity metadata:
-
Enable the discovery of protocol specific endpoints. In OpenID Connect this can be the
redirect_uri
of the relying party, or the keys, authorisation and token endpoints of the identity provider. -
List supported cryptography algorithms. In OpenID Connect this can include the JWS algorithm for JWT-based client authentication.
-
Configure UIs. In OpenID Connect this can be the client name and logo to display on the login screen.
-
Identify supported protocol extensions. In OpenID Connect this can be extensions such as Identity Assurance / eKYC.
2. When should metadata be policed?
When policing of the published entity metadata becomes necessary this usually boils down to these two reasons:
-
To ensure interoperability between entities at the protocol level – When the metadata contains optional parameters or must be configured in a certain way to ensure all entities can successfully interop with one another. In OpenID Connect an example of this is that both providers and relying parties must publish support for the same method(s) of client authentication. If that isn’t observed a login requests may fail due to the client using an inappropriate authentication method.
-
To enforce a security profile – When the protocol and its metadata support varying levels of security and all entities in the federation must comply with a certain profile. In OpenID Connect this could for instance be a requirement to support a FAPI security profile.
Federation designers may feel tempted to use the policy facility to enforce type checks on the JSON values of metadata parameters. This is an antipattern, federation policies should not be concerned with such checks. Tney should be done by the application layer, which receives the resolved metadata as a JSON object to parse into an internal application specific representation.
Metadata policies may not be needed when the following is true:
-
The metadata is minimal, has no optional parameters or generally doesn’t allow metadata instances with incompatible interoperability to be specified.
-
The application protocol / layer is capable on its own to enforce any interoperability or security requirements of the federation.
Future protocols that are designed for use by entities in OpenID compliant federations may be devised so that the metadata requires little or no special policies.
3. Principles of the policy language
In the previous section we learned that OpenID Federation 1.0 enables operators to define policies for metadata published by entities.
The policy language has a simple expressive syntax that is entirely JSON based. This means metadata policies can be seamlessly embedded in subordinate statements issued by trust anchors and intermediate entities. No special parsing is needed to parse the policy syntax, this can be done with the help of regular JSON libraries.
The policy language in OpenID Federation 1.0 was designed around 6 principles:
-
Hierarchy
Trust anchors and intermediate entities can define policies in the subordinate statements they issue. Once defined, a policy cannot be overridden, repealed or made more permissive by intermediate entities that are subordinate in the trust chain.
The hierarchy of policies is preserved in nested multilateral federations where a trust anchor in one federation may act as an intermediate entity in another.
-
Specificity
Just like metadata, the policies are entity-type specific. The policies for different entity types, for example OpenID providers on one hand and OpenID relying parties on the other, are thus cleanly and reliably isolated from one another.
When a trust anchor or an intermediate entity publishes a policy, it applies to all descendant entities in the trust chain. Because the place to define a policy is the subordinate statement, and every statement is issued for a specific subject, a federation authority can choose to define a common policy for all its subordinates (and their descendants), or specific policies for specific subordinates.
-
Granularity
Policies are expressed at the level of individual metadata parameters. The policies for a given metadata parameter are thus independent and isolated from those for other parameters.
-
Operation
A policy operates by performing a check, a modification, or a combination of both on a given metadata parameter.
OpenID Federation 1.0 specifies 7 standard operators. A federation may define and use additional custom operators, provided they don’t break the general principles of policy.
-
Integral metadata policing
The resolution and application of metadata policies is an integral part of the trust chain resolution process.
This means:
-
A trust chain with entity metadata that does not comply with the resolved policies is automatically deemed invalid.
-
A trust chain which policy resolution fails due to an error, for example due to an intermediate entity’s policy clashing with a superior’s policy, is deemed invalid too.
-
-
Determinism
The resolution and application of metadata policies in a trust chain is deterministic. This means trust anchors and intermediate entities are able to formulate policies that exhibit predictable and reproducible outcomes.
4. Operators
OpenID Federation 1.0 defines 7 operators for validating and shaping entity metadata in a trust chain.
Policy operator | Purpose | JSON type | ||
---|---|---|---|---|
Modifier | Check | Policy operator | Metadata parameter | |
value | v | x | any | any |
add | v | x | any | JSON array |
default | v | x | any | any |
essential | x | v | true, false | any |
one_of | x | v | JSON array (1) | any |
subset_of | v | v | JSON array | JSON array |
superset_of | v | v | JSON array | JSON array |
Legend:
- “any” means any JSON value type per RFC 8259, section 3.
- (1) the JSON array must not be empty
Policy operator: value
The value
operator sets or overrides a metadata parameter.
Scenario 1
Example policy to ensure RPs will be registered to receive ID tokens with the
auth_time
claim, by setting the require_auth_time
metadata parameter to
true
.
{
"require_auth_time" : {
"value" : true
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
Scenario 2
Example policy to ensure RPs cannot register a 3rd party login initiation URL,
by removing any initiate_login_uri
metadata parameter.
{
"initiate_login_uri" : {
"value" : null
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
Policy operator: add
The add
operator appends one or more values to a metadata parameter of type
JSON array.
Scenario 1
Example policy by an intermediate federation entity that adds the email address
of its administrator to the contacts
metadata parameter of subordinate RPs.
{
"contacts" : {
"add" : "admin@example.com"
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
Scenario 2
Example policy that adds two email addresses to the contacts
metadata
parameter of subordinate RPs.
{
"contacts" : {
"add" : [ "admin@example.com", "webmaster@example.com" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
Policy operator: default
The default
operator specifies a parameter when it’s absent in the metadata.
Scenario 1
Example policy that sets the ID token JWS algorithm to RS256
for RPs that
don’t specify an algorithm in their metadata.
{
"id_token_signed_response_alg" : {
"default" : "RS256"
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
Policy operator: essential
When true
the essential
operator requires a metadata parameter to be
present. When false
the metadata parameter is voluntary and
may be absent. The essential
operator has a default value false
(voluntary). Entity metadata that is missing an essential parameter is
considered invalid.
Scenario 1
Example policy that requires RPs to provide a client_name
metadata parameter.
{
"client_name" : {
"essential" : true
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
Scenario 2
Example RP policy that marks the client_name
metadata parameter as voluntary.
This is the same as omitting essential
.
{
"client_name" : {
"essential" : false
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
Policy operator: one_of
The one_of
operator ensures a metadata parameter that is present and not
null
is set to a whitelisted value.
Scenario 1
Example policy to ensure that when RPs choose to register for signed UserInfo
responses the JWS algorithm must be either PS256
or ES256
.
{
"userinfo_signed_response_alg" : {
"one_of" : [ "PS256", "ES256" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
Scenario 2
Example policy that requires RPs to register either for the PS256
or the
ES256
ID token JWS algorithm. The metadata parameter is marked essential and
hence RPs must always specify it.
{
"id_token_signed_response_alg" : {
"essential" : true,
"one_of" : [ "PS256", "ES256" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
Policy operator: subset_of
The subset_of
operator computes the intersection between a specified JSON
array of values and a metadata parameter (also a JSON array) that is present:
- If the resulting intersection is non-empty the metadata parameter becomes the intersection.
- If the resulting intersection is empty the outcome depends on whether the
metadata parameter is essential:
- If the parameter is essential, the metadata is considered invalid.
- If the parameter is voluntary it is removed from the metadata.
Scenario 1
Example policy to ensure that when RPs choose to specify a set of response
types they must include the code
and / or code id_token
values.
{
"response_types" : {
"subset_of" : [ "code", "code id_token" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
C |
|
|
D |
|
|
E |
|
Scenario 2
Example policy requiring RPs to register for a set of response types that
includes the code
and / or code id_token
values. The metadata parameter is
marked essential and RPs must always specify it.
{
"response_types" : {
"essential" : true,
"subset_of" : [ "code", "code id_token" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
C |
|
Policy operator: superset_of
The superset_of
operator ensures a metadata parameter (JSON array) that is
present includes a specified set of values.
Scenario 1
Example policy requiring RPs that choose to specify a set of grant types to
include at least the authorization_code
type.
{
"grant_types" : {
"superset_of" : [ "authorization_code" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
C |
|
|
Scenario 2
Example policy requiring RPs to register for a set of grant types that include
at least the authorization_code type
. The metadata parameter is marked
essential and RPs must always specify it.
{
"grant_types" : {
"essential" : true,
"superset_of" : [ "authorization_code" ]
}
}
Input metadata | Output metadata | |
---|---|---|
A |
|
|
B |
|
|
C |
{} |
|