Skip to content
Connect2id

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 architects explains the principles and operation of the OpenID Federation 1.0 metadata policy language and how to apply it.

1. Application protocols rely on entity metadata

When a federation is formed it is to establish a trust framework for its participants. The participants can then safely transact with one another, using one or more agreed-upon 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 on the OIDC4VC/VP specs.

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 1.0 enables an entity to publish metadata about itself in its configuration, at the
/.well-known/openid-federation URL, so that other federation participants can readily obtain the metadata, as part of the trust chain resolution. The metadata is explicitly typed, 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" : "Space Launcher 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?

When a policy the published entity metadata becomes necessary this usually boils down to 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 request 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 architects 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 are not necessary 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 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 policy language of OpenID Federation 1.0 has a simple expressive syntax that is entirely JSON-based. Trust anchors and intermediate entities can seamlessly embed metadata policies in the subordinate statements that they issue. The policy syntax can be parsed with a regular JSON library, no special parser is required.

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

  1. Hierarchy

    Trust anchors and intermediate entities can define metadata policies for their subordinate statements. Once a policy is defined, a subordinate intermediate cannot override it, repeal it 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.

    Trust anchors and intermediate entities have the choice to define policies that apply to all their subordinate entities, or only to specific subjects.

  4. Operation

    A policy is 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 are in line the principles

  5. Integral metadata enforcement

    The resolution and application of metadata policies occurs 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 with entity metadata that does not comply with the resolved policies is also automatically deemed invalid.

  6. Determinism

    This principle guarantees that when a trust anchor or an intermediate entity formulates a policy, it has 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
{}
 
 
{
  "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 appends one or more values to a metadata parameter that is a 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
{}
 
{
  "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: 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
{}
 
{}
 

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
{}
 
{}
 
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

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
{
  "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" ]
}
{}
 
 
 
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
{
  "response_types" :
    [ "code", "token" ]
}
{
  "response_types" :
    [ "code" ]
}
B
{
  "response_types" :
    [ "token" ]
}
INVALID METADATA
 
 
 
C
{}
 
INVALID METADATA
 

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
{
  "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