Skip to content

Einbindung der itm:Connect Web-Komponenten

Warenkorb & UserAccount inkl. Auth- & Proxy-Logik


1. Überblick

Die itm:Connect Web-Komponenten (z. B. Warenkorb und UserAccount) werden per Custom HTML Tags in bestehende Websites integriert.

Die Komponenten:

  • kommunizieren mit der itm:Connect API
  • benötigen einen serverseitigen HTTP-Proxy
  • unterstützen OAuth-Authentifizierung
  • erwarten optional ein XSRF-Token
  • liefern Notifications & Events an die Website zurück
  • basieren optisch auf Bootstrap 4

2. Architektur & Kommunikationsfluss

Grundprinzip

Die Web-Komponenten kommunizieren nicht direkt mit der itm:Connect API, sondern immer über einen Proxy auf eurer Website.

Ablauf

  1. Web-Komponente ruft /endpoint/proxy/... auf
  2. PHP-Proxy:prüft XSRF-Tokenergänzt ggf. OAuth-Headerleitet Request an die itm:Connect API weiter
  3. API-Antwort wird als JSON an die Web-Komponente zurückgegeben

3. HTTP-Proxy (Pflicht)

Der Proxy dient als zentrale Schnittstelle zwischen Website und itm:Connect API.

Beispiel-Endpoint

/endpoint/proxy/*

Alle Requests der Web-Komponenten laufen automatisch über diesen Pfad.


4. XSRF-Token (empfohlen)

Zweck

Die Web-Komponenten erwarten ein XSRF-Token, um Cross-Site-Scripting zu verhindern.

Ohne Token:

  • funktionieren die Komponenten technisch
  • es entstehen jedoch Warnungen in der Browser-Konsole
  • geringere Sicherheit

Token serverseitig erzeugen (PHP)

$xsrftoken = hash("sha256", "itemkg_vhsconnect_webcomponents_proxy");
setcookie("XSRF-TOKEN", $xsrftoken, 0, "/");
$_SESSION["XSRF-TOKEN"] = $xsrftoken;

Der Proxy prüft bei jedem Request das Vorhandensein des Tokens.


5. Authentifizierung – OAuth Client Credentials (wichtig)

Wann greift diese Logik?

Wenn eine Web-Komponente einen Request auf

/endpoint/proxy/oauth/token

mit

grant_type = client_credentials

ausführt.


Aufgabe des Proxys

In diesem Fall muss der Proxy:

  • client-key und client-secret serverseitig kennen
  • diese per Basic-Auth-Header an die API übergeben

Die Credentials dürfen nicht im Browser sichtbar sein.


Basic-Auth-Header

Authorization: Basic base64(client-key:client-secret)

6. Vollständiges Beispiel: PHP-Proxy inkl. Auth-Logik

<?php
session_start();

$apiBaseUrl = "https://api.vhs-connect.de";

// === XSRF-Check ===
if (!isset($_COOKIE['XSRF-TOKEN'])) {
    http_response_code(403);
    echo json_encode(["error" => "XSRF-Token fehlt"]);
    exit;
}
$xsrfToken = $_COOKIE['XSRF-TOKEN'];

// === Request-Infos ===
$requestUri = str_replace("/endpoint/proxy", "", $_SERVER['REQUEST_URI']);
$method     = $_SERVER['REQUEST_METHOD'];
$body       = file_get_contents("php://input");

// Standard-Header
$headers = [
    "X-XSRF-TOKEN: {$xsrfToken}",
    "Content-Type: application/json"
];

// === OAuth: client_credentials ===
$isOauthTokenCall = (strpos($requestUri, "/oauth/token") === 0);

// grant_type auslesen (JSON oder x-www-form-urlencoded)
$grantType = null;
$parsedJson = json_decode($body, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($parsedJson)) {
    $grantType = $parsedJson["grant_type"] ?? null;
} else {
    parse_str($body, $parsedForm);
    $grantType = $parsedForm["grant_type"] ?? null;
}

if ($isOauthTokenCall && $grantType === "client_credentials") {
    $clientKey    = getenv("VHS_CONNECT_CLIENT_KEY");
    $clientSecret = getenv("VHS_CONNECT_CLIENT_SECRET");

    if (!$clientKey || !$clientSecret) {
        http_response_code(500);
        echo json_encode(["error" => "Client-Credentials nicht konfiguriert"]);
        exit;
    }

    $basicAuth = base64_encode($clientKey . ":" . $clientSecret);
    $headers[] = "Authorization: Basic {$basicAuth}";
}

// === Request weiterleiten ===
$ch = curl_init($apiBaseUrl . $requestUri);
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST  => $method,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_POSTFIELDS     => $body
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

http_response_code($httpCode);
echo $response;

7. Einbindung der Web-Komponenten

Gemeinsame Assets

<link rel="stylesheet" href="https://webcomponents.vhs-connect.de/styles.css">

<script src="https://webcomponents.vhs-connect.de/runtime.js" type="module"></script>
<script src="https://webcomponents.vhs-connect.de/polyfills.js" type="module"></script>
<script src="https://webcomponents.vhs-connect.de/main.js" type="module"></script>
Hinweis: Unter webcomponents-next.vhs-connect.de kann der NEXT-Releasering angesprochen werden, der immer die neueste Version enthält.

8. Beispiel: UserAccount

<itemkg_connect-user_account></itemkg_connect-user_account>

Funktionen

  • Login
  • Registrierung
  • Passwort zurücksetzen
  • Benutzerstatus

9. Beispiel: Warenkorb

<itemkg_connect-cart cart-id="12345"></itemkg_connect-cart>

10. Notifications & Events

Die Web-Komponenten senden Feedback an die Website, z. B.:

Event-Typ Beschreibung
navigation Seitenwechsel im Warenkorb
login Erfolgreicher Login inkl. Benutzerdaten
changes Allgemeine Statusänderungen

JavaScript-Listener

const cart = document.querySelector("itemkg_connect-cart");

if (cart) {
    cart.addEventListener("changes", (event) => {
        console.log(event.detail);
    });
}

11. Einstellungen & Übersetzungen (settings.json)

Die Einstellungen können optional über einen lokalen /endpoint/settings Endpunkt bereitgestellt werden.

Beispielstruktur (vereinfacht und anonymisiert):

{
    "settings": [],
    "translations": {
        "de-DE": {
            "GENERAL": {
                "VALIDATION": {
                    "DATE": {
                        "COURSE_AGE_RESTRICTION": "Das Geburtsdatum liegt außerhalb der Altersgrenzen des Kurses ({{data.minAge}} - {{data.maxAge}} {{data.unitOfAgeDE}})."
                    }
                }
            },
            "WEBCOMPONENTS": {
                "CART": {
                    "GENERAL": {
                        "ALREADY_IN_CART": "Der Kurs befindet sich bereits im Warenkorb."
                    }
                }
            }
        }
    }
}

12. Optische Anpassung per CSS

  • Basis: Bootstrap
  • CSS vollständig überschreibbar
itemkg_connect-cart .btn-primary {
    background-color: #004b8d;
}