Skip to content
Connect2id

OpenID Federation policy guide

How can metadata policies ensure protocol and API interoperability between federated entities such as applications, services and devices? How can a federation enforce a common security profile? This guide for federation architects explains the purpose, principles and operators of the OpenID Federation metadata policy language.

1. Application protocols rely on entity metadata

Forming a federation establishes a trust framework for its participants. They can then interact using one or more agreed protocols. In a federation for user authentication and single sign-on (SSO), the protocol can be OpenID Connect. In a federation of verifiable credential (VC) issuers, wallets and verifiers, the protocols can be based the OID4VCI and OID4VP specifications.

Protocols often require certain knowledge about the other entity 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 enables an entity to publish metadata about itself in its configuration, at a /.well-known/openid-federation endpoint. Other federation participants obtain and validate this metadata while resolving a trust chain. Metadata is grouped by entity type; for example, openid_relying_party identifies OpenID Relying Party metadata. An entity can publish metadata for several roles at once, such as both an OpenID Provider and a Relying Party.

Example metadata for an OpenID relying party:

{
  "metadata" : {
    "openid_relying_party" : {
      "redirect_uris" : [ "https://rp.example.com/cb" ],
      "client_name" : "TeamFlow 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"
    }
  }
}

What are the typical purposes of entity metadata?

  • Enable the discovery of protocol 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 are metadata policies needed?

Policies for published entity metadata are generally needed for 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 support a compatible client authentication method. Otherwise, a token request can fail because the client uses a method the provider does not support.

  • 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.

Metadata policies are not a substitute for validating metadata syntax and semantics. Each operator accepts specific JSON types and produces a policy error for unsupported types, but the application layer must still validate the resolved metadata according to the specification that defines each parameter.

Metadata policies are not necessary when the following is true:

  • The metadata is minimal, has no optional parameters, or otherwise cannot express configurations that are incompatible within the federation.

  • The application protocol or layer can itself enforce all interoperability or security requirements of the federation.

Future protocols that are intended for use by entities in OpenID compliant federations may be designed with a strategy to require little or no special metadata policies.

3. Principles of the policy language

The OpenID Federation policy language has a compact, expressive, JSON-based syntax. Trust anchors and intermediate entities place metadata policies in the subordinate statements they issue. A regular JSON parser can parse the data structure, but the implementing software must implement the policy operators, their permitted combinations and merge rules, and the required order in which multiple operators are applied to a metadata parameter.

The policy language in OpenID Federation was designed around 6 principles:

  1. Hierarchy

    Trust anchors and intermediate entities can define metadata policies for their subordinate entities. Once a policy is defined, a subordinate intermediate cannot override it, repeal it or make it more permissive.

    The principle of policy hierarchy is preserved in nested federations where a trust anchor in one federation may act as an intermediate entity in another.

  2. Equal opportunity

    Intermediate entities are given the opportunity to define their own policies, as long as they do not clash with the policies of superior entities. An intermediate can for instance define a more restrictive policy, or a new policy for a metadata parameter that isn’t already controlled by superior entities.

  3. Specificity and granularity

    Policies are expressed at the level of individual metadata parameters, for example token_endpoint_auth_method, and collected into an object for a given entity type, for example openid_relying_party. This ensures the policies for different entity types are independent and isolated from one another. This rule applies also to the individual metadata parameters for an entity type.

    Because each policy is carried in a subordinate statement issued for a particular subject, an authority can issue a common policy for all its immediate subordinates or a different policy for a particular subordinate.

  4. Operation

    A policy is a check, a modification, or a combination of both on a given metadata parameter.

    OpenID Federation specifies 7 standard operators. A federation may define and use additional operators, provided they comply with these principles and the rules for additional operators. Unknown custom operators are ignored unless listed in metadata_policy_crit.

  5. Integral metadata enforcement

    The resolution and application of metadata policies occur as part of the trust chain resolution.

    • A trust chain which has conflicting policies, for example a policy of an intermediate entity clashing with a trust anchor’s policy, is deemed invalid.

    • A trust chain whose subject metadata does not comply with the resolved metadata policy is also deemed invalid.

  6. Determinism

    Policy resolution and application are deterministic, giving trust anchors and intermediates predictable and reproducible outcomes.

4. Policy structure and processing

A metadata policy is carried in the metadata_policy claim of a Subordinate Statement and has three levels: entity type, metadata parameter and operator. For example:

{
  "metadata_policy" : {
    "openid_relying_party" : {
      "id_token_signed_response_alg" : {
        "default" : "ES256",
        "one_of" : [ "ES256", "ES384", "ES512" ]
      }
    }
  }
}

Processing has two distinct stages:

  1. Resolve the policy. Starting with the subordinate statement issued by the trust anchor, merge the policies down the trust chain. Each operator defines how two occurrences of that operator are merged. A conflict or a disallowed operator combination is a policy error and invalidates the trust chain.

  2. Apply the resolved policy. First apply any metadata supplied by the subject’s immediate superior to the metadata from the subject’s entity configuration. Then apply the resolved policy operators in their defined order. If application produces a policy error or invalid resolved metadata, the trust chain is invalid.

The standard operator order is value, add, default, one_of, subset_of, superset_of, then essential. The order matters when several operators are combined for one parameter.

5. Operators

OpenID Federation 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 string, number, boolean, array, null string, number, boolean, array
add v array of strings (1) array of strings (1)
default v string, number, boolean, array string, number, boolean, array
one_of v array of strings (1) string (2)
subset_of v v array of strings (1) array of strings (1)
superset_of v v array of strings (1) array of strings (1)
essential v boolean string, number, boolean, object, array

Legend:

  • The table lists the JSON types that implementations are required to support. Some operators allow implementations to support other JSON types in addition to the mandatory listed above.
  • (1) Implementations may also support array of objects, array of numbers.
  • (2) Implementations may also support object, number.

When the same operator occurs in policies at multiple levels of a trust chain, its values are merged as follows:

  • value and default: the values must be equal.
  • add and superset_of: take the union.
  • one_of and subset_of: take the intersection. An empty one_of intersection is a policy error; an empty subset_of intersection is allowed.
  • essential: apply logical OR, so an essential parameter cannot become voluntary lower in the hierarchy.

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
{}
 
 
{
  "require_auth_time" : true
}
B
{
  "require_auth_time" : false
}
{
  "require_auth_time" : true
}

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
{}
 
{}
 
B
{
  "initiate_login_uri" : "https://example.com/login"
}
{}
 
 

Policy operator: add

The add operator adds one or more values to a metadata parameter that is a JSON array. Values already present are not added again. If the parameter is absent, it is initialised with the operator value.

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
{}
 
{
  "contacts" : [ "admin@example.com" ]
}
B
{
  "contacts" : [ "support@example.com" ]
}
 
{
  "contacts" : [ "support@example.com",
                 "admin@example.com" ]
}

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
{}
 
 
 
{
  "contacts" : [ "admin@example.com",
                 "webmaster@example.com" ]
}
B
{
  "contacts" : [ "alice@example.com" ]
}
 
 
{
  "contacts" : [ "alice@example.com",
                 "admin@example.com",
                 "webmaster@example.com" ]
}

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
{}
 
 
 
{
  "id_token_signed_response_alg" :
    "RS256"
}
B
{
  "id_token_signed_response_alg" :
    "ES256"
}
{
  "id_token_signed_response_alg" :
    "ES256"
}

Policy operator: one_of

The one_of operator ensures that a metadata parameter, when present, is set to one of the permitted values. By itself, it does not require the parameter to be present; combine it with essential: true to do that.

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
{}
 
{}
 
B
{
  "userinfo_signed_response_alg" :
    "PS256"
}
{
  "userinfo_signed_response_alg" :
    "PS256"
}
C
{
  "userinfo_signed_response_alg" :
    "RS256"
}
INVALID METADATA
 
 
 

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
{}
 
INVALID METADATA
 
B
{
  "id_token_signed_response_alg" :
    "PS256"
}
{
  "id_token_signed_response_alg" :
    "PS256"
}
C
{
  "id_token_signed_response_alg" :
    "RS256"
}
INVALID METADATA
 
 
 

Policy operator: subset_of

When a JSON-array metadata parameter is present, the subset_of operator replaces it with the intersection of its current values and the operator’s values. The result can be an empty array. An empty array is still a present parameter, so essential: true does not turn an empty intersection into an error. If the parameter is absent, subset_of has no effect; essential determines whether that absence is allowed.

Scenario 1

Example policy that, when an RP specifies response types, retains only the permitted code and code id_token values.

{
  "response_types" : {
    "subset_of" : [ "code", "code id_token" ]
  }
}
Input metadata Output metadata
A
{
  "response_types" :
    [ "code" ]
}
{
  "response_types" :
    [ "code" ]
}
B
{
  "response_types" :
    [ "code", "code id_token" ]
}
{
  "response_types" :
    [ "code", "code id_token" ]
}
C
{
  "response_types" :
    [ "code", "token" ]
}
{
  "response_types" :
    [ "code" ]
}
D
{
  "response_types" :
    [ "token" ]
}
{
  "response_types" : []
}
 
E
{}
 
{}
 

Scenario 2

Example policy requiring RPs to specify response_types and retaining only the permitted code and code id_token values. A present empty array still satisfies essential; use superset_of as well if at least one particular value must be present.

{
  "response_types" : {
    "essential" : true,
    "subset_of" : [ "code", "code id_token" ]
  }
}
Input metadata Output metadata
A
{
  "response_types" :
    [ "code", "token" ]
}
{
  "response_types" :
    [ "code" ]
}
B
{
  "response_types" :
    [ "token" ]
}
{
  "response_types" : []
}
 
C
{}
 
INVALID METADATA
 

Policy operator: superset_of

The superset_of operator checks that a JSON-array metadata parameter, when present, contains every value specified by the operator. Equality counts as a superset. By itself, the operator does not require the parameter to be present.

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
{
  "grant_types" :
    [ "authorization_code" ]
}
{
  "grant_types" :
    [ "authorization_code" ]
}
B
{
  "grant_types" :
    [ "authorization_code",
      "refresh_token" ]
}
{
  "grant_types" :
    [ "authorization_code",
      "refresh_token" ]
}
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
{
  "grant_types" :
    [ "authorization_code" ]
}
{
  "grant_types" :
    [ "authorization_code" ]
}
B
{
  "grant_types" :
    [ "authorization_code",
      "refresh_token" ]
}
{
  "grant_types" :
    [ "authorization_code",
      "refresh_token" ]
}
C
{}
 
 
INVALID METADATA
 

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
{
  "client_name" : "My Payments App"
}
{
  "client_name" : "My Payments App"
}
B
{}
 
INVALID METADATA
 

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
{
  "client_name" : "My Payments App"
}
{
  "client_name" : "My Payments App"
}
B
{}
 
{}