Using Azure Digital Twins SDKs

You can use the official Azure Digital Twins SDKs (Python, .NET, JavaScript) to connect to Konnektr Graph, as it is fully API-compatible with Azure Digital Twins.

Authentication with Konnektr Graph

Konnektr Graph uses Auth0 for authentication instead of Azure AD, so you cannot use DefaultAzureCredential or other Azure identity providers. Instead, you must implement a custom TokenCredential that obtains tokens from Auth0.

Auth0 Configuration

  • Domain: auth.konnektr.io
  • Audience: https://api.graph.konnektr.io
  • Grant Type: client_credentials (service-to-service)

Python SDK

Custom TokenCredential Implementation

import requests
import time
from azure.core.credentials import AccessToken, TokenCredential
from azure.digitaltwins.core import DigitalTwinsClient

class KonnektrTokenCredential(TokenCredential):
    def __init__(self, domain: str, client_id: str, client_secret: str, audience: str):
        self.domain = domain
        self.client_id = client_id
        self.client_secret = client_secret
        self.audience = audience
        self._token = None
        self._expires_on = 0

    def get_token(self, *scopes, **kwargs) -> AccessToken:
        if self._token and time.time() < self._expires_on - 300:  # 5 min buffer
            return self._token

        url = f"https://{self.domain}/oauth/token"
        payload = {
            "client_id": self.client_id,
            "client_secret": self.client_secret,
            "audience": self.audience,
            "grant_type": "client_credentials"
        }
        
        response = requests.post(url, json=payload)
        response.raise_for_status()
        
        token_data = response.json()
        access_token = token_data["access_token"]
        expires_in = token_data["expires_in"]
        
        self._expires_on = time.time() + expires_in
        self._token = AccessToken(access_token, int(self._expires_on))
        
        return self._token

Using the Python SDK

from azure.digitaltwins.core import DigitalTwinsClient

# Create credential
credential = KonnektrTokenCredential(
    domain="auth.konnektr.io",
    client_id="your-client-id",
    client_secret="your-client-secret", 
    audience="https://api.graph.konnektr.io"
)

# Create client
client = DigitalTwinsClient(
    endpoint="https://your-graph-name.api.graph.konnektr.io",
    credential=credential
)

# Example operations
try:
    # List models
    models = list(client.list_models())
    print(f"Found {len(models)} models")
    
    # Get a specific twin
    twin = client.get_digital_twin("twin-id")
    print(f"Twin: {twin}")
    
    # Create a twin
    twin_data = {
        "$metadata": {"$model": "dtmi:example:Room;1"},
        "Temperature": 20.0,
        "Humidity": 45.0
    }
    client.upsert_digital_twin("room-001", twin_data)
    
except Exception as e:
    print(f"Error: {e}")

.NET SDK

Custom TokenCredential Implementation

using Azure.Core;
using Azure.DigitalTwins.Core;
using System.Text.Json;

public class KonnektrTokenCredential : TokenCredential
{
    private readonly string _domain;
    private readonly string _clientId;
    private readonly string _clientSecret;
    private readonly string _audience;
    private readonly HttpClient _httpClient;
    
    private AccessToken? _cachedToken;
    private DateTimeOffset _tokenExpiry;

    public KonnektrTokenCredential(string domain, string clientId, string clientSecret, string audience)
    {
        _domain = domain;
        _clientId = clientId;
        _clientSecret = clientSecret;
        _audience = audience;
        _httpClient = new HttpClient();
    }

    public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
        => GetTokenAsync(requestContext, cancellationToken).GetAwaiter().GetResult();

    public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
    {
        if (_cachedToken.HasValue && DateTimeOffset.UtcNow < _tokenExpiry.AddMinutes(-5))
            return _cachedToken.Value;

        var tokenUrl = $"https://{_domain}/oauth/token";
        var payload = new
        {
            client_id = _clientId,
            client_secret = _clientSecret,
            audience = _audience,
            grant_type = "client_credentials"
        };

        var content = new StringContent(JsonSerializer.Serialize(payload), System.Text.Encoding.UTF8, "application/json");
        var response = await _httpClient.PostAsync(tokenUrl, content, cancellationToken);
        response.EnsureSuccessStatusCode();

        var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
        var tokenResponse = JsonSerializer.Deserialize<TokenResponse>(responseContent);

        _tokenExpiry = DateTimeOffset.UtcNow.AddSeconds(tokenResponse.expires_in);
        _cachedToken = new AccessToken(tokenResponse.access_token, _tokenExpiry);

        return _cachedToken.Value;
    }

    private class TokenResponse
    {
        public string access_token { get; set; }
        public int expires_in { get; set; }
    }
}

Using the .NET SDK

using Azure.DigitalTwins.Core;
using System.Text.Json;

// Create credential
var credential = new KonnektrTokenCredential(
    domain: "auth.konnektr.io",
    clientId: "your-client-id",
    clientSecret: "your-client-secret",
    audience: "https://api.graph.konnektr.io"
);

// Create client
var client = new DigitalTwinsClient(
    new Uri("https://your-graph-name.api.graph.konnektr.io"),
    credential
);

try
{
    // List models
    var models = client.GetModelsAsync();
    await foreach (var model in models)
    {
        Console.WriteLine($"Model: {model.Id}");
    }
    
    // Get a twin
    var twin = await client.GetDigitalTwinAsync<JsonElement>("twin-id");
    Console.WriteLine($"Twin: {twin.Value}");
    
    // Create a twin  
    var twinData = new
    {
        Metadata = new { Model = "dtmi:example:Room;1" },
        Temperature = 20.0,
        Humidity = 45.0
    };
    
    await client.UpsertDigitalTwinAsync("room-001", JsonSerializer.Serialize(twinData));
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

JavaScript/Node.js SDK

Custom TokenCredential Implementation

const axios = require('axios');
const { DigitalTwinsClient } = require('@azure/digital-twins-core');

class KonnektrTokenCredential {
    constructor(domain, clientId, clientSecret, audience) {
        this.domain = domain;
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.audience = audience;
        this.cachedToken = null;
        this.tokenExpiry = 0;
    }

    async getToken() {
        const now = Math.floor(Date.now() / 1000);
        if (this.cachedToken && now < this.tokenExpiry - 300) {
            return { 
                token: this.cachedToken, 
                expiresOnTimestamp: this.tokenExpiry * 1000 
            };
        }

        const tokenUrl = `https://${this.domain}/oauth/token`;
        const payload = {
            client_id: this.clientId,
            client_secret: this.clientSecret,
            audience: this.audience,
            grant_type: 'client_credentials'
        };

        const response = await axios.post(tokenUrl, payload);
        const { access_token, expires_in } = response.data;

        this.cachedToken = access_token;
        this.tokenExpiry = now + expires_in;

        return { 
            token: access_token, 
            expiresOnTimestamp: this.tokenExpiry * 1000 
        };
    }
}

Using the JavaScript SDK

const { DigitalTwinsClient } = require('@azure/digital-twins-core');

// Create credential
const credential = new KonnektrTokenCredential(
    'auth.konnektr.io',
    'your-client-id',
    'your-client-secret',
    'https://api.graph.konnektr.io'
);

// Create client
const client = new DigitalTwinsClient(
    'https://your-graph-name.api.graph.konnektr.io',
    credential
);

async function example() {
    try {
        // List models
        const models = client.listModels();
        for await (const model of models) {
            console.log(`Model: ${model.id}`);
        }
        
        // Get a twin
        const twin = await client.getDigitalTwin('twin-id');
        console.log(`Twin:`, twin);
        
        // Create a twin
        const twinData = {
            $metadata: { $model: 'dtmi:example:Room;1' },
            Temperature: 20.0,
            Humidity: 45.0
        };
        
        await client.upsertDigitalTwin('room-001', JSON.stringify(twinData));
        
    } catch (error) {
        console.error(`Error: ${error.message}`);
    }
}

example();

Environment Variables

For security, store your credentials as environment variables:

# .env file
KONNEKTR_CLIENT_ID=your-client-id
KONNEKTR_CLIENT_SECRET=your-client-secret
KONNEKTR_DOMAIN=auth.konnektr.io
KONNEKTR_AUDIENCE=https://api.graph.konnektr.io
KONNEKTR_ENDPOINT=https://your-graph-name.api.graph.konnektr.io

Then load them in your application:

import os
from dotenv import load_dotenv

load_dotenv()

credential = KonnektrTokenCredential(
    domain=os.getenv('KONNEKTR_DOMAIN'),
    client_id=os.getenv('KONNEKTR_CLIENT_ID'),
    client_secret=os.getenv('KONNEKTR_CLIENT_SECRET'),
    audience=os.getenv('KONNEKTR_AUDIENCE')
)

client = DigitalTwinsClient(os.getenv('KONNEKTR_ENDPOINT'), credential)

Error Handling

Common authentication errors and solutions:

  • 401 Unauthorized: Check your client credentials and ensure they're valid
  • 403 Forbidden: Verify your Auth0 application has the correct permissions
  • Invalid audience: Ensure you're using https://api.graph.konnektr.io
  • Token expired: The custom credential should handle renewal automatically

Note: Unlike Azure Digital Twins which uses Azure AD, Konnektr Graph requires Auth0 authentication. You cannot use Azure identity providers like DefaultAzureCredential, AzureCliCredential, or ManagedIdentityCredential.

Cookie Notice

We use cookies to enhance your browsing experience.