Support for OAuth2 client credentials flow for HTTP connections
The upcoming release of Eclipse Ditto version 2.2.0 supports HTTP connections that authenticate their requests via OAuth2 client credentials flow as described in section 4.4 of RFC-6749.
Detailed information can be found at Connectivity API > HTTP 1.1 protocol binding.
This blog post shows an example of publishing a twin event to an HTTP endpoint via OAuth2 client credentials flow.
For simplicity, we will use webhook.site
for both the token endpoint and the event publishing destination.
Feel free to substitute them for real OAuth and HTTP servers.
Prerequisites
This example requires 2 webhooks. We will use
https://webhook.site/785e80cd-e6e6-452a-be97-a59c53edb4d9
for access token requests, andhttps://webhook.site/6148b899-736f-47e6-9382-90b1d721630e
for event publishing.
Replace the webhook URIs by your own.
Configure the token endpoint
Configure the token webhook to return a valid access token response. Here is an example for a token expiring
at 00:00 on 1 January 3000. The field expires_in
is an arbitrary big number not reflecting the actual expiration
time of the access token.
- Status code: 200
- Content type:
application/json
- Response body:
{ "access_token": "ewogICJhbGciOiAiUlMyNTYiLAogICJ0eXAiOiAiSldUIgp9.ewogICJhdWQiOiBbXSwKICAiY2xpZW50X2lkIjogIm15LWNsaWVudC1pZCIsCiAgImV4cCI6IDMyNTAzNjgwMDAwLAogICJleHQiOiB7fSwKICAiaWF0IjogMCwKICAiaXNzIjogImh0dHBzOi8vbG9jYWxob3N0LyIsCiAgImp0aSI6ICI3ODVlODBjZC1lNmU2LTQ1MmEtYmU5Ny1hNTljNTNlZGI0ZDkiLAogICJuYmYiOiAwLAogICJzY3AiOiBbCiAgICAibXktc2NvcGUiCiAgXSwKICAic3ViIjogIm15LXN1YmplY3QiCn0.QUJD", "expires_in": 1048576, "scope": "my-scope", "token_type": "bearer" }
The access token has the form <headers>.<body>.<signature>
, where <headers>
and <body>
are base64-encoding
of the headers and the body in JSON format, and <signature>
is the base-64 encoded signature computed according
to the issuer’s key pair. Since the token webhook is not a real OAuth2 server, the signature in the example is a
placeholder. The unencoded headers and body are as follows.
Headers
{
"alg": "RS256",
"typ": "JWT"
}
Body
{
"aud": [],
"client_id": "my-client-id",
"exp": 32503680000,
"ext": {},
"iat": 0,
"iss": "https://localhost/",
"jti": "785e80cd-e6e6-452a-be97-a59c53edb4d9",
"nbf": 0,
"scp": [
"my-scope"
],
"sub": "my-subject"
}
Create the connection
Create a connection
publishing twin events to the event publishing webhook using OAuth2 credentials.
The tokenEndpoint
field is set to the access token webhook.
{
"id": "http_oauth2",
"name": "http_oauth2",
"connectionType": "http-push",
"connectionStatus": "open",
"uri": "https://webhook.site:443",
"targets": [
{
"address": "POST:/6148b899-736f-47e6-9382-90b1d721630e",
"topics": ["_/_/things/twin/events"],
"authorizationContext": ["integration:ditto"]
}
],
"credentials": {
"type": "oauth-client-credentials",
"tokenEndpoint": "https://webhook.site/785e80cd-e6e6-452a-be97-a59c53edb4d9",
"clientId": "my-client-id",
"clientSecret": "my-client-secret",
"requestedScopes": "my-scope"
}
}
Generate a thing-created event
Create a thing granting read access to the connection’s subject. The thing-created event will be distributed to the connection for publishing.
{
"_policy": {
"entries": {
"DEFAULT": {
"subjects": {
"{{ request:subjectId }}": {
"type": "the creator"
},
"integration:ditto": {
"type": "the connection"
}
},
"resources": {
"policy:/": {
"grant": ["READ", "WRITE"],
"revoke": []
},
"thing:/": {
"grant": ["READ", "WRITE"],
"revoke": []
}
}
}
}
}
}
HTTP requests made by the HTTP connection
Before the HTTP connection publishes the thing-created event, it makes an access token request against the token endpoint to obtain a bearer token.
POST /785e80cd-e6e6-452a-be97-a59c53edb4d9 HTTP/1.1
Host: webhook.site
Accept: application/json
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=my-client-id
&client_secret=my-client-secret
&scope=my-scope
The request should appear at the access token webhook. The webhook should return the configured access token response.
{
"access_token": "ewogICJhbGciOiAiUlMyNTYiLAogICJ0eXAiOiAiSldUIgp9.ewogICJhdWQiOiBbXSwKICAiY2xpZW50X2lkIjogIm15LWNsaWVudC1pZCIsCiAgImV4cCI6IDMyNTAzNjgwMDAwLAogICJleHQiOiB7fSwKICAiaWF0IjogMCwKICAiaXNzIjogImh0dHBzOi8vbG9jYWxob3N0LyIsCiAgImp0aSI6ICI3ODVlODBjZC1lNmU2LTQ1MmEtYmU5Ny1hNTljNTNlZGI0ZDkiLAogICJuYmYiOiAwLAogICJzY3AiOiBbCiAgICAibXktc2NvcGUiCiAgXSwKICAic3ViIjogIm15LXN1YmplY3QiCn0.QUJD",
"expires_in": 1048576,
"scope": "my-scope",
"token_type": "bearer"
}
The HTTP connection will cache the access token and use it to authenticate itself at the event publishing webhook for each thing event, including the first thing-created event.
POST /6148b899-736f-47e6-9382-90b1d721630e HTTP/1.1
Host: webhook.site
Content-Type: application/vnd.eclipse.ditto+json
Authorization: Bearer ewogICJhbGciOiAiUlMyNTYiLAogICJ0eXAiOiAiSldUIgp9.ewogICJhdWQiOiBbXSwKICAiY2xpZW50X2lkIjogIm15LWNsaWVudC1pZCIsCiAgImV4cCI6IDMyNTAzNjgwMDAwLAogICJleHQiOiB7fSwKICAiaWF0IjogMCwKICAiaXNzIjogImh0dHBzOi8vbG9jYWxob3N0LyIsCiAgImp0aSI6ICI3ODVlODBjZC1lNmU2LTQ1MmEtYmU5Ny1hNTljNTNlZGI0ZDkiLAogICJuYmYiOiAwLAogICJzY3AiOiBbCiAgICAibXktc2NvcGUiCiAgXSwKICAic3ViIjogIm15LXN1YmplY3QiCn0.QUJD
{
"topic": "<namespace>/<name>/things/twin/events/created",
"headers": {},
"path": "/",
"value": {
"policyId": "<policy-id>"
},
"revision": 1
}
The HTTP connection will obtain a new token from the access token webhook when the previous token is about to expire.
Please get in touch if you have feedback or questions regarding this new functionality.
–
The Eclipse Ditto team