Origo Integration

Keep Api Integration with Origo
keepapi integrations

Summary

KeepAPI exposes new endpoints / resources and extensions to the existing data model to facilitate integration with the HID Mobile Access Credentials product, Origo. Currently all access to the is through the API, with future plans to incorporate the Origo integration into the Windows and Web Client user interfaces.

Licensing

Origo Integration is a licensable feature. An example license request would be:

{
                    "Environment": "DEV",
                    "InstanceKey": "{{ WorkingInstance.Key }}",
                    "LicensedBy": {
                        "CompanyName": "Feenics Inc",
                        "EmailAddress": "ralph.shillington@feenics.com",
                        "MailingAddress": {
                            "Street": "301 - 2310 St. Laurent Blvd",
                            "City": "Ottawa",
                            "Province": "ON",
                            "Country": "CA",
                            "PostalCode": "K1G 5H9"
                        },
                        "PhoneNumber": "613-520-2455"
                    },
                    "Licensee": {
                        "CompanyName": "Feenics Inc - Development",
                        "EmailAddress": "ralph.shillington@feenics.co",
                        "MailingAddress": {
                            "Street": "302 - 2310 St. Laurent Blvd",
                            "City": "Ottawa",
                            "Province": "ON",
                            "Country": "CA",
                            "PostalCode": "K1C 5J9"
                        },
                        "PhoneNumber": "613-520-2426"
                    },
                    "PurchaseOrder": "RALPH",
                    "RequestingComponents": [
                        {
                            "PrivateProductCode": "ORIGO",
                            "ValueAdded": 1
                        }
                    ]
                }

Permissions

Users that will be configuring the Origo integration must have the OrigoAdmin action attached to the Instance object type. Of course administrators with *,* permissions will automatically have this permission.

Configuration

Configuration can be set or updated by with POST method to the endpoint /api/origo/configuration The currently stored configuration can not be retrieved by the API user since it contains sensitive information. Subsequent POST methods will replace the existing configuration.

Setting the Configuration, will automatically register the instance to receive callback messages.

Response Condition Description
401 NotAuthorized failed to find and operation right for the current user with action of OrigoAdmin on the object type Instance
409 Conflict Missing license for this instance.
400 BadRequest Failed to log into Origo with the supplied credentials
400 BadRequest Failed to register the callback endpoint with Origo
200 Ok Configuration has been saved, and the callback endpoint has been registered with Origo

Example setting configuration

In this example, the keepcli tool is used to maintain credentials to the KeepApi endpoint. The example configures the default defined instance. The example posts the contents of the file origoconfig.json

INSTANCE=$(keepcli test -j)
BASEADDRESS=$(echo $INSTANCE | jq -r .BaseAddress)
TOKEN=$(echo $INSTANCE | jq -r .Token)

curl -v -X POST -d @origoconfig.json -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" ${BASEADDRESS}/api/origo/configuration

The contents of the configuration information is obtained from HID by the customer’s administrator using the HID Origo portal. It’s important to note that the user may have access to both a pre-production and production HID portal

{
    "CustomerId":"1000582",
    "ClientId":"1000582-SRV1620440120",
    "ClientSecret":"password_goes_here",
    "GrantType":"client_credentials",
    "DefaultPartNumber":"MID-SUB-CRD_FTPN_30176"
}

Confirm Origo Customer

The Api exposes a new endpoint to get the Origo Customer information for the configured CustomerId: /api/origo/customer. The following script gets the customer information

INSTANCE=$(keepcli test -j)
BASEADDRESS=$(echo $INSTANCE | jq -r .BaseAddress)
TOKEN=$(echo $INSTANCE | jq -r .Token)
curl -s -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" ${BASEADDRESS}/api/origo/customer | json_pp
{
   "Name" : "FEENICS-TP-D_SUB",
   "Id" : "1000582",
   "SubscriptionMode" : "Full term subscription",
   "pendingInvitations" : 0,
   "TotalUsers" : 18,
   "$type" : "Feenics.Keep.Origo.Customer, Feenics.Keep.WebApi.Model",
   "urn:hid:scim:api:ma:2.0:LicenseInfo" : [
      {
         "ConsumedQty" : 0,
         "AvailableQty" : 100,
         "StartDate" : "2019-05-27T00:00:00Z",
         "PartNumber" : "MID-SUB-T100",
         "LicenseState" : "Good Standing",
         "StatusMessage" : "Good Standing",
         "PeriodState" : "Normal",
         "EndDate" : "2020-05-26T00:00:00Z",
         "Name" : "T100 Subscription",
         "$type" : "Feenics.Keep.Origo.License, Feenics.Keep.WebApi.Model"
      }
   ],
   "MobileKeysets" : "MOB0001, MOB0022",
   "ActiveUsers" : 0
}

Normal Operation

Once properly configured, the normal operation of the integration is largely ‘behind the scenes’. There is only one additional Origo specific endpoint that has been added to the PersonInfo resource: /origo/issue.

To issue a mobile credential a cardholder must already exist in the Keep instance. In the case of a Enterprise instances, the card holder may exist in either the root instance, or the shared instance.

Internally the processing of issuing a mobile credential involves several steps: 1. Confirm the cardholder exists as an Origo user, and if not, then add the user 2. Create an invitation code, send invitation email, and create credential (all one call to Origo) 3. Wait for an ISSUED status callback for the requested credential 4. Create the CardAssignmentInfo object and attach it to the PersonInfo object in Keep.

The ISSUED status will be sent from Origo to Keep (via the preconfigured endpoint that was provisioned at the time of setting the Origo Configuration). This call only occurs after the mobile device has successfully downloaded the credential. It is the callback handler that creates the CardAssignmentInfo object attaches it to the PersonInfo and raises the appropriate event, such that the Mercury Service pushes the Mobile Credential card number to the appropriate controllers.

Example of issuing a new mobile credential

In this example keepcli is being used to provide authentication to the Keep api, using it’s default configuration. A search by moniker is executed for a specific person, and a POST to /origo/issue on Person is called, sending the requested activeOn and expiresOn values (UTC).

In a separate window use keepcli to subscribe to events, to observe the mobile credential being issued.

keepcli subscribe | jq '{d:.PublishedOn."$date"| (. / 1000 | todate),m:.MessageLong,et:.ObjectLinks[] | select(.Relation=="PublishingEventType")|.CommonN
ame,bd:.EventData.BeforeData, ad:.EventData.AfterData}'

With the event subscriber running, issue a new mobile credential.

#!/bin/bash

INSTANCE=$(keepcli test -j)
BASEADDRESS=$(echo $INSTANCE | jq -r .BaseAddress)
TOKEN=$(echo $INSTANCE | jq -r .Token)

BODY='{"activeOn":"2019-09-04T:00:00.0000000+00:00","expiresOn":"2019-09-04T07:00:00.0000000+00:00"}'
PERSON=$(keepcli search -s '{"Monikers":{"$elemMatch":{"Nickname":"ralshi", "Namespace":"feenicsdev.people"}}}' | jq -r .Href)
echo ${BASEADDRESS}${PERSON}/origo/issue

echo ${BODY}

curl -v -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" -d ${BODY} ${BASEADDRESS}${PERSON}/origo/issue

Currently it is possible that the issue request will fail with an HTTPStatus of 400 and a response body of:

{
  "$type": "Feenics.Keep.WebApi.ErrorResponse, WebApi",
  "Error": "OrigoOperation",
  "Message": "Failed to get send invite. Status=InternalServerError response: {\"schemas\":[\"urn:hid:scim:api:ma:2.0:Error\"],\"detail\":\"We are unable to continue with your request, due to technical difficulty with Subscription Service. Please try again or contact your support.\",\"status\":500}"
}

This is a known issue with HID Origo, and occurs occasionally when issuing both a new user request immediately followed by a new invitation request. In this circumstance it’s OK to retry the request. On the second call the user will exist in Origo and the new invitation email and invitation code will be sent to the user.

When the user accepts the invitation and receives the credential on the mobile device, Origo will send an ISSUED event to the registered Keep endpoint for the instance and a credential will be issued, which can be observed in the window that is subscribing to events.

{
  "d": "2019-09-04T23:57:10Z",
  "m": "Shillington, Ralph card 24 modified by System Administrator. Action POST",
  "et": "Object Modified",
  "bd": null,
  "ad": {
    "_t": [
      "Item",
      "CardAssignmentInfo"
    ],
    "Href": "/api/f/5d52b8b453b83b0001f25361/people/10436012/cards/5d704f562bc5040001225f80",
    "Key": "5d704f562bc5040001225f80",
    "EncodedCardNumber": 24,
    "DisplayCardNumber": "24",
    "ActiveOn": {
      "$date": 1567486800000
    },
    "ExpiresOn": {
      "$date": 1567494000000
    },
    "PinCode": null,
    "AntiPassbackExempt": false,
    "ExtendedAccess": false,
    "PinExempt": false,
    "IsDisabled": false,
    "ManagerLevel": 0,
    "OriginalUseCount": null,
    "CurrentUseCount": 0,
    "Note": null,
    "HexValue": null,
    "RecordId": 6,
    "LastUsed": null,
    "OrigoCredentialId": 10436012
  }
}

Note the OrigoCredentialId property that is available both in the EventData.AfterData property of the EventMessageData and is also present on the CardAssignment entry for the new mobile credential. This non-zero value is the indicator that the credential is a mobile credential.

Example of revoking a Mobile Credential

In this example, simply setting the expired on value to something less than DateTime.UtcNow on the mobile credential will trigger a call to Origo by the KeepAPI to revoke the credential.

INSTANCE=$(keepcli test -j)
BASEADDRESS=$(echo $INSTANCE | jq -r .BaseAddress)
TOKEN=$(echo $INSTANCE | jq -r .Token)
CARDURL=$(keepcli search -s '{"Monikers":{"$elemMatch":{"Nickname":"ralshi", "Namespace":"feenicsdev.people"}}}' | jq -r .CardAssignments[0].Href)

echo ${BASEADDRESS}${CARDURL}
curl -s -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" ${BASEADDRESS}${CARDURL} | jq '.ExpiresOn=.ActiveOn' | \
curl -v -X PUT -H 'Content-Type: application/json' -H 'Accept: application/json' -H "Authorization: Bearer ${TOKEN}" -d @- ${BASEADDRESS}${CARDURL} | jq .

This sample script assumes the first member of the CardAssignments array for the selected person is a mobile credential. Using the card assignment URL, the first cUrl command retrieves the CardAssignmentInfo details, and uses jq to set the ExpiresOn field to the same value as the ActiveOn value (effectively making the card revoked.)

Observe in the event subscriber window the updated CardAssignmentInfo object, immediately followed by an Origo Command Sent event, which instructs Origo to revoke the mobile credential.

{
  "d": "2019-09-05T00:16:42Z",
  "m": "Shillington, Ralph modified by System Administrator. Action PUT",
  "et": "Object Modified",
  "bd": {
    "_t": [
      "Item",
      "CardAssignmentInfo"
    ],
    "Href": "/api/f/5d6eac48c198dc0001664425/people/5d704ec62bc5040001225f6c/cards/5d704f562bc5040001225f80",
    "Key": "5d704f562bc5040001225f80",
    "EncodedCardNumber": 24,
    "DisplayCardNumber": "24",
    "ActiveOn": {
      "$date": 1567486800000
    },
    "ExpiresOn": {
      "$date": 1567494000000
    },
    "PinCode": null,
    "AntiPassbackExempt": false,
    "ExtendedAccess": false,
    "PinExempt": false,
    "IsDisabled": false,
    "ManagerLevel": 0,
    "OriginalUseCount": null,
    "CurrentUseCount": 0,
    "Note": null,
    "HexValue": null,
    "RecordId": 6,
    "LastUsed": null,
    "OrigoCredentialId": 10436012
  },
  "ad": {
    "_t": [
      "Item",
      "CardAssignmentInfo"
    ],
    "Href": "/api/f/5d6eac48c198dc0001664425/people/5d704ec62bc5040001225f6c/cards/5d704f562bc5040001225f80",
    "Key": "5d704f562bc5040001225f80",
    "EncodedCardNumber": 24,
    "DisplayCardNumber": "24",
    "ActiveOn": {
      "$date": 1567486800000
    },
    "ExpiresOn": {
      "$date": 1567486800000
    },
    "PinCode": null,
    "AntiPassbackExempt": false,
    "ExtendedAccess": false,
    "PinExempt": false,
    "IsDisabled": false,
    "ManagerLevel": 0,
    "OriginalUseCount": null,
    "CurrentUseCount": 0,
    "Note": null,
    "HexValue": null,
    "RecordId": 6,
    "LastUsed": null,
    "OrigoCredentialId": 10436012
  }
}
{
  "d": "2019-09-05T00:16:43Z",
  "m": "Origo Command Sent",
  "et": "Origo Command Sent",
  "bd": null,
  "ad": null
}

Manually installing the full Keep by Feenics Stack

September 9, 2019
keepapi