Message Signatures

The Grafbase Gateway can sign subgraph HTTP requests following RFC 9421.

This can be enabled globally:

[gateway.message_signatures] enabled = true key.file = "key.json"

Or only for a single subgraph:

[subgraphs.products.message_signatures] enabled = true key.file = "products-key.json"

All options documented on this page can be provided globally or for a specific subgraph. If an option is not provided for a subgraph it will inherit from the global configuration.

A key file should be provided in the config. This key file should be one of:

  1. A JSON file containing a JWK.
  2. A PEM file containing a PKCS#8 private key.

A key ID will be included as a signature parameter when signing. If possible this ID will be determined from the provided key file, but it can also be provided with the key.id field:

[gateway.message_signatures] enabled = true key.file = "key.json" key.id = "my-key"

We'll choose which algorithm to use based on the key file provided, but a specific algoithm can be provided in the algorithm field:

[gateway.message_signatures] enabled = true key.file = "key.json" algorithm = "ed25519"

The available algorithms are:

  • hmac-sha256
  • ed25519
  • ecdsa-p256-sha256
  • ecdsa-p384-sha384

If the provided key & algorithm don't match the gateway will refuse to start.

The algorithm you use for singing can have an impact on the latency of your subgraph requests. The list above is in performance order, from most performant to least performant. We recommend testing your chosen algorithm & settings if this is a concern - a message signing span will be output in tracing that can be used to determine the impact of your settings.

The Grafbase Gateway allows you to control which parts of a subgrah request are used as input to message signing. There are several settings for this:

  • The headers key can control which headers are included or excluded. It has two sub-keys:
    1. include should be a list of headers to include in the signature. If not present, all headers will be included.
    2. exclude should be a list of headers to exclude from the signature. This setting takes precedence over include
  • The derived_components key allows you to control which "derived components" are included. This defaults to ["request_target"]. The following options are available:
    • method the HTTP method.
    • target_uri the full URL of the request
    • authority the hostname of the requests target URL
    • scheme the scheme of the requests target URL
    • request_target the request target of the request.
    • path the absolute path of the request URL
  • The signature_parameters key is a list of additional signature parameters to include. It currently only has one setting:
    • nonce can be provided to include a random nonce in every requests signature.
  • expiry can be set to a duration string. (e.g. "30s" for 30 seconds). If provided, signatures will expire after this duration.

Here is an example of these settings:

[gateway.message_signatures] headers.include = ["content-type", "content-length"] derived_components = ["method", "target_uri"] expiry = "10s" [subgraphs.product.message_signatures] headers.exclude = ["content-type"] signature_parameters = ["nonce"] expiry = "5m"