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
- Web-Komponente ruft /endpoint/proxy/... auf
- PHP-Proxy:prüft XSRF-Tokenergänzt ggf. OAuth-Headerleitet Request an die itm:Connect API weiter
- 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;
}