Tokens¶
External API clients need to present tokens to the DSH in order to authenticate, and to receive the appropriate permissions on MQTT topics in public DSH streams:
- The API Client Authentication Service needs an API key to request a REST token from the DSH.
- An API client needs a REST token to request an MQTT token from the DSH.
- An API client needs an MQTT token to connect to the Messaging API.
- Each token can contain claims that restrict what the bearer of the token can do.
Tip
See Authentication mechanism for more information.
REST token¶
The REST token is a JSON Web Token (JWT), which contains a set of REST claims. These claims describe the following:
- Which other REST APIs the bearer of the token can connect to.
- Which actions the bearer of the token can execute on those REST APIs.
Requesting a REST token¶
You can request a REST token from the DSH via a POST request:
- Endpoint:
/auth/v0/tokenon your platform. The full URL has the following form:https://api.<your-platform>.kpn-dsh.com/auth/v0/token. - HTTP method: POST
- Authentication:
apikeyin the HTTP header of the request. You receive the API key from your platform administrator. - Success return:
HTTP 200 OK, with the REST token in the body - Failure return: Any other HTTP status code
The body of your request is a JSON document with the following informal schema:
| Key | Description |
|---|---|
tenant |
|
exp |
|
claims |
|
The example below just uses the defaults, which results in a REST token with full access rights and an expiration time of 30 days:
The example below has specific claims, which is highly recommended. This REST token can only be used to request an MQTT token that allows the client ‘just-this-thermostat’ to subscribe to the MQTT topic house/kitchen/sensor in the public DSH stream ‘temperature’:
{
"tenant": "tenant-a",
"exp": 1498942700,
"claims": {
"datastreams/v0/mqtt/token": {
"id": "just-this-thermostat",
"exp": 1498122712,
"tenant": "tenant-a",
"claims": [
{ "action": "subscribe",
"resource": {
"type": "topic",
"prefix": "/tt",
"stream": "temperature",
"topic": "house/kitchen/sensor"
}
}
]
}
}
}
Contents of REST token¶
The REST token consists of a header, body, and signature, separated by a . character. The body of the token is a Base64-encoded JSON document. The example below shows the decoded body of a REST token:
{
"gen":14,
"endpoint":"api.<platform-dns-name>.kpn-dsh.com",
"iss":"snqn8-s13",
"claims":{"datastreams/v0/mqtt/token": {
"id": "just-this-thermostat",
"exp": 1498122712,
"tenant": "tenant-a",
"dshclc": { "custom-key": "some-value" }
"claims": [
{ "action": "subscribe",
"resource": {
"type": "topic",
"prefix": "/tt",
"stream": "temperature",
"topic": "house/kitchen/sensor"
}
}
]
}
},
"exp":1498942700,
"tenant-id":"tenant-a",
}
| Key | Description |
|---|---|
gen |
You can ignore the generation (gen) key because the DSH uses it internally to process the token. |
endpoint |
|
iss |
The issuer (iss) key identifies the principal that issued the REST token. |
claims |
|
exp |
This key defines the expiration time for the token as a UNIX timestamp (seconds since midnight of 1 January, 1970). |
tenant-id |
|
MQTT token¶
The MQTT token is a JSON Web Token (JWT), which contains a set of claims. These claims describe the following:
- Which other REST APIs the bearer of the token can connect to.
- Which actions the bearer of the token can execute on those REST APIs.
Note
If you connect via HTTP, then The Messaging API also requires the MQTT token. In other words, use the MQTT token to access both MQTT and HTTP.
Requesting an MQTT token¶
You can request an MQTT token from the DSH via a POST request:
- Endpoint:
datastreams/v0/mqtt/tokenon your platform. The full URL has the following form:https://api.<your-platform>.kpn-dsh.com/datastreams/v0/mqtt/token. - HTTP method: POST
- Authentication: REST token in the
Authorization: BearerHTTP header of the request. - Success return:
HTTP 200 OK, with the MQTT token in the body - Failure return: Any other HTTP status code
The body of your request is a JSON document with the following informal schema:
| Key | Description |
|---|---|
tenant |
|
id |
|
exp |
|
claims |
|
dshclc |
|
The example below requests an MQTT token without additional restrictions:
The example below requests an MQTT token that lets the client ‘just-this-thermostat’ subscribe to 1 MQTT topic only, namely the topic house/kitchen/temperature of the public DSH stream ‘temperature’.
Contents of MQTT token¶
The MQTT token consists of a header, body, and signature, separated by a . character. The body of the token is a Base64-encoded JSON document. The example below shows the decoded body of an MQTT token:
{
"iss": "0",
"gen": 7,
"exp": 1735115547,
"iat": 1734514347,
"endpoint": "mqtt.<platform-dns-name>.kpn-dsh.com",
"ports": {
"mqtts": [
8883
],
"mqttwss": [
443,
8443
]
},
"tenant-id": "tenant-a",
"client-id": "just-this-thermostat",
"claims": [
{ "action": "subscribe",
"resource": {
"type": "topic",
"prefix": "/tt",
"stream": "temperature",
"topic": "house/kitchen/sensor"
}
}
]
"dshclc": {
"custom-key": "some-value"
}
}
| Key | Description |
|---|---|
iss |
The issuer (iss) key identifies the principal that issued the MQTT token. |
gen |
You can ignore the generation (gen) key because the DSH uses it internally to process the token. |
exp |
This key defines the expiration time for the token as a UNIX timestamp (seconds since midnight of 1 January, 1970). |
iat |
This key defines the time that the token was issued at (iat), as a UNIX timestamp (seconds since midnight of 1 January, 1970). Use this value to calculate the age of the token. |
endpoint |
|
ports |
This key specifies the ports that an MQTT client needs to use to connect via MQTT over SSL (mqtts), or via MQTT over WebSockets (mqttwss). See Connecting via MQTT for more information. |
tenant-id |
This key contains the ID of the DSH tenant. |
client-id |
This the MQTT client ID that the client provides when it connects to the MQTT broker. The client ID must be unique across all connections to the DSH for the tenant mentioned in the |
claims |
|
dshclc |
|
Guidelines¶
Bear in mind the following guidelines when you request an MQTT token.
- Request tokens with specialized claims. It’s recommended to set restrictions in an MQTT token request:
- If a token is compromised, it can’t be used for more than its intended use.
- A token with restricted permissions is smaller and saves bandwidth.
- Request tokens with a limited lifetime:
- The default lifetime of an MQTT token is 7 days, which is long.
- A shorter lifetime prevents abuse, for example a lifetime of 5 minutes.
- A token must only be valid at connection time. As a consequence, a live connection won’t break when the token expires.
- Use stable client IDs:
- Use stable client IDs for external clients, instead of discard client IDs.
- This makes it easier to attribute published messages to concrete clients.
- It’s recommended to pass the client ID from the MQTT token as the client ID when establishing the connection with the Messaging API. See Client ID for more information.
- Use the most recent MQTT token:
- It’s possible to request multiple tokens for the same client ID, with an overlap in the lifetime.
- As long as the tokens are valid, external clients can use them to connect to the platform.
- However, the external clients can’t connect at the same time, because the client ID must be unique.
- If a newer MQTT token for a specific client ID is used to connect to the Messaging API, then the platform invalidates the older requested tokens for that client ID.
Permissions¶
The permissions for MQTT topics are managed at 3 different levels:
- In the MQTT ACL, which specifies the set of permissions that a Messaging API has for MQTT topics in public DSH streams.
- In the claims of the REST token, which can add more restrictions for an API client that requests an MQTT token.
- In the claims of the MQTT token, which can add even more restrictions for an API client that wants to connect to the Messaging API.
Topic patterns¶
At the different levels, one can specify the “publish” or “subscribe” permissions for specific MQTT topics in a DSH stream. These permissions consist of two parts:
- The action, namely “publish” or “subscribe”
- A topic pattern that defines the MQTT topics that the action applies to
Topic patterns can contain the following special characters:
- A forward slash
/to separate topic levels - A plus sign
+as a single-level wildcard - A number sign
#as a multi-level wildcard
Tip
See Topic Names and Topic Filters in the MQTT specification for more information.
The MQTT specification allows a topic filter (with wildcards) for the “subscribe” action, but it prohibits wildcards for the “publish” action. This leads to separate rules for the two actions when evaluating MQTT topics against topic patterns.
For the “publish” action, a specific MQTT topic matches the topic pattern if the following is true:
- The MQTT topic starts with
<topic-prefix>/<DSH-stream-name>/. Because the topic prefix is always “/tt”, this results in/tt/<DSH-stream-name>/. - After the prefix, the MQTT topic contains the following:
- A topic level for each corresponding
+wildcard in the topic pattern - 0 or more topic levels for any
#wildcard in the topic pattern - The identical topic level for each level in the topic pattern that isn’t a wildcard
- A topic level for each corresponding
For the “subscribe” action, a specific MQTT topic matches the topic pattern if the following is true:
- The MQTT topic starts with
<topic-prefix>/<DSH-stream-name>/. Because the topic prefix is always “/tt”, this results in/tt/<DSH-stream-name>/. - After the prefix, the MQTT topic contains the following:
- A topic level for each corresponding
+wildcard in the topic pattern - 0 or more topic levels or
+wildcards, and 0 or 1#wildcard for any#wildcard in the topic pattern - The identical topic level for each level in the topic pattern that isn’t a wildcard
- A topic level for each corresponding
The table below gives several examples of topics that match and that don’t match for the topic prefix /tt, the DSH stream temperature and the topic pattern z/+/+/+/#:
| Action | Match | No match |
|---|---|---|
| Publish |
|
|
| Subscribe |
|
|
Claims key¶
An API client can request more restrictions for the REST token and the MQTT token, using the “claims” key. These restrictions can contain topic patterns, but also a client ID, expiration time, etc. If the REST token and the MQTT token don’t contain a “claims” key, then no further restictions apply, and the API client receives the permissions as set in the MQTT ACL of the API in question.
The sections below list the keys that you can use when you request specific claims for a REST token or an MQTT token.
REST token request¶
The “claims” key in the request for a REST token specifies limitations on the MQTT token. It has the following informal schema:
…
"claims":{string: {
"id": string,
"exp": long,
"relexp": long,
"tenant": string,
"dshclc": object,
"claims": [
{ "action": "subscribe"|"publish",
"resource": {
"type": "topic",
"prefix": "/tt",
"stream": string,
"topic": string
}
}
]
}
}
…
| Key | Description |
|---|---|
claims |
|
id |
This key specifies the ID of the MQTT/HTTP client that connects to the Messaging API. The API client won't be able to connect to the API if its client ID doesn't match the value in this key. A single REST token can't contain restrictions for multiple specific MQTT client IDs. If you add a restriction for the MQTT client ID, then you can use the 1 single REST token to request MQTT tokens for 1 single MQTT client only. |
exp |
This key defines the absolute expiration time of the MQTT token, as a UNIX timestamp (seconds since midnight of 1 January, 1970). |
relexp |
This key defines the relative expiration time of the MQTT token, in seconds. It reflects the maximum lifetime of the MQTT token. A value of "300" results in a maximum lifetime of 5 minutes. |
tenant |
This key contains the tenant ID for the Messaging API in question. It specifies that the API client can only request an MQTT token for the tenant ID in question. |
dshclc |
|
claims |
The lower-level "claims" key is a collection of objects that reflect permissions on MQTT topics. These objects contain the following keys:
|
MQTT token request¶
The claims in the request for an MQTT token limit the MQTT topics that the MQTT/HTTP client can access. They have the following informal schema:
…
"claims": [
{ "action": "subscribe"|"publish",
"resource": {
"type": "topic",
"prefix": "/tt",
"stream": string,
"topic": string
}
}
]
…
| Key | Description |
|---|---|
action |
The action, either "publish" or "subscribe". |
resource |
The MQTT topic in question, defined using the keys below:
|