Warning

You're reading a development version (main) of the documentation. For the latest released version, please see 1.0.0.

6. Common Security Requirements

Note

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Open Energy defines a security and trust model for shared data APIs. Three parties are involved in each shared data request:

  1. The Data Consumer wishing to access the shared data API

  2. The authorization server, as part of the governance service (OEGS), with knowledge about the Data Consumer as represented by an organisation account within the OEGS

  3. The Data Provider responsible for supplying shared data through its shared data API

The interactions are shown graphically below in the form of a sequence diagram.

../_images/fapi_sequence_diagram.svg

Fig. 6.1 FAPI Sequence Diagram - client credentials flow

6.1. Applicable standards

We use a strict sub-set of the FAPI specification for interactions between Data Providers and Data Consumers. The applicable standards are linked here for reference, we reference the precise elements of these standards in later sections.

6.1.1. Discovery of endpoint URLs

While not strictly necessary, the authorization server deployed as part of the OEGS implements the OpenID Connect Discovery provider configuration information endpoint as described here, references in this document to e.g. token_endpoint refer to properties discoverable in this fashion.

6.2. Token acquisition

In order to access a shared data API, a Data Consumer must first acquire an access token. This is done by sending an HTTP request to the authorization server (part of the OEGS). The Data Consumer MUST:

  • Use Mutual TLS, presenting a client certificate when requested. This is the tls_client_auth authentication method described in section 2 of RFC8705.

    • In our implementation, this certificate is acquired by creating a transport certificate in a software statement within the OEGS directory

  • Use the client_credentials grant type

  • Send a POST request to the token_endpoint of the authorization server containing the following properties as application/x-www-form-urlencoded key / value pairs:

    client_id : <CLIENT_ID>
    scope: <REQUESTED_SCOPES>
    grant_type: client_credentials
    

    Scope may be omitted, for most uses within Open Energy there is no requirement to specify a scope. CLIENT_ID can be obtained from the software statement within the directory corresponding to this client

A successful call to the token_endpoint is indicated by a 200 response code, in which case the body of the response will contain a JSON object with at least two properties:

  1. access_token is an opaque string to be used as a bearer token for requests to resource servers (a Data Consumer shared data API in our context)

  2. expires_in is an integer number of seconds from the current time, after which the token will no longer be valid - after this point the Data Consumer MUST request a new token in order to continue to access shared data resources

6.3. Token usage - calling a shared data API

To call a shared data API within a Data Provider, the Data Consumer MUST:

  • Use Mutual TLS as previously described

  • Pass the previously acquired bearer token in an HTTP header:

    Authorization: Bearer <TOKEN>
    

In addition, the Data Consumer SHOULD:

  • Specify an interaction ID for this call in an HTTP header:

    x-fapi-interaction-id: <UUID>
    

    This allows for tracking of transactions between clients and resource servers, aiding troubleshooting. We use a UUID4 in our reference implementation

6.4. Request validation

To participate in the Open Energy ecosystem, a Data Provider MUST:

  • Expose an HTTPS API

  • Perform validation on any requests to this API

    • Reject any requests which do not present a valid client certificate. Client certificates are validated in the context of the root CAs provided by the OEGS directory.

    • Reject any requests which do not provide an Authorization header containing a Bearer token as described above

If any of the above checks fail, the Data Provider MUST NOT continue processing the request, and SHOULD respond with an error response as defined in this section of RFC6750

6.4.1. Token introspection

If all the above checks pass, the Data Provider MUST then validate the presented token. Tokens in our case are opaque identifiers (as opposed to JWTs) and must be passed to the introspection_endpoint of the authorization server to obtain additional information. To obtain this introspection response, the Data Provider MUST:

  • Make a POST request to the introspection_endpoint of the authorization server

  • Use Mutual TLS, this means Data Providers must also have a provisioned client within the OEGS directory in the form of a software statement and corresponding transport certificate

  • Send the bearer token and client ID of the Data Provider as an application/x-www-form-urlencoded body with the following values:

    token: <BEARER_TOKEN>
    client_id: <CLIENT_ID>
    

6.4.2. Introspection response validation

The response body of this introspection call contains a JSON object with information about the entity which requested the supplied token from the authorization server, as well as properties of the token itself. An example introspection response is shown below:

{
  "active": true,
  "organisation_id": "8",
  "organisation_name": "A Demo Provider",
  "organisation_number": "8",
  "software_roles": [
    "EDSP_L1"
  ],
  "software_description": "Description: https://www.demo.org.uk/ is the location of our demo server",
  "additional_software_metadata": {
    "metadata": {
      "something": "something else"
    }
  },
  "client_id": "kZuAsn7UyZ98Wwh29hDpf",
  "exp": 1626279245,
  "iat": 1626278645,
  "iss": "https://auth.directory.energydata.org.uk",
  "scope": "directory:software",
  "cnf": {
    "x5t#S256": "rP_-9u3ZyVo4ryQxg-bn4rr6gJGNu1dTowEeppOuIt8"
  },
  "token_type": "Bearer"
}

The following elements of the introspection response MUST be validated further before any Open Energy specific processing is performed:

6.4.2.1. active

If the introspection response does not contain the key active, or the value of this key is anything other than the boolean true value, the Data Provider MUST reject the request and cease further processing.

If the active key was not present, it SHOULD respond with 400 invalid_request

If the active key was present but not true it SHOULD respond with 401 invalid_token

6.4.2.2. time ranges

If the introspection response contains iat this is interpreted as a number of seconds since the epoch at which the token was issued. If this is in the future the Data Provider MUST reject the request and cease further processing. It SHOULD respond with a 401 invalid_token.

Note

The Data Provider SHOULD allow for a reasonable degree of clock skew when interpreting the iat timestamp, an allowance of no more than 10 seconds should cover all reasonable cases.

If the introspection response contains exp this is interpreted as a number of seconds since the epoch after which the token should be considered invalid. If this is in the past, the Data Provider MUST reject the request and cease further processing. It SHOULD respond with a 401 invalid_token

6.4.2.3. certificate thumbprint

Open Energy uses certificate pinning combined with MTLS on all requests between Data Consumers and Data Providers. This ensures that a token issued to one client cannot be re-used by another client. Data Providers MUST check that the thumbprint of the presented client certificate matches that provided within the introspection response.

The introspection response contains the SHA256 thumbprint of the certificate used to acquire the token as a nested property ['cnf']['x5t#S256']. This MUST be equal to the SHA256 thumbprint of the client certificate, if this is not the case the Data Provider MUST reject the request and cease any further processing, responding with a 401 invalid_token

6.4.3. Interaction header

If the x-fapi-interaction-id header is set in the request, it MUST be set to the same value in the response header of the same name. If not set, a new ID MUST be generated and set in the response header.

6.4.4. Other validation

If all the above checks have passed, the Data Provider can service the request and return whatever data were requested. It MAY, however, apply additional checks based on information in the introspection response about the client. This is where any Open Energy specific access control and licensing policies are applied.

To inform any additional processing, the Data Provider MAY make use of the ['additional_client_metadata']['metadata'] key within the introspection response. This contains a JSON object with properties asserted about the Data Consumer. The exact set of properties is not defined here, please see the access control language specification for more information about what could be specified.

Data Providers MAY make use of the organisation_id field in the token introspection response to uniquely and consistently identify the organisation of the Data Consumer where required, for example to reference a customer record within the Data Provider.

More information on the Open Energy specific access control language can be found in Access Control and Capability Grant Language, and its expression in the metadata file at Data Set Metadata in the Access Block section.