Request Signing

This page explains in detail how Authentication is done against your integration:

  • Explanation of the Request Signing process
  • The Manifold libraries supporting request verification
  • The Manifold Request signing Algorithm
  • Request verification guidelines
  • The Manifold Public Key

In order to provision, deprovision, or resize resources and credentials Manifold performs HTTP calls against the Provider's API implemented by your integration. All requests sent by Manifold are signed, allowing a Provider to validate that the requests were made by Manifold.

The signature of the request is relayed in the X-Signature header. This header contains the signature of the request, the public key of the ed25519 keypair used to sign the request, and the signature of this public key signed by the Manifold master offline signing key.

This provides a complete chain of trust from the signature of the request all the way to the root signing key allowing a Provider to verify the integrity and authenticity of the request from Manifold.

Included in the signature is the request method, path, query parameters, various headers (including the Date and Host headers), and the request body.

Requests to GET /v1/sso are not signed by Manifold. Instead, integrations must validate that the user has access to the resource by requesting GET /v1/resources/:id from the Connector API using an authorization_code granted access token.

Authentication libraries

Manifold provides the following SDKs, making it easy for a Provider to verify any incoming requests from Manifold:

LanguageSupportURL
GoManifoldhttps://github.com/manifoldco/go-signature
Node.jsManifoldhttps://github.com/manifoldco/node-signature
PythonManifoldhttps://github.com/manifoldco/python-manifoldco-signature
RubyManifoldhttps://github.com/manifoldco/ruby-manifoldco-signature
JavaManifoldhttps://github.com/manifoldco/java-signature
C#Manifoldhttps://github.com/manifoldco/csharp-signature
ElixirManifoldhttps://github.com/manifoldco/elixir-manifoldco-signature
PHPCommunityhttps://github.com/Ziggeo/manifold-php-signature

Are we missing your language? Do you want us to list your library here? Please contact us.

The Request Signing Process

Manifold takes two steps to sign all outgoing requests to Provider's integrations:

  • Create the canonical form of the request.
  • Sign the request.

Create the Canonical Form of the Request

1. Begin by writing the target of the signature

lower(METHOD) < space > PATH <'?'> canonical(QUERY)<newline>

Where canonical(QUERY) contains the query parameters, lexicographically sorted in ascending order (including param name, = sign, and value), and delimited by an &. If no query params are set, the ? after the PATH is omitted.

Example:

put /v1/resources?foo=bar\n

2. Add all headers

These are the headers listed in the X-Signed-Headers header, in the order they are listed, followed by the X-Signed-Headers header itself.

Headers are written in the form:

lower(NAME) <colon> <space> VALUES <newline>

Where VALUES have all optional whitespace removed. If the header occurs multiple times on the request, the values are included delimited by , (comma space), in the order they appear on the request.

The X-Signed-Headers header includes the list of all headers included in the canonical request form, lowercased, and delimited by a space. Only one occurrence of X-Signed-Headers should exist on a request. If more than one exists, The first is used.

Manifold includes all headers that are explicitly set on any request we send, including the callback related headers.

Example:

content-type: application/json\n

3. Finally, add the request body to the canonical request form

Append the bytes from the request into the canonical form.

Sign the request

The request signature is created by creating an ed25519 signature of the canonical request form, using a live signing key pair. This key pair's public key is signed by Manifold's offline master key, and the master key signature is included with each signature.

The signature is included in the X-Signature header, which has the form:

X-Signature: <request_signature> <live_public_key> <master_key_signature>

Verifying a Request

Verifying a request follows similar steps to signing a request:

  • Verify the request age.
  • Create the canonical form of the request. This is identical to the request signing step.
  • Verify the signature.

Verify the Request Age

To prevent replay attacks, all providers should verify that value relayed within the Date (RFC3339 Format) header is within 5 minutes of the current time. If it is not, a 401 error should be returned to the caller.

Create the canonical form of the request

Refer to the request signing step above on how to do this.

Verify the Signature

To verify a request signature, first verify that the signature of the public key included in the header is valid and signed by Manifold's offline signing key. Then verify that the signature of the request is a valid signature on the canonical form of the request, and that it was signed by the public key included in the X-Signature header.

Public Master Key

The following is the public key used for generating endorsements encoded in base64.

PtISNzqQmQPBxNlUw3CdxsWczXbIwyExxlkRqZ7E690

This key is already included in Manifold's signature checking SDKs.

The Manifold master key was generated using a high quality entropy source on an air-gapped system. Access to the private portion of the key is restricted; 3 of the 5 members of Manifold that have access to it must be present to unencrypt the key (portions of the key are distributed to each member through Shamir's Secret Sharing and uniquely encrypted for each member). The master key is only used to sign live signing keys, which will in turn be used to sign the requests made to provider's integrations.