You will have to implement support for these http endpoints. All endpoints must implement authorization as described
on the authentication page. Each request will contain a Authorization: bearer <jwt>
header
and you have to extract, parse and validate the token.
Polling manifests
GET <path>/manifest
After the new adapter has been registered in our configuration, backend will start polling its manifest every n minutes. This also doubles as monitoring / alerting in case a third party system starts misbehaving or goes offline. It is important that the third party system has a proper TLS certificate and that we verify it.
Sample manifest request token
Each http request to the manifest
endpoint will contain an Authorization
header on the format below. Your adapter is
responsible for parsing and validating the token.
Authorization: bearer eyJraWQiOiJGY3hwY3pLM0l2V3F2Q2x2ZFRYV3ZFMVBpN3phVV9oaV9NSGdUalgtME9rIiwiYWxnIjoiRVMyNTYifQ.eyJhdWQiOiJodHRwczpcL1wvdGhpcmQtcGFydHktc3lzdGVtLmNvbSIsInNjb3BlIjpbIm1hbmlmZXN0OnNjcmFwZSJdLCJpc3MiOiJodHRwczpcL1wvb3Nsb25va2tlbGVuLm9zbG8ua29tbXVuZS5ubyIsImV4cCI6MTYxNDA2NTQ2NiwiaWF0IjoxNjE0MDY1NDM2LCJqdGkiOiI2ZDNjNjY0NS1kMDI2LTRkZjItYjJjMS1kNTQ3YThkZDkwZDAifQ.yWZQJ4Xlv0ZWPthU674tX2JPlRbmsvHvjvJP7hSfwPZ9sHoE-TBEFHH5RhKzYR7j4I3iHhMXEd5lWPzowlaNNg
{
"aud": "https://third-party-system.com",
"scope": [
"manifest:scrape" (1)
],
"iss": "https://oslonokkelen.oslo.kommune.no",
"exp": 1614065466,
"iat": 1614065436,
"jti": "6d3c6645-d026-4df2-b2c1-d547a8dd90d0"
}
1 | All requests to the manifest endpoint will have this scope |
Sample manifest response
version: 42
things:
- id: front-door
description: The front door
actions:
- id: open
description: Unlocks and opens the front door for 10 seconds
- id: unlock
description: Unlocks the front door
- id: lock
description: Locks the front door
- id: back-door
description: The back door
actions:
- id: open
description: Unlocks and opens the back door for 10 seconds
This sample uses yaml formatting just to give you an idea of what a manifest looks like. The actual manifest response produced by your adapter should be protobuf encoded. |
Executing a request
POST <path>/execute
This is the fun part! The user has pressed a button in the app and expects a door to open. When the user hits the big open button the app will make a request to backend that runs authorization, figures out what adapters are involved with the request and forwards the request to the endpoint registered in the process described above.
All this is might be easier to visualize with a sequence diagram:
The important part here is that the adapter is responsible for downloading the correct key (the signed token contains a key id) from Oslonøkkelen backend and verify that the token actually is signed by a private key belonging to the public key it downloaded. Another assumption here is that the adapter verifies Oslonøkkelens TLS certificate.
Sample request token
Each http request to the execute
endpoint will contain an Authorization
header on the format below. Your adapter is
responsible for parsing and validating the token.
Authorization: bearer eyJraWQiOiJGY3hwY3pLM0l2V3F2Q2x2ZFRYV3ZFMVBpN3phVV9oaV9NSGdUalgtME9rIiwiYWxnIjoiRVMyNTYifQ.eyJhdWQiOiJodHRwczpcL1wvdGhpcmQtcGFydHktc3lzdGVtLmNvbSIsInJlcXVlc3QiOnsiYXR0YWNobWVudHMiOlt7Im5vcndlZ2lhbkZvZHNlbHNudW1tZXIiOnsibnVtYmVyIjoiMzAwOTg2MDIyNDcifX1dLCJyZXF1ZXN0SWQiOiJyMSIsImFjdGlvbklkIjoib3BlbiIsInRoaW5nSWQiOiJkb29yIn0sInNjb3BlIjpbImFjdGlvbjpleGVjdXRlIl0sImlzcyI6Imh0dHBzOlwvXC9vc2xvbm9ra2VsZW4ub3Nsby5rb21tdW5lLm5vIiwiZXhwIjoxNjE0MDY1NDY2LCJpYXQiOjE2MTQwNjU0MzYsImp0aSI6IjZkM2M2NjQ1LWQwMjYtNGRmMi1iMmMxLWQ1NDdhOGRkOTBkMCJ9.g0t3pC6kmlW_YIkDsdRvG7MX3yogeoDqDridjjG2wnas25Z9M3j_3cipdmLOAZjiS5P5BfIPEa75FE_k0f8VRg
If you copy the serialized token above into https://jwt.io you should see something like the json structure below.
{
"aud": "https://third-party-system.com",
"request": {
"attachments": [ (1)
{
"norwegianFodselsnummer": {
"number": "30098602247" (2)
}
}
],
"requestId": "r1",
"actionId": "open",
"thingId": "door"
},
"scope": [
"action:execute" (3)
],
"iss": "https://oslonokkelen.oslo.kommune.no",
"exp": 1614065466, (4)
"iat": 1614065436,
"jti": "6d3c6645-d026-4df2-b2c1-d547a8dd90d0" (5)
}
1 | Most requests won’t have any attachments. |
2 | Randomly generated for this example. |
3 | All execute requests will have this scope. The scope tells the adapter what the purpose of the tokken is. The adapter must not open any doors unless this scope is present in the token. |
4 | Token expire time. The adapter must reject any expired tokens. |
5 | The adapter can prevent replay attacks by keeping a list of non expired token ids and rejecting already used tokens. |
Sample execute response
status: ERROR_TEMPORARY (1)
attachments:
- error_description:
code: door-offline (2)
- end_user_message:
message:
message: Sorry, but the door appears to be offline (3)
1 | Success, denied, temporary error or permanent error |
2 | Error code mostly for debugging / statistics |
3 | Human-readable message that will show up in the users app |
This sample uses yaml formatting just to give you an idea of what a manifest looks like. The actual manifest response produced by your adapter should be protobuf encoded. |