AutoFlow-Anmeldedaten
AutoFlow-Anmeldedaten sind ein zentraler, verschlüsselter Speicher für die Authentifizierungsdetails, die deine Flows beim Aufruf externer Systeme brauchen. Der HTTP-Anfrage-Schritt ist der erste Konsument; künftige Schritte für externe Aufrufe werden denselben Speicher nutzen.
Konfiguriere jeden externen Service einmal und referenziere ihn anschließend per Code aus jedem Schritt, der ihn anspricht. Rotierst du einen Schlüssel, wechselst die Umgebung oder änderst ein Geheimnis, geschieht das an einer einzigen Stelle — jeder Flow, der die Anmeldedaten nutzt, übernimmt die Änderung sofort. Geheimnisse erscheinen nie in der Schritt-Konfiguration und nie im Ausführungsprotokoll.
Was du gewinnst
| Fähigkeit | Was das bedeutet |
|---|---|
| Keine Geheimnisse in Flows | Tokens, Passwörter und Client-Secrets liegen verschlüsselt im Speicher, nicht in Schritt-Konfigurationen oder Logs. |
| Eine Änderung, jeder Flow | Rotiert ein API-Key, aktualisierst du die Anmeldedaten — alle Flows, die sie nutzen, sind sofort aktuell. |
| Konsistente Authentifizierung | Der passende Authorization-Header (oder Query-Parameter) wird je Auth-Typ automatisch erzeugt. |
| Sauberes Ausführungsprotokoll | Auth-Header werden automatisch aus dem Protokoll herausgefiltert. |
| Allow-List für URLs | Sind Basis-URLs konfiguriert, prüft AutoFlow jede Anfrage — Anmeldedaten können nicht durch einen falsch konfigurierten oder bösartigen Schritt an eine Spy-URL geraten. |
| Pro Mandant | Jeder Business-Central-Mandant hat seine eigenen Anmeldedaten. Derselbe Code kann in unterschiedlichen Mandanten auf unterschiedliche Konten zeigen. |
Anmeldedaten anlegen
Öffne AutoFlow-Anmeldedaten über Tell-Me und wähle Neu. Die Karte ist in Allgemein, Authentifizierung, Standardheader und Basis-URLs unterteilt.
Allgemein
| Feld | Bedeutung |
|---|---|
| Code | Bis zu 20 Zeichen. Verwende eine Konvention wie MYAPI-PROD oder SHOP-DE-TEST. Diesen Wert siehst du im Lookup des HTTP-Anfrage-Schritts. |
| Beschreibung | Freitext, erscheint in Lookups. |
| Test-URL (optional) | URL, die die Test-Aktion aufruft. Bleibt leer? Dann fällt Test auf die erste Basis-URL zurück. Sinnvoll, wenn keine Basis-URL ein gutes Probe-Ziel ist — dann kannst du hier auf einen Health-Endpunkt zeigen. |
Authentifizierung
Wähle den Typ, der zum Zielsystem passt. Die Karte zeigt nur die Felder, die für den gewählten Typ relevant sind.
Eine weiche, gelbe Hinweismeldung erscheint, wenn ein erforderliches Geheimnis noch nicht hinterlegt ist — gespeichert wird die Anmeldedaten-Konfiguration trotzdem; Flow-Ausführungen, die das Geheimnis brauchen, scheitern dann mit einer klaren Fehlermeldung, bis du es nachreichst.
Keine Authentifizierung
Für öffentliche Endpunkte. Es wird kein Geheimnis gespeichert.
API-Key
Die API verlangt einen statischen Schlüssel, der bei jeder Anfrage mitgesendet wird. Konfiguriere:
- API-Key-Name — der Header- oder Query-Parameter-Name.
- API-Key-Standort —
Header(am häufigsten) oderQuery-Parameter. - API-Key-Wert — einmal eingeben, dann maskiert. Verschlüsselt gespeichert.
Basic (Benutzer + Passwort)
HTTP-Basic-Authentifizierung. Konfiguriere:
- Benutzername
- Passwort — einmal eingeben, dann maskiert.
AutoFlow sendet Authorization: Basic <base64(user:pass)>.
Bearer-Token
Ein statisches Bearer-Token. Konfiguriere:
- Bearer-Token — einmal eingeben, dann maskiert.
AutoFlow sendet Authorization: Bearer <token>. Tokens beliebiger Länge werden unterstützt (der Speicher chunked transparent).
OAuth 2.0 Client Credentials
Server-zu-Server-OAuth. AutoFlow ruft beim Authorization-Server ein Token ab, cached es und nutzt es bis kurz vor Ablauf wieder. Konfiguriere:
- OAuth-Token-URL — der Token-Endpunkt des Authorization-Servers.
- OAuth-Client-ID
- Client-Secret — einmal eingeben, dann maskiert.
- OAuth-Scope (optional) — leerzeichengetrennte Liste von Scopes.
- OAuth-Grant-Type — derzeit nur Client Credentials.
- OAuth-Client-Credential-Übertragung — wie Client-ID und Secret an den Token-Endpunkt übermittelt werden:
- Request-Body (formularkodiert) — als
client_id=…&client_secret=…im Body. Standard. - Authorization-Header (HTTP Basic) — als
Authorization: Basic <base64(client_id:client_secret)>. Manche IdPs verlangen das (z. B. ältere ADFS-Instanzen).
- Request-Body (formularkodiert) — als
Tokens werden verschlüsselt gecached und automatisch erneuert, wenn sie weniger als 60 Sekunden gültig sind. Das expires_in-Feld wird tolerant geparst — sowohl JSON-Integer (3600) als auch JSON-String ("3600") werden akzeptiert; bei fehlendem oder unparsbarem Wert greift ein 3600-Sekunden-Fallback.
Liefert der Token-Endpunkt einen Fehlerstatus, enthält die Fehlermeldung die ersten 200 Zeichen des Antwort-Bodys (laut RFC 6749 ist das bei Client-Credentials-Fehlern error + error_description, niemals ein Token) — so siehst du auf einen Blick, was der IdP wirklich sagt, ohne dass Geheimnisse leaken.
Basis-URLs
Eine Liste erlaubter URL-Präfixe für diese Anmeldedaten. Zwei wichtige Funktionen:
- Komfort-Präfix. Verwendet der HTTP-Anfrage-Schritt eine relative URL wie
/widgets, präfixt AutoFlow sie mit dem ersten Listeneintrag. - Sicherheits-Allow-List. Verwendet der Schritt eine absolute URL, prüft AutoFlow, ob sie mit einem der konfigurierten Präfixe beginnt. Passt keiner, wird die Anfrage vor dem Senden abgelehnt — das Geheimnis verlässt BC nicht. Das verhindert, dass ein Angreifer (oder ein falsch konfigurierter Flow) das Token an eine Spy-URL wie
https://attacker.test/exfilschickt.
Beispiele (mit Basis-URL https://api.beispiel/v1):
| Schritt-URL | Ergebnis |
|---|---|
/widgets | Präfixiert → https://api.beispiel/v1/widgets ✅ |
https://api.beispiel/v1/widgets?page=2 | Erlaubt (matcht Präfix) ✅ |
https://api.beispiel/v1 | Erlaubt (exakter Match) ✅ |
https://api.beispiel/v123/widgets | Abgelehnt — Grenz-Prüfung an /v1 |
https://attacker.test/exfil | Abgelehnt — Host stimmt nicht |
Mehrere Einträge sind unterstützt — sinnvoll, wenn dieselbe Authentifizierung mehrere regionale oder umgebungsspezifische Endpunkte autorisiert (api-eu.beispiel.com, api-us.beispiel.com). Der erste Eintrag gewinnt für die Relativ-URL-Präfixierung; alle Einträge sind gültige Präfixe für die Allow-List.
Die Konfigurationsseite des HTTP-Anfrage-Schritts führt die Allow-List-Prüfung schon zur Designzeit aus — gibst du eine URL ein, die beim Ausführen abgelehnt würde, erscheint eine weiche Warnung direkt unter dem Feld. Die Prüfung beim Ausführen bleibt der harte Wächter.
Lässt du die Liste leer, sind beliebige URLs erlaubt — kein Präfix, keine Prüfung. Verwende das nur, wenn du wirklich offene Anmeldedaten willst und das Risiko akzeptierst, dass eine Fehlkonfiguration das Geheimnis an einen beliebigen Endpunkt schicken könnte.
Plain-HTTP-Warnung
http://-Basis-URLs sind weiterhin zulässig (On-Prem- und Localhost-Workflows brauchen das), aber die Karte zeigt eine weiche Warnung, wenn eine der Basis-URLs ungesichertes HTTP verwendet — Geheimnisse, die über http:// gesendet werden, können auf dem Übertragungsweg abgefangen werden. Verwende https:// für produktive Endpunkte.
Standardheader
Header, die mit dieser Anmeldedaten-Konfiguration immer gesendet werden — z. B. User-Agent, X-Tenant, Accept. Werden auf jede Anfrage angewandt, die diese Anmeldedaten nutzt.
Zwei Einschränkungen:
Authorizationdarf nicht als Standardheader hinzugefügt werden — er ist für den Auth-Typ reserviert.- Steht der API-Key der Anmeldedaten auf
Header, darf kein Standardheader denselben Namen wie der konfigurierte API-Key-Header tragen — die Auth würde ihn ohnehin überschreiben.
Manuelle Header am HTTP-Anfrage-Schritt überschreiben Standardheader gleichen Namens.
Header-Reihenfolge und Ausführungsprotokoll
Verwendet ein Schritt eine Anmeldedaten-Konfiguration, baut AutoFlow die Header der ausgehenden Anfrage in dieser Reihenfolge zusammen:
- Standardheader der Anmeldedaten (niedrigste Priorität).
- Manuelle Header des HTTP-Anfrage-Schritts (überschreiben Standardheader gleichen Namens).
- Auth-Header des Auth-Typs (gewinnen über alles, auch über manuelle Header).
Auth-Header werden zusätzlich aus dem Ausführungsprotokoll entfernt, damit Geheimnisse dort nie auftauchen. Standard- und manuelle Header werden ganz normal protokolliert.
Bei ApiKey-in-Query wird die URL nach der Basis-URL-Auflösung, aber vor dem Anhängen des Query-Parameters protokolliert — das Geheimnis ist also auf der Drahtleitung, nie im Log.
Die Test-Aktion
Über Test auf der Karte schickst du eine GET-Anfrage an die Test-URL (oder die erste Basis-URL, wenn Test-URL leer ist). Die Ergebnismeldung zeigt den vollständigen HTTP-Status und den vollständigen Response-Body.
Hilfreich, um zu prüfen, ob
- Basis-URL bzw. Test-URL erreichbar ist,
- die Authentifizierung wirklich funktioniert (
200oder401ist deutlich aufschlussreicher als ein verkonfigurierter Flow).
Lifecycle
Geheimnis rotieren
Karte öffnen, neuen Wert ins Geheimnis-Feld tippen, speichern. Der alte Wert wird im verschlüsselten Speicher überschrieben. Zwischengespeicherte OAuth-Tokens werden nicht automatisch verworfen — über Gespeicherte Geheimnisse löschen erzwingst du einen frischen Tokenabruf.
Alle Geheimnisse löschen
Die Aktion Gespeicherte Geheimnisse löschen entfernt jedes für diese Anmeldedaten gespeicherte Geheimnis dauerhaft (API-Key, Passwort, Bearer-Token, OAuth-Client-Secret, zwischengespeicherte OAuth-Tokens). Die Anmeldedaten selbst bleiben erhalten.
Anmeldedaten umbenennen
Der Code lässt sich über die Standard-BC-Umbenennung ändern. Die Plattform verschiebt verschlüsselte Geheimnisse und Kindzeilen (Standardheader, Basis-URLs) auf den neuen Code und ruft anschließend den Hook OnCredentialRenamed des Auth-Typs auf — Erweiterungs-Auth-Typen können ihre eigenen, unter Custom-Schlüsseln gespeicherten Geheimnisse mitziehen.
Anmeldedaten löschen
Beim Löschen der Anmeldedaten werden alle Geheimnisse und Kindzeilen entfernt und der OnCredentialDeleted-Hook des Auth-Typs ausgeführt. Flows, die noch auf den gelöschten Code referenzieren, scheitern bei der nächsten Ausführung mit einer eindeutigen Fehlermeldung — passe den Schritt an, indem du andere Anmeldedaten auswählst oder die Referenz entfernst.
Mehrere Mandanten
Anmeldedaten sind pro Mandant. Möchtest du denselben Code in mehreren Mandanten verwenden, lege ihn in jedem Mandanten an. Jeder Mandant kann auf ein eigenes Konto zeigen.
Berechtigungen
Drei Berechtigungssätze gehören zum Feature:
| Berechtigungssatz | Zweck |
|---|---|
| mse365 AF Cred. Read | Lesezugriff auf Anmeldedaten und ihre Kindtabellen (wird beim Ausführen von Flows verwendet). Wer Flows ausführt, die Anmeldedaten nutzen, braucht das. |
| mse365 AF Cred. Edit | Lese- und Schreibzugriff. Schließt Cred. Read ein. Notwendig, um Anmeldedaten anzulegen, zu ändern oder zu löschen. |
| mse365 AF Cred. RT | Wrappt Cred. Read. Gedacht zur Aufnahme in den Runtime-/Flow-Ausführungs-Berechtigungssatz des Kunden — wer Flow-Ausführungsrechte bekommt, erbt automatisch den Lesezugriff für die Auflösung von Anmeldedaten. Enthält nicht den Edit-Grant. |
Speicherung
Geheimnisse werden mit dem Tenant-Encryption-Key der BC-Plattform AES-verschlüsselt und in IsolatedStorage mit DataScope::Company abgelegt. Da die Verschlüsselungsfunktionen der Plattform Eingaben auf 215 Zeichen begrenzen, werden Werte in ≤ 200-Zeichen-Chunks gesplittet; Lesezugriffe setzen sie transparent wieder zusammen. Klartext landet nie in der Datenbank.
Voraussetzung Tenant-Verschlüsselung
Cryptography Management.EncryptText setzt voraus, dass im BC-Tenant die Datenverschlüsselung aktiviert ist.
- BC SaaS: Verschlüsselung ist standardmäßig aktiv. Nichts zu tun.
- On-Prem / Sandbox / Dev-Container: Ein Tenant-Admin muss Verschlüsselung einmalig einschalten — entweder über die Seite Verschlüsselungsverwaltung im BC-Web-Client oder, falls PowerShell-
Enable-NavEncryptionKeyin containerisierten Umgebungen hängt, durch Veröffentlichen einer einmaligen OnPrem-Target-Bootstrap-App, deren Install-CodeunitCryptography Management.EnableEncryption(true)aufruft.
Fehlt die Verschlüsselung, scheitert jeder Lese- oder Schreibzugriff mit der Plattform-Meldung An encryption key is required to complete the request. — bewusst harter Fehler statt stillem Klartext-Fallback.
Erweitern: eigene Auth-Typen
Die Liste der Auth-Typen ist erweiterbar. Sinnvoll, wenn das Zielsystem ein Authentifizierungsschema verlangt, das keiner der fünf eingebauten Typen abdeckt — etwa ein Legacy-Webshop, der Header aus einem konfigurierbaren Secret + Zeitstempel + HMAC zusammenbaut.
Was zu implementieren ist
Erweitere das Enum mse365 AF Credential Auth Type um einen neuen Wert, der auf eine Codeunit zeigt, die das Interface mse365 AF ICredentialAuth implementiert:
enumextension 50100 "Acme Hmac Auth" extends "mse365 AF Credential Auth Type"
{
value(50100; AcmeHmac)
{
Caption = 'Acme HMAC';
Implementation = "mse365 AF ICredentialAuth" = "Acme Hmac Auth Impl.";
}
}
codeunit 50100 "Acme Hmac Auth Impl." implements "mse365 AF ICredentialAuth"
{
procedure BuildAuthHeaders(CredentialCode: Code[20]; RequestCtx: Interface "mse365 AF IHttpRequest Ctx."; var Headers: Dictionary of [Text[50], Text[4096]])
begin
// Header aus dem hinterlegten Geheimnis + aktuellem Zeitstempel berechnen.
end;
procedure RewriteUrl(CredentialCode: Code[20]; var Url: Text)
begin
// No-op für Header-basierte Auth; ApiKey-in-Query überschreibt das.
end;
procedure OnCredentialDeleted(CredentialCode: Code[20])
begin
// IsolatedStorage-Einträge unter eigenen Schlüsseln aufräumen.
end;
procedure OnCredentialRenamed(OldCode: Code[20]; NewCode: Code[20])
begin
// IsolatedStorage-Einträge von OldCode auf NewCode umziehen.
// Eingebaute Geheimnisse und Kindtabellen migriert die Plattform selbst.
end;
}
Eigene Konfigurationsfelder
Braucht dein Auth-Typ mehr als nur ein Geheimnis, erweitere Tabelle und Karte:
tableextension 50100 "Acme Hmac Cred Fields" extends "mse365 AF Credential"
{
fields
{
field(50100; "Acme Hmac Algorithm"; Code[10]) { Caption = 'HMAC algorithm'; }
}
}
pageextension 50100 "Acme Hmac Cred Card" extends "mse365 AF Credential Card"
{
layout
{
addlast(Authentication)
{
group(AcmeHmac)
{
Visible = Rec."Auth Type" = Rec."Auth Type"::AcmeHmac;
field("Acme Hmac Algorithm"; Rec."Acme Hmac Algorithm") { }
}
}
}
}
Speichere Geheimnisse über mse365 AF Credential Storage, um dieselbe gechunkte verschlüsselte Speicherung zu erben — keine Eigenbau-Lösung:
var
Storage: Codeunit "mse365 AF Credential Storage";
begin
Storage.SetSecret(CredentialCode, 'AcmeHmacSigningKey', SigningKey);
end;
Storage.DeleteAllSecrets und MoveAllSecrets kennen nur die sechs eingebauten Geheimnisnamen — deshalb existieren OnCredentialDeleted und OnCredentialRenamed, damit Erweiterungen ihre eigenen Schlüssel selbst aufräumen bzw. mitziehen.
Interface-Vertrag
| Methode | Wann gerufen | Was zu tun |
|---|---|---|
BuildAuthHeaders | Bei jeder ausgehenden Anfrage | Auth-Header in das Dictionary schreiben. Hier hinzugefügte Header werden automatisch aus dem Ausführungsprotokoll entfernt. |
RewriteUrl | Bei jeder ausgehenden Anfrage | URL mutieren, wenn nötig (z. B. Query-Parameter anhängen). Die URL vor dem Rewrite ist die geloggte. |
OnCredentialDeleted | Anmeldedaten-Zeile gelöscht | Eigene IsolatedStorage-Einträge oder Hilfstabellen aufräumen. |
OnCredentialRenamed | Code der Anmeldedaten umbenannt | Eigene IsolatedStorage-Einträge von OldCode auf NewCode verschieben. |
Die fünf eingebauten Auth-Typen (None / ApiKey / Basic / Bearer / OAuth2CC) implementieren leere Stubs für OnCredentialDeleted und OnCredentialRenamed — die Plattform erledigt das über DeleteAllSecrets / MoveAllSecrets.