Skip to content
Last update: January 26, 2024

Customer Proof

Info

Relevant JSON-RPC method: custodian_getCustomerProof

Customer proof diagram

Why the Customer proof mechanism is needed

Custodians usually provide the ability to create an organisation with multiple different users, wallets and accounts within a wallet tied to the organisation. A user will authenticate the MMI Extension to the custodian using a refresh token more details provided here.

The refresh token is tied to a user who is tied to an organisation. The refresh token also provides authentication and access to one or more accounts. Once a user has imported accounts into the extension see the demo, they can then transact on that account. With MMI, a user can connect to a Dapp, initiate a transaction, confirm that transaction and is then deep-linked into their custodian UI to approve and/or sign transactions. As per the architecture overview, the custodian is required to send a webhook to the MMI backend (MMI API) in order to the extension to receive transaction status updates. To prove that the user is a customer (authenticate the user) and for the correct transaction statuses to be sent to the user that initiated the transaction, we have implemented what we call the customer proof mehcanism.

Transaction updates

How the Customer proof mechanism is implemented

This custodian is required to implement a method in the JSON-RPC API called custodian_getCustomerProof. The mechanism produces cryptographically signed tokens for users which prove that they are a customer.

They must be signed using RSA keys known only to the custodian. The custodian will publish the public part of these keys on a JWKS endpoint.

MMI provides a websocket service which communicates transaction updates to users. The purpose of this token is to allow the extension to contact MMI’s APIs as an authenticated user, without using the custodian’s refresh token.

Customer proof claims

This token should include the following claims, attested by the custodian:

  • sub: The custodian user ID of the user, in any format. This can be in any format, although UUID is common. Any webhooks you send will include the same value as metadata.userId.
  • mmi.customerId : The customer ID of the user. This corresponds to any grouping of users, usually a customer ID or organisation ID. This can be in any format.
  • mmi.customerName: A human readable name for the entity corresponding
  • iss : The issuer of the token. This should be the URL of the custodian’s JSON-RPC API. You must provide this value to us when giving us your API URL as it is used to map tokens to issuers.

Verification

Verification is performed by MMI’s APIs. The custodian must host an endpoint returning a JSON Web Key Set (JWKS) corresponding to the public part of the keys used to sign the above tokens.

Info

We load these keys at the time when we register a custodian. Please let us know if they change, so that we can load a new set.

Customer proof example

Example request from MMI to the custodian API

POST http://custodian-api/eth/v1/json-rpc

Content-type: application/json
Authorization: Bearer custodian-access-token

{
    "method" : "custodian_getCustomerProof"
    "id" : 1,
    "params" : []
    "jsonrpc": "2.0",
}

Example response

{
  "id": 1,
  "jsonrpc": "2.0",
  "result": {
    "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vY3VzdG9kaWFuLWFwaSIsImlhdCI6MTYyODc4MzcyMiwiZXhwIjoxNjYwMzE5NzIyLCJhdWQiOiIiLCJzdWIiOiIxMjM0LTU2NzgiLCJtbWkiOiJ7XCJ2ZXJzaW9uXCI6XCI5LjguNVwifSJ9.yYSUyOAdDzh9ViSrJsJO6vU-cRESzbu4y7wRFblQ4Po"
  }
}

Example response decoded

{
    "iss": "http://custodian-api",
    "iat": 1628783722,
    "exp": 1660319722,
    "aud": "",
    "sub": "1234-5678",
    "mmi": { "customerId": "9999-0000", "customerName": "ACME corporation" }
}

FAQ

What should we use as a customerId claim ?

The customerId claim corresponds to the legal entity that is billed for using the extension, e.g. a customer or fund. If you don’t have a concept of a customer, you can repeat the sub claim.