Follow this step by step procedure to Integrate a Data Source system in Platform of Trust Sandbox and start Harmonized Data Flow in the Platform in less than an hour.
This tutorial is based on a sample connector implemented by Platform of Trust
PREREQUISITE: You should already have a connector hosted to send requests to the desired Data source and fetch responses from it.
Sign up to Platform of Trust Sandbox
via our World app .
Learn more about Sandbox capabilities from our Sandbox developer guide.
Get your Bearer token to start making calls to Platform of Trust APIs in Sandbox.
NOTE: Bearer token
expires in 24 hours. So Make sure to get the regenerated one to continue.
The first step of registering any Data Product or Application in the Platform Sandbox
is to create a Group
identity.
You can also use the World app
to create a Group .
Or you can use the following cURL requests:
curl -i --request POST \
--url https://api-sandbox.oftrust.net/identities/v1 \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiL...RtaWrVlxDG2awTlixI-fnVsfjbkJ1uGXVUnVU' \
--header 'content-type: application/json' \
--data '{
"context": "https://standards.oftrust.net/v2/Context/Identity/Group/",
"type": "Group",
"data": {
"name": "demo-group"
}
}'
On success, you'll receive a similar response:
{
"@context":"https://standards.oftrust.net/v2/Context/Identity/Group/",
"@type":"Group",
"@id":"0db1e898-2184-4eb5-9b9b-4d259c5cb4de",
"data":{
"name":"demo-group"
},
"metadata":{
"createdAt":"2020-05-06T09:52:34+00:00",
"createdBy":"01725951-3bd4-4c6f-875c-df1d07d7120f",
"updatedAt":"2020-05-06T09:52:34+00:00",
"updatedBy":"01725951-3bd4-4c6f-875c-df1d07d7120f"
},
"inLinks":[
],
"outLinks":[
]
}
Make sure to save the group @id
and createdBy
values to use further.
NOTE: In Platform of Trust, every user is an identity
, hence it has an identity ID
. createdBy
is your user's identity ID
.
Lastly, to register an application or create a data product, you need to be memberOf
in a group
. Execute in the same terminal the following:
curl -i --request POST \
--url https://api-sandbox.oftrust.net/identities/v1/{createdBy_id}/link/{group_id} \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...RtaWrVlxDG2awTlixI-fnVsfjbkJ1uGXVUnVU' \
--header 'content-type: application/json' \
--data '{
"context": "https://standards.oftrust.net/v2/Context/Link/Role/MemberOf/",
"type": "MemberOf"
}'
In successful response, you'll receive the link @id
from you user to the created group:
HTTP/1.1 201 Created
date: Wed, 06 May 2020 10:05:01 GMT
server: uvicorn
content-type: application/json
transfer-encoding: chunked
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
{
"@context":"https://standards.oftrust.net/v2/Context/Link/Role/MemberOf/",
"@type":"MemberOf",
"@id":"67e1dfba-7092-43d3-a2bf-54eaa4cba0b1",
"from":"01725951-3bd4-4c6f-875c-df1d07d7120f",
"to":"0db1e898-2184-4eb5-9b9b-4d259c5cb4de",
"data":{
},
"metadata":{
"createdAt":"2020-05-06T10:05:01+00:00",
"createdBy":"01725951-3bd4-4c6f-875c-df1d07d7120f",
"updatedAt":"2020-05-06T10:05:01+00:00",
"updatedBy":"01725951-3bd4-4c6f-875c-df1d07d7120f"
}
}
Now you can use this group to register Application or create Data Products.
NOTE: You can try out our Insomnia REST API workspace to access and test Platform of Trust APIs in Sandbox.
It is always the best practice to draw a demo diagram of the identities you want to create and link.
To create an identity :
curl -i --request POST \
--url https://api-sandbox.oftrust.net/identities/v1 \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9eyJzY29w...DVs5aaf' \
--header 'content-type: application/json' \
--data '{
"context": "https://standards.oftrust.net/v2/Context/Identity/Structure/Building/",
"type": "Building",
"data": {
"name": "Glass building"
}
}'
Here, we have created an ìdentityof type
Building`.
Make sure you correctly define the context
and type
of the identity you want to create. You can find out more about context
s at Platform of Trust Ontology Viewer .
On success, you will receive the id
of the created identity. Make sure to save it for creating links later.
HTTP/1.0 201 Created
{
"@context": "https://standards.oftrust.net/v2/Context/Identity/Structure/Building/",
"@type": "Building",
"@id": "ec2d273b-b866-496e-b682-79b061dbf71f",
"inLinks": [],
"outLinks": [],
"data": {
"name": "Glass building"
},
"metadata": {
"createdAt": "2019-09-11T11:24:23+00:00",
"createdBy": "33237067-e72c-4f26-b78b-9f9e234b2e7d",
"updatedAt": "2019-09-11T11:24:23+00:00",
"updatedBy": "33237067-e72c-4f26-b78b-9f9e234b2e7d"
}
}
Make sure to save the @id
of the identity created as they are required to create links.
To create a link between two existing identities:
curl --request POST \
--url https://api-sandbox.oftrust.net/identities/v1/<INSERT_FROM_IDENTITY_ID>/link/<INSERT_TO_IDENTITY_ID> \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9eyJzY29w...DVs5aa' \
--header 'content-type: application/json' \
--data '{
"context": "https://standards.oftrust.net/v2/Context/Link/BelongsTo/",
"type": "BelongsTo"
}'
You need to carefully select id
of the FROM_IDENTITY
and TO_IDENTITY
in the cURL request. So it is better to define the link directions in the diagram.
You also need to correctly define the context
and type
of the link.
Read more about links
in Platform of Trust Ontology Viewer
On success, you will receive id
of the created link. Make sure to save it for further use.
HTTP/1.0 201 Created
{
"@context": "https://standards.oftrust.net/v1/Context/Link/BelongsTo/",
"@type": "BelongsTo",
"@id": "be7a2c57-03d8-46f4-aaf0-2b1ca118ef5c",
"from": "8ac7494b-b7bc-4a63-a253-4b9b1887b262",
"to": "a6b5a74e-bd98-4c9b-9561-932877258833",
"data": {},
"metadata": {
"createdAt": "2019-09-12T09:49:24+00:00",
"createdBy": "33237067-e72c-4f26-b78b-9f9e234b2e7d",
"updatedAt": "2019-09-12T09:49:24+00:00",
"updatedBy": "33237067-e72c-4f26-b78b-9f9e234b2e7d"
}
}
NOTE: it is important that first, you create two adjacent identities and then link them. Then create the 3rd identity and link it. Continue this process until you have created your desired identity network.
To consume the harmonized data flow from the Platform, you need to register an Application
in the Sandbox
.
You can register an application in Sandbox
by using Application API .
The request format is:
curl --request POST \
--url https://api-sandbox.oftrust.net/apps/v1 \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzY29w...DVs5aaf' \
--header 'Content-type: application/json' \
--data '{
"name": "Example Application",
"description": "Application description",
"privacyPolicyUrl": "http://example.com/privacy.html",
"webPageUrl": "http://example.com/application.html",
"iconUrl": "http://example.com/icon.png",
"scopes": "",
"defaultScopes": "",
"redirectUris": "https://example.com/auth-callback",
"defaultRedirectUri": "https://example.com/auth-callback",
"groupId": "{group_id}"
}'
You only need to provide name
and groupID
in the cURL request. groupID
is of the Group
created in step 3.
On success, you will receive a response similar to this:
{
"@context": "https://standards.oftrust.net/v2/Context/Identity/Digital/Software/App/",
"@type": "App",
"@id": "8c40d6d4-2dbb-4f8f-987f-5c68e7475d79",
"data": {
"iconUrl": "http://example.com/icon.png",
"privacyPolicyUrl": "http://example.com/privacy.html",
"description": "Application description",
"webPageUrl": "http://example.com/application.html",
"name": "Example Application"
},
"metadata": {
"createdAt": "2020-02-14T07:18:22+00:00",
"createdBy": "e224629d-3f4f-4cb2-8823-fdc839e5da98",
"updatedAt": "2020-02-14T07:18:22+00:00",
"updatedBy": "e224629d-3f4f-4cb2-8823-fdc839e5da98"
},
"inLinks": [],
"outLinks": [],
"client": {
"clientId": "8c40d6d4-2dbb-4f8f-987f-5c68e7475d79",
"redirectUris": "https://example.com/auth-callback",
"defaultRedirectUri": "https://example.com/auth-callback",
"scopes": "",
"defaultScopes": "",
"clientSecrets": [
"4RbY09PR16F74VacbFhIsxzAJTytJfplpgZRdqE_tp4"
]
},
"tokens": [
{
"access_token": "wvkBrsvjBEigwd-PA...1h5vweXnzCEvpkapESHz6sxE",
"expires_in": 63072000,
"token_type": "Bearer"
},
{
"access_token": "CkT5COQfHtbuih1a2...1h5vweXnzCEvpkapESHz6sxE",
"expires_in": 63072000,
"token_type": "Bearer"
}
]
}
NOTE: Make sure to save clientId
, clientSecrets
, and the two access_token
s for future use. They will be required for data consumption.
You can also Register an Application in Sandbox
using the World app
.
You can find out more about Building Applications in the platform in relevant resources.
Data Product
is used to fetch harmonized data related to your created identity network.
To register a Data Product in the Platform:
You need to have a connector to make calls to the Data Source API in order to fetch harmonized data.
Below is a connector skeleton, written in python to get you started.
Make sure to carefully define the parameters that would be accepted by the connector.
import base64
import json
import settings
from jwt.algorithms import RSAAlgorithm
# List of supported headers, and if they're required or not.
SUPPORTED_HEADERS = {
'X-Pot-Signature': {
'required': True
},
'X-App-Token': {
'required': True
},
'X-User-Token': {
'required': False
}
}
# Get the request headers from the request object.
headers = dict()
# Get the body from the request json body.
body = dict()
# Keep the Platform of Trust public key e.g. in the settings.
public_pem = settings.POT_PUBLIC_KEY
# Loop through the request headers and validate them.
for header, rules in SUPPORTED_HEADERS.items():
header = header.lower()
if rules['required'] and header not in headers:
raise Exception(
f'Missing required header "{header}"'
)
# Convert the request body to a string, sorting the keys, without
# indentation and using separators comma (,) and colon (:)
payload_string = json.dumps(
body,
sort_keys=True,
indent=None,
separators=(',', ': ')
).strip()
alg_obj = RSAAlgorithm(RSAAlgorithm.SHA256) # RSA SHA256 signature
key = alg_obj.prepare_key(public_pem)
# Verify the payload and signature against the Platform of Trust public
# key
is_valid = alg_obj.verify(
payload_string.encode('utf-8'),
key,
base64.b64decode(headers['X-Pot-Signature'].encode('utf-8'))
)
if not is_valid:
raise Exception('Signature validation failed')
Check out Setup A Connector guide for more details.
You can also use the Connector Engine service of Platform of Trust to implement and customize your connector. Contact us with the subject "Interested in Building Connectors".
You can create a Data Product in Sandbox with Product API
curl -i --request POST \
--url https://api-sandbox.oftrust.net/products/v1 \
--header 'authorization: Bearer eyJ0eXAiOi...fnVsfjbkJ1uGXVUnVU' \
--header 'content-type: application/json' \
--data '{
"dataContext": "https://standards.oftrust.net/contexts/product-data.jsonld",
"parameterContext": "https://standards.oftrust.net/contexts/product-parameters.jsonld",
"productCode": "example-product-60",
"name": "60 Minute Data Product",
"groupId": "0db1e898-2184-4eb5-9b9b-4d259c5cb4de",
"translatorUrl": "https://api-external-sandbox.oftrust.net/lh-translator/v1/fetch",
"organizationPublicKeys": [
{
"url": "https://api-external-sandbox.oftrust.net/lh-translator/v1/public.key",
"type": "RsaSignature2018"
}
]
}'
NOTE: productCode
needs to be unique!
keep in mind to correctly define the dataContext
and parameterContext
for your Data Product.groupID
is of the Group
created in step 3
NOTE: translatorUrl
is the server URL where you are hosting the implemented connector in step 6.1
organizationPublicKeys
is a RsaSignature2018
type public key for the hosted connector.
On success, you will receive a response similar to the following:
HTTP/1.0 201 Created
{
"@context": "https://standards.oftrust.net/v2/Context/Identity/Product/DataProduct/",
"@type": "DataProduct",
"@id": "https://api-sandbox.oftrust.net/products/v1/example-product-1",
"productCode": "example-product-60",
"dataContext": "https://platformoftrust.github.io/standards/contexts/product-data.jsonld",
"parameterContext": "https://platformoftrust.github.io/standards/contexts/product-parameters.jsonld",
"translatorUrl": "https://example.com/translator/url",
"name": "60 Minute Data Product",
"organizationPublicKeys": [
{
"type": "RsaSignature2018",
"url": "https://example.com/example.pub"
}
],
"description": null,
"imageUrl": null,
"identityId": "5d58025b-3764-4f3d-8d09-5e17b064f0f9"
}
NOTE: Make sure to save the identityId
for the created Data Product
as it would be needed later connect it to a Sensor
.
Read more about Data Product in Data Product 101 guide.
To connect a Data Product to a Sensor:
curl --request POST \
--url https://api-sandbox.oftrust.net/identities/v1/{sensorId}/link/{dataProductId} \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9eyJzY29w...DVs5aa' \
--header 'content-type: application/json' \
--data '{
"context": "https://standards.oftrust.net/v2/Context/Link/AtDataProduct/",
"type": "AtDataProduct",
"data": {
"ids": {
"site_name": "some_site_name"
},
"capabilities": ["TEMPERATURE"]
}
}'
NOTE: In the cURL request, use @id
s of the Sensor
and Data Product
of your choice.
Here, the link context
has to be of type AtDataProduct and the ´type´ be AtDataProduct
The link direction has to be from the Data Product
to the Sensor
.
NOTE: You need to include the parameters that would be received by your connector. For this demo, the parameters defined are:
"data": {
"ids": {
"site_name": "some_site_name"
},
"capabilities": ["TEMPERATURE"]
}
On success, you will receive a response similar to this:
HTTP/1.0 201 Created
{
"@context": "https://standards.oftrust.net/v2/Context/Link/AtDataProduct/",
"@type": "AtDataProduct",
"@id": "be7a2c57-03d8-46f4-aaf0-2b1ca118ef5c",
"from": "5d58025b-3764-4f3d-8d09-5e17b064f0f",
"to": "a6b5a74e-bd98-4c9b-9561-932877258833",
"data": {
{
"ids": {
"site_name": "some_site_name"
},
"capabilities": ["TEMPERATURE"]
}
},
"metadata": {
"createdAt": "2019-09-12T09:49:24+00:00",
"createdBy": "33237067-e72c-4f26-b78b-9f9e234b2e7d",
"updatedAt": "2019-09-12T09:49:24+00:00",
"updatedBy": "33237067-e72c-4f26-b78b-9f9e234b2e7d"
}
}
The final step before starting the harmonized data flow in the Platform.
Make a request to the Broker API to test your Data Product. You also need to know how to construct a valid request
NOTE: Broker API requires a header called x-pot-signature
, which must be used in the API request within the 5 seconds of its generation. This is to ensure same signature is not used in subsequent API requests.
To generate an x-pot-signature
and send a request to Broker API
at the same time, customize the following python script:
import json
import hmac
import hashlib
import base64
import http.client
from datetime import datetime
# App secret and token
secret = "<APP_SECRET_GENERATED_WITH_APPLICATION_REGISTRATION>"
app_token = "<APP_TOKEN_GENERATED_WITH_APPLICATION_REGISTRATION>"
timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z")
body = {
"timestamp": timestamp,
"productCode": "<DATA_PRODUCT_CODE>",
"parameters": {
"ids": [
{"id": "<some_id>"}
],
"startTime": "2020-02-10 13:06:40",
"endTime": "2020-02-10 21:20:54",
"dataTypes": ["TEMPERATURE"]
},
}
body_hash = json.dumps(
body, sort_keys=True, indent=None, separators=(",", ": ")
).strip()
digest = hmac.new(
secret.encode("utf-8"), body_hash.encode("utf-8"), hashlib.sha256
).digest()
signature = base64.b64encode(digest).decode()
conn = http.client.HTTPSConnection("api-sandbox.oftrust.net")
headers = {
"content-type": "application/json",
"x-pot-signature": signature,
"x-app-token": app_token,
}
conn.request("POST", "/broker/v1/fetch-data-product", json.dumps(body), headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
Here, x-app-token
is the access_token
you obtained while registering an Application in step 5. secret
refers to the clientSecrets
from that application.
timestamp
refers to the time when the request was sent. This needs to be in RFC3339 format.
productCode
is from the Data Product
you created in step 6.2.
parameters
are additional parameters that the connector needs. Different products and connectors require different parameters. You should check the parameters list from Data Provider's translator.
x-pot-signature
is A HMAC-SHA256 signature in base64 encoded format. The signature is created from the request payload and clientSecrets
obtained while registering an Application in step 5.
NOTE: Make sure to add in the request payload the correct parameters in the that can be accepted and processed by the connector you created in step 6.1
Save the script. Execute the python script in your terminal with the following command:
python script_name.py
On success, depending on the connector accepting the parameters and returning a response from the data source, you should see a response similar to the following:
{
"@context":"https://standards.oftrust.net/v2/Context/Identity/Product/DataProduct/",
"data":{
"@context":"https://standards.oftrust.net/v2/Context/Identity/Product/DataProduct/",
"@type":"DataProduct",
"items":[
{
"id":{
"id":"Valtuustotalo_kokoushuone4-temp"
},
"data":[
{
"timestamp":"2020-02-10 13:30:00",
"value":22.0,
"type":"Temperature",
"unit":"\u00b0C"
},
{
"timestamp":"2020-02-10 14:00:00",
"value":21.0,
"type":"Temperature",
"unit":"\u00b0C"
},
{
"timestamp":"2020-02-10 21:00:00",
"value":22.0,
"type":"Temperature",
"unit":"\u00b0C"
}
]
}
]
},
"signature":{
"type":"RsaSignature2018",
"created":"2020-04-22T10:28:04+00:00",
"creator":"https://api-external-sandbox.oftrust.net/dummy-translator/v1/public.key",
"signatureValue":"zR35LeCcwZ94...XS0kzeM58CEUCTpMPrM/N89Jo6hQhhogr2Z8QfnXLY6uOgi7fg=="
}
}
This ensures the created connector is functioning properly and is capable to fetch data from the connected data source and pass it to Broker API in harmonized format.