Preview
Microsoft Microsoft
Microsoft home
  • Documentation
  • Code Samples
Show / Hide Table of Contents

Identity Hub API Reference

Updated: June 2, 2020


Identity hubs expose a set of interfaces for reading and writing data to a DID's personal data store, and for synchronizing that data across all hub instances and devices. The APIs described on this page are part of a proposed standard for identity hub interaction. This allows developers to write their code once and support all identity hubs, regardless of where a DID chooses to run their hub.

Best practices

We recommend you keep the following in mind when programming against identity hubs:

  • Adhere closely to the documented behavior on this page and in hub standards. This ensures that you won't take a dependency on any API behavior that may not be supported by other identity hub providers the user may use.
  • Use DIF's identity hub client library/SDK if possible. The library abstracts away much of the complexity of identity hubs, and exposes a simple set of methods.
  • Do not assume all identity hub services will offer similar performance levels or uptime. Your apps and services should be prepared to handle identity hubs that are offline or responding slowly. Once again, using DIF's client libraries will help in this capacity.
  • Be prepared for breaking changes. At this time, identity hubs and client libraries are in early stage development. You should be prepared for APIs to change or be deprecated without notice.

Endpoint Discovery

The first step in using an identity hub is locating its DID and URL. If you are exclusively using Microsoft's identity hub cloud service, you can use the values listed immediately below. Alternatively, you can follow the endpoint discovery process outlined in our tutorial, which uses the InterfaceMap object below.

Microsoft specific values

Currently the Microsoft identity hub cloud service uses the following parameters:

DID:

did:test:hub.id

URL:

https://beta.personal.hub.microsoft.com

InterfaceMap

The InterfaceMap is a mechanism for describing the endpoints of an identity hub service in detail:

{
    "@context": "https://schema.identity.foundation/1.0/hub",
    "@type": "IdentityHubConfiguration",
    "endpoints": [{
        "@context": "http://schema.identity.foundation/1.0/hub",
        "@type": "InterfaceMap",
        "interfaces": {
            "Collections": "https://hub.azure.com/Collections",
            "Profile": "https://www.foo.com/.identity/Profile",
            "Actions": "https://id.bar.org/.identity/Actions",
            ...
        }
    },
    {
        "@context": "http://schema.identity.foundation/1.4/hub",
        "@type": "InterfaceMap",
        "interfaces": {
            "Collections": "https://hub.azure.com/Collections",
            "Profile": "https://www.foo.com/whatever-path/Profile",
            "Actions": "https://id.bar.org/.identity/Actions",
            ...
        }
    }],
    "signature": {
        "kid": "did:btcs:456#key-1",
        "value": "jv9323lavjsdav0d9ada2...",
        "timestamp": "2018-10-24T18:39:10.10:00Z"
    }
}

Hub implementations using the InterfaceMap can choose to use a single URL for all interfaces they support, or may have different URLs for each. The format of each interface URL is not specified in this document.

Commits

Commits are the fundamental data type in identity hub's data model. Each object in hubs is represented as a series of commits.

Data Formats & Encodings

At this time, the only data format supported by hubs is JSON objects. JSON objects are encapsulated into JWSs and JWEs as described in the authentication section. Images, videos, streams, and other MIME types are not currently supported.

Commit

A commit is a JSON web token (JWT) that is signed by the author. The structure of an example commit is presented below:

// Each commit is a JWT using Flattened JSON serialization.
// The JWT contents are displayed below in decoded form.
{
  "protected": {
      "alg": "RS256",
      "kid": "did:example:abc123#key-abc",
      "interface": "Collections",
      "context": "http://schema.org",
      "type": "MusicPlaylist",
      "operation": "update",
      "committed_at": "2018-10-24T18:39:10.10:00Z",
      "object_id": "3a9de008f526d239...",
      "commit_strategy": "basic",
      "sub": "did:example:abc123",
  },

  "header": {
      "rev": "fe4fd3240ff1c68a...",
      "iss": "did:example:123456"
  },

  "payload": {
      "@context": "http://identity.foundation",
      "@type": "MusicPlaylist",
      "@id": "foo",
      "name": "A modified playlist",
      "tracks": []
  },

  "signature": "j3irpj90af992l..."
}

The JWT payload is the commit contents. The header values must be the following:

Header Description
alg Standard JWT header. Indicates the algorithm used to sign the JWT.
kid Standard JWT header. The value should take the form {did}#{key-id}. Another app can take this value, resolve the DID, and find the indicated public key that can be used for signature validation of the commit.
interface Must be one of Collections, Profile, Actions, or Permissions.
context The context of the object. This, along with type, indicates the type of object that is being created.
type The type of the object. This, along with context, indicates the type of object that is being created.
operation Must be one of create, update, or delete.
committed_at The time at which the commit is taking place.
commit_strategy Must be basic. See the hub overview for more details.
sub The DID of the user whose hub is being accessed; in other words, the hub owner's DID.
object_id The unique ID of the object this commit pertains to. The object ID value for an object is the rev of the commit that creates the object.
header.rev The unique ID for this commit, which can be constructed by taking the SHA-256 hash of the protected and payload values of the commit concatenated by a . character.
header.iss The DID of the issuer of the commit. Must match the DID used in the kid property of the commit protected headers.

Basic Requests & Responses

WriteRequest

A WriteRequest is used for submitting new commits to hubs. This includes creating, updating, and deleting data.

{
    "@context": "https://schema.identity.foundation/0.1",
    "@type": "WriteRequest",
    "iss": "did:example:123456",
    "aud": "did:example:some-hub",
    "sub": "did:example:abc123",
    "commit": <Commit>
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be WriteRequest.
iss Issuer. The DID of the party sending the request. The keys for this DID will be used to encrypt responses from the hub.
aud Audience. The DID of the hub receiving the request. We got this DID during the hub endpoint discovery step above. The keys for this DID will be used to encrypt requests to the hub.
sub Subject. The DID of the user who owns the hub where the data will be stored.
commit A commit, in JWS Flattened JSON Serialization format. This is an alternative representation of a JWT. It can be easily constructed by splitting the parts (header, body, signature) of a conventional compact serialized JWT and placing them in the relevant properties (protected, payload, signature). An additional header property may also be specified, but is not protected by the signature.

WriteResponse

A WriteResponse is returned in the event of a successful write.

{
    "@context": "https://schema.identity.foundation/0.1",
    "@type": "WriteResponse",
    "developer_message": "completely optional",
    "revisions": ["3a9de008f526d239..."]
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be WriteResponse.
revisions An array of rev values, each of which represents a commit for the object that has been modified.

ObjectQueryRequest

An ObjectQueryRequest can be used to look up objects of a certain type in a hub.

{
  "@context": "https://schema.identity.foundation/0.1",
  "@type": "ObjectQueryRequest",
  "iss": "did:example:123456",
  "aud": "did:example:some-hub",
  "sub": "did:example:abc123",
  "query": {
      "interface": "Collections",
      "context": "http://schema.org",
      "type": "MusicPlaylist",
      "object_id": ["3a9de008f526d239..", "a8f3e7..."]
  }
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be ObjectQueryRequest.
iss Issuer. The DID of the party sending the request. The keys for this DID will be used to encrypt responses from the hub.
aud Audience. The DID of the hub receiving the request. The keys for this DID will be used to encrypt requests to the hub.
sub Subject. The DID of the user who owns the hub where the data will be stored.
query.interface One of Collections, Actions, Permissions, or Profile. Collections is most commonly used for data storage.
query.context This value, along with type, indicates the type of object that is being queried for.
query.type This value, along with context, indicates the type of object that is being queried for.
query.object_id This optional value can be provided if the query should be restricted to one or more known objects, instead of all objects of the provided type.

ObjectQueryResponse

An ObjectQueryResponse is returned after a successful ObjectQueryRequest.

{
    "@context": "https://schema.identity.foundation/0.1",
    "@type": "ObjectQueryResponse",
    "developer_message": "completely optional",
    "objects": [
        {
            "interface": "Collections",
            "context": "http://schema.org",
            "type": "MusicPlaylist",
            "id": "3a9de008f526d239...",
            "created_by": "did:example:abc123",
            "created_at": "2018-10-24T18:39:10.10:00Z",
            "sub": "did:example:abc123",
            "commit_strategy": "basic",
        },
    ]
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be ObjectQueryResponse.
objects[i].interface The hub interface where the object was retreived from.
objects[i].context This value, along with type, indicates the type of the object.
objects[i].type This value, along with context, indicates the type of the object.
objects[i].id The unique object_id for this object. The object_id for an object is the commit id (rev) of the commit that initally created the object.
objects[i].created_by The DID of the party that created the object.
objects[i].created_at The time at which the object was initally created.
objects[i].sub The DID that owns the object.
objects[i].commit_strategy Must be basic. See the hub overview for more details.

CommitQueryRequest

A CommitQueryRequest returns the details of commits for particular objects.

{
  "@context": "https://schema.identity.foundation/0.1",
  "@type": "CommitQueryRequest",
  "iss": "did:example:123456",
  "aud": "did:example:some-hub",
  "sub": "did:example:abc123",
  "query": {
      "object_id": ["3a9de008f526d239..."],
  }
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be CommitQueryRequest.
iss Issuer. The DID of the party sending the request. The keys for this DID will be used to encrypt responses from the hub.
aud Audience. The DID of the hub receiving the request. The keys for this DID will be used to encrypt requests to the hub.
sub Subject. The DID of the user who owns the hub where the data will be stored.
query.object_id The object_id of the object whose commits we want to read.

CommitQueryResponse

A CommitQueryResponse is returned after a successful CommitQueryRequest.

{
    "@context": "https://schema.identity.foundation/0.1",
    "@type": "CommitQueryResponse",
    "developer_message": "completely optional",
    "commits": [<Commit>]
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be CommitQueryResponse.
commits An array of commits, in JSON serialized JWT format, that modify the object. The format of each commit is described in the above sections.

ErrorResponse

An ErrorResponse may be returned in response to any of the requests above.

{
    "@context": "https://schema.identity.foundation/0.1",
    "@type": "ErrorResponse",
    "error_code": "ABC123",
    "developer_message": "An error has occurred."
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be ErrorResponse.
error_code A unique error code that describes the error and can be handled by application code. See below section for details.
developer_message A helpful message to developers to assist in debugging.

Error Codes

The following values may be returned in the error_code field for hub responses.

Error Code Description
bad_request The request could not be completed because it was malformed. Cases include:
- the request JWE could not be decrypted
- the response JWE could not encrypted
- a required property was missing
- an invalid value was provided in request
authentication_failed The client could not be authenticated, because the request JWS could not be verified using the DID keys of the DID provided in the iss property.
permissions_required The request is denied because the DID in the iss field has not be granted sufficient permission to perform the operation.
not_found The resource requested could not be found in the hub.
too_many_requests The client is being throttled, and should wait before retrying any requests.
server_error An unexpected or unhandled error occurred on the hub.
not_implemented The operation requested includes a standard hub feature that is not supported by this implementation of the hub.
service_unavailable The hub service is temporarily not available and requests should not be retried.
temporarily_unavailable The hub service experienced a transient error and the request should be retried at a later time.

Paging

In a successful ObjectQueryResponse or CommitQueryResponse, the results returned may exceed the allowable size limit for responses. In these cases, the results can be paged using a skip_token.

{
    "@context": "https://schema.identity.foundation/0.1",
    "@type": "ObjectQueryResponse",
    "objects": [
        {
            "context": "http://schema.org",
            "type": "MusicPlaylist",
            "id": "3a9de008f526d239...",
            "created_at": "2018-10-24T18:39:10.10:00Z",
            "sub": "did:example:abc123",
            "commit_strategy": "basic",
        },
        ...
    ],
    "skip_token": "ajfl43241nnn1p;u9390",
}

To use a skip_token key value to get additional results, re-submit your original query with the skip_token key and key value in the query property.

If a response does not contain a skip_token, then there are no more results for the client to fetch from the hub. Due to filtering performed in the Hub, it's possible that you may receive one or more responses which contains no results, however this does not necessarily indicate that no more results are available. Your app should continue to query until no skip_token is returned.

A read request to a hub's collection interface that uses the skip_token property:

Request
{
  "@context": "https://schema.identity.foundation/0.1",
  "@type": "ObjectQueryRequest",
  "iss": "did:example:123456",
  "aud": "did:example:some-hub",
  "sub": "did:example:abc123",
  "interface": "Collections",
  "query": {
      "context": "http://schema.org",
      "type": "MusicPlaylist",
      "skip_token": "ajfl43241nnn1p;u9390"
  }
}

Authentication

All requests and responses above are encoded into a JWE format that is both signed and encrypted by the sender using the DID keys of the hub and the client. This allows the hub to authenticate the client and secure any messages exchanged. For details on creating JWEs, please refer to our tutorial.

Authorization

By rule, the DID that owns an identity hub always has full access to read, modify, write, and delete any and all data in the hub. The owner DID can create PermissionGrant objects in their hub that grant other DIDs the ability to access data.

PermissionGrant

{
  "@context": "https://identity.foundation/0.1",
  "@type": "PermissionGrant",
  "owner": "did:example:12345",
  "grantee": "did:example:67890",
  "context": "https://schema.org",
  "type": "MusicPlaylist",
  "allow": "CRUD", 
}
Property Description
@context Must be https://schema.identity.foundation/0.1.
@type Must be ErrorResponse.
owner The DID that owns the data and the hub.
grantee The DID that access is being granted to.
context The type of data that is being accessed.
type The type of data that is being accessed.
allow Allows Create C, Read R, Update U, and Delete D.

HTTP Requests

Once hub requests and responses have been constructed and encapsulated in a JWE, they must be sent to the identity hub service over HTTP. A request must use the POST method with the following values:

POST / HTTP/1.1
Host: beta.personal.hub.microsoft.com
Content-Type: application/jwt
Content-Length: 1283

eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ...

Responses are returned as JWEs as well. Hubs usually use a status code of 200, but may use other 2** error code values to indicate success. If a 2** status code is returned, the response body must contain a properly formed JWE. Note that a 200 does not necessarily indicate a successful hub request; the JWE returned may still contain an error response inside.

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2018 12:28:53 GMT
Content-Length: 501
Content-Type: application/jwt
Connection: Closed

eyJraWQiOiJkaWQ6dGVzdDpodWIuaWJrR...

A JWE cannot be returned, however, in the following cases:

  • if the client's DID public keys cannot be resolved.
  • if the client's request was improperly encrypted, so the client's DID is unknown.
  • if the client's request was improperly signed, so the client could not be authenticated.
  • if a server error occurred while retrieving keys or encrypting the JWE response.
  • if the client and hub do not support the same signing or encryption algorithms.
  • if the client is being throttled by a reverse proxy/load balancer/gateway.

In these cases, the HTTP response is returned with an error status and a JSON formatted response containing additional information. If there was a problem with the client's request, or any problem fetching or using the client's DID keys:

HTTP/1.1 400 Bad Request
Date: Mon, 27 Jul 2018 12:28:53 GMT
Content-Length: 124
Content-Type: application/json
Connection: Closed

{
    "error_code": "ABC123",
    "developer_message": "Unable to verify signature of JWE in request",
}

If the server encountered an error during JWE parsing or construction:

HTTP/1.1 500 Server Error
Date: Mon, 27 Jul 2018 12:28:53 GMT
Content-Length: 124
Content-Type: application/json
Connection: Closed

{
    "error_code": "ABC123",
    "developer_message": "Temporary server error", 
}

If the server is throttling the client due to too many requests:

HTTP/1.1 429 Too Many Requests
Date: Mon, 27 Jul 2018 12:28:53 GMT
Content-Length: 124
Content-Type: application/json
Retry-After: 120
Connection: Closed

{
    "error_code": "ABC123",
    "developer_message": "Too many requests",
}

Hubs may also use other 4** and 5** status codes to indicate client and server error responses, respectively.




See something missing? We'd love your feedback and input on the Verifiable Credentials preview. Please contact us. When you use Microsoft DID Services, you agree to the DID Preview Agreement and the Microsoft Privacy Statement.

In This Article
  • Contact us
  • Terms of use
  • Privacy statement
  • © Microsoft 2018