Simple SAML Sample
Diese Seite beschreibt eine einfache Einrichtung einer Applikation in meinem Tenant, damit sich Anwender meines Tenants auf eine Webseite zugreifen, dann auf Entra ID umgeleitet und bei der Rückkehr mit einem Token ankommen, welches die Webanwendung dann als Anmeldeinformation nutzen kann.
Worum geht es?
Stellen Sie sich vor, sie haben eine selbst entwickelte Webapplikation und müssten sich um die Anmeldung selbst kümmern. Natürlich können Sie nun eine Anmeldung per "Formular" mit "Benutzername + Kennwort" vorstehen und die Information in einer eigenen Datenbank speichern. Das ist aber unsicher und kein Single-SignIn. Sie könnten Insbesondere mit dem IIS auch einfach die Anmeldung per "Negotiate/NTLM/Kerberos" nutzen. Das funktioniert gut, wenn Sie im LAN sind, der Computer "Domain Joined" ist und die Anwender als Domainbenutzer angemeldet sind. Für Kerberos müssen Sie aber eine Verbindung zum KDC haben und 2FA/MFA ist so auch erst einmal nicht vorhanden.
Die meisten Firmen haben aber schon einen Microsoft 365 Mandanten und damit auch eine Anmeldung an Entra ID für ihre Benutzer eingerichtet. Die meisten Benutzer sind mit ihrem Client auch schon authentifiziert und dies ist unabhängig von einer NT-Domain. EntraID Joined und Entra-ID Konto samt Primary Refresh Token (PRT) reichen aus aus. Ihre Applikation muss nur ihren Anwender beim Anonymen Zugriff zu Entra ID senden und den Rücksprung als "Form-Post" annehmen, decodieren und verifizieren. Aber dann hat ihre Software ein OAUTH-Token und kann den Anwender identifizieren. Alle Funktionen wie Multi Faktor, Login-Protokollierung, Benutzerverwaltung etc. nimmt ihnen Entra ID ab.
Für die Einrichtung brauchen wir nur wenige Dinge:
- AppRegistration in Entra ID
Damit definieren unsere eigene Applikation als Token-Empfänger und könnten über Claims sogar weitere Details ermitteln wie z.B. - Enterprise App in EntraID
Zur App wird auch eine Enterprise App angelegt, über welche wir z.B. die Berechtigungen für Benutzer und Gruppen steuern können. - Eine Webseite zur Umleitung
Ich habe mir einfach eine "Index.htm"-Seite angelegt, die einen 302-Redirect zu Entra ID mit der passenden Payload - Eine Webseite für den Rücksprung
Entra-ID wird nach der Anmeldung diesen wieder mit einem HTTP-POST zur definierten URL schicken. Dort wartet eine HTML-Seite, genauer eine PH-Seite", die einfach nur die übertragenen Daten decodiert und ausgibt.
Dies ist also eher eine Beispielanwendung, um die Anwendung und Funktion zu testen und nicht für die Produktion. Insbesondere die Verifizierung, Schutz gegen DoS-Attacken, Buffer Overflow etc. sind alle nicht implementiert und dazu sollten sie fertige bewährte Pakete nutzen und nicht selbst sich an der Decodierung versuchen.
App Definition in Entra
Zuerst lege ich eine App Registration in meinem Tenant an. Auf "https://portal.azure.com" gehe ich in den Bereich der App Registrations und addiere eine neue App.

Die App braucht natürlich einen Namen und hier kann ich schon auswählen, ob ich eine "Single Tentant Only"-App für meinen Tenant oder sogar eine App für mehrere Tenants bereitstellen möchte. Darauf gehe ich später noch ein. Zudem muss ich die Plattform, z.B. "Web", auswählen und eine Rücksprung-Adresse mitliefern. Das ist die URL, zu der ein WebClient nach der Anmeldung zurückkehrt und sein Token per POST übermittelt
Nachdem die App angelegt werden, muss ich für meinen "SimpleSAMLSample nichts mehr einrichten. Allerdings muss ich neben der Redirect-URI noch die AppID und die TenantID aus der Übersicht abrufen:

Diese brauche ich im nächsten Schritt./p>
Webseite zur Umleitung zu Entra
ZZuerst dachte ich an eine einfache HTML-Seite mit einem 302 Redirect. Aber das wäre zu wenig, wenn ich muss den Client per HTTP-POST zu Entra ID Umleiten und zumindest die GUID der Applikation und die Rücksprungadresse mitgeben, welche in der App registriert ist. Das ist wichtig, damit sich nicht jemand anderes als diese App bösartig ausgeben kann. Ich habe mir dazu folgende kleine PHP-Seite gebaut. (Ok. die KI hat etwas mitgeholfen).
<?php
$tenant = "604d9047-44e5-443a-ad8f-98abe5748b0a";
$appId = "4099d059-adaf-4ee1-aa79-af1b961d180b";
$ssoUrl = "https://login.microsoftonline.com/$tenant/saml2";
$acs = "https://www.msxfaq.de/test/saml/acs.php";
$xml = <<<XML
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="_123456"
Version="2.0"
IssueInstant="2026-06-25T12:00:00Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
AssertionConsumerServiceURL="$acs">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"><![CDATA[$appId]]></saml:Issuer>
</samlp:AuthnRequest>
XML;
$url = $ssoUrl . '?SAMLRequest=' . urlencode(base64_encode(gzdeflate($xml)));
header('Location: ' . $url, true, 302);
echo "Redirecting to SSO URL: $url";
exit;
Der Code ist schnell erklärt aber da am Ende ein "header(Location:..." steht, darf nichts davor eine Ausgabe erzeugen, da ansonsten PHP keinen Header mehr schreiben kann. Eine einfache Leerzeile kann zu viel sein und achten Sie beim Speichern als Unicode-Datei, dass kein BOM davor geschrieben wird.
Oben sind die GUIDs der Applikation und des Tenant, die Entra ID SSO-URL und auch die Rücksprungadresse hinterlegt.
Mit den Werten können Sie nicht anfangen, denn Entra ID prüft, ob die von ihrer Applikation angeforderte RedirectURI zur Definition bei der App passt. Sie können selbst keine App mit der gleichen GUID in Entra anlegen und wenn Sie die Daten hier verwenden, dann springen ihre Clients zu meinem Tenant zurück, wenn die Benutzer denn entsprechend definiert wären.
Aus den vier Daten baut PHP eine XML-Datei zusammen, die dann erst mit gzdeflate komprimiert dann BASE64-Encoded und zuletzt noch URLEncoded wird. Daraus wird dann die eigentliche URL ,welche der Client per Redirect im Header zur Umleitung bringt.
Anmeldung bei Entra ID
Der Client springt zu "$ssoUrl = "https://login.microsoftonline.com/<GUID des Tenant>/saml2" und Entra ID decodiert die XML-Struktur. Wenn der Anwender schon angemeldet ist. dann wird Entra ID ein OAUTH-Ticket erstellen und dem Client in der Form übergeben, damit der Client diese an die "Redirect-URL" mittels Post zurücksendet. Wenn der Anwender noch nicht authentifiziert ist, dann startet die ganz normale Entra ID Anmeldemaske.
Webseite mit Redirect Processing
Der Client kommt in meinem Beispiel auf die ACS-URL unter der Adresse "https://www.msxfaq.de/test/saml/acs.php" zurück und hat als Payload ein POST mit dem Feld "SAMLResponse" Am Anfang der Seite steht wieder de PHP-Code, der den Inhalt von "SAMLResponse" ohne weitere Verifikation auseinandernimmt, decodiert und dann in die entsprechenden Felder der HTML-Vorlage einbindet.
<?php
if (!isset($_POST['SAMLResponse'])) {
die("Keine SAMLResponse empfangen.");
}
$base64 = $_POST['SAMLResponse'];
$xmlString = base64_decode($base64);
if ($xmlString === false) {
die("Base64 konnte nicht decodiert werden.");
}
// XML laden
$dom = new DOMDocument();
if (!$dom->loadXML($xmlString)) {
die("Ungültiges XML.");
}
// XML hübsch formatieren
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$xpath = new DOMXPath($dom);
$xpath->registerNamespace(
"saml",
"urn:oasis:names:tc:SAML:2.0:assertion"
);
$xpath->registerNamespace(
"samlp",
"urn:oasis:names:tc:SAML:2.0:protocol"
);
function getFirstValue(DOMXPath $xpath, string $query): string
{
$node = $xpath->query($query)->item(0);
return $node ? trim($node->textContent) : "";
}
?>
<!DOCTYPE html>
..... die Datei geht hier noch weiter
IIch habe ihnen die Datei hier als TXT-Datei zum Download bereitgestellt.
Beispiel mit Entra ID User im eigenen Tenant
Wenn alles wie erwartet funktioniert, dann gehe ich auf die URL https://www.msxfaq.de/test/saml und nach etwas "Geflacker" sehe ich die decodierten Daten:

Die Applikation bekommt ein OAUTH-Token des Anwender mit dem Displayname, Vorname, Nachname und Name (=UPN). Mein Code decodiert nur den POST aber prüft nicht die Signatur. Das sollten Sie natürlich nicht tun. Schauen Sie sich den Issuer an und prüfen Sie entsprechend das Token, ehe Sie dem Anwender den Zugriff anhand der gelieferten Identitätsinformationen liefern.
Beispiel mit anderen Benutzern
Nachdem die Anmeldung mit dem einzelnen eigenen Benutzer funktioniert hat, habe ich weitere Benutzer auf die Webseite gesendet.
|
Benutzer |
Ergebnis |
Beschreibung |
|---|---|---|
|
Eigener Benutzer |
OK |
Den Fall habe ich schon beschrieben und hat gezeigt, dass die Funktion im Grunde gegeben ist |
|
Gastbenutzer Entra ID |
OK |
Wenn ein Benutzer im Tenant der Application vorhanden ist, dann kann er sich problemlos anmelden und sendet sein SAML-Token an meine App |
|
Gast als Microsoft Konto |
OK |
Wenn ein Microsoft-Konto (früher LiveID, Passport) als Gast eingeladen wurde, dann kann er sich ebenfalls anmelden. |
|
Fremdes EntraID Konto |
Error |
Nutzt ein Anwender die Anmeldung an der App ohne ein Konto im Tenant der Application zu haben, dann kann er sich mit dem Fehler AADST50020 nicht anmelden.
|
|
Fremdes Microsoft-Konto |
Error |
Zuletzt habe ich noch ein Microsoft Konto (Consumer) verwendet, welches nicht im Tenant eingeladen wurde. Auch das war dann erfolglos. Anders als bei Entra ID habe ich aber keine Fehlernummer gesehen.
|
Solange mein Redirect die genaue AppID und die TenantID überliefert, kann Entra ID auch nur diesen Tenant befragen. Gibt es den Benutzer in diesem Tenant nicht, dann kommt eine Fehlermeldung.
In meinem Tenant sehe ich nur meine erfolgreichen Anmeldungen an den entsprechenden Konten aber nicht die fehlerhaften Anmeldungen durch Identitäten, die ich nicht kenne.
Multi Tenant
Wenn ich meine App aber auch anderen Tenants ohne vorherige Einladung der User als "Gast" zur Verfügung stellen will, dann muss ich diese etwas anpassen. Es gibt dazu aus meiner Sicht zwei Wege:
- Eigene App je Tenant
Ich kann den Admin deren anderen App bitte, eine App Registation anzulegen nur mir die AppID und TenantID zu übergeben. Wenn der Benutzer sich dann an meiner Webseite meldet, dann müsste ich den Benutzer um seinen Anmeldenamen bitten, um dann den Redirect zur richtigen AppID und TenantID zu machen. Das ist einfach aber skaliert nicht wirklich und ist für den Anwender zumindest bei der ersten Anmeldung kein "Single SignOn". Diese Option beschreibe ich daher nicht weiter. - Multi Tenant App
Viel besser ist es, wenn ich die App in meinem Tenant für viele andere Tenants erreichbar mache. Das muss ich nur entsprechend definieren. Diese Einstellungen schaue ich mir im weiteren an.
Ich muss dazu im Entra ID Portal meine App von "Single Tenant" auf "Multi Tenant" in der gewünschten Ausprägung umstellen.
- Convert single-tenant app to multitenant
on Microsoft Entra ID
https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-admin-consent-workflow
Wer bei der Einrichtung einer neuen App aufgepasst hat, konnte dort auch schon die Einstellmöglichkeit sehen. Wenn die Anwendung schon eingerichtet ist, dann können Sie die Konfiguration in der Application Registration unter "Authentication - Supportet Accounts" umstellen.
Manchmal kommt eine Fehlermeldung, das dies nicht möglich ist, das der Parameter "requestedAccessTokenVersion" nicht korrekt gesetzt ist. Diesen können Sie im Manifest dann z.B. auf "2" setzen.
Check the Application Manifest: Inspect the application manifest or the update payload to ensure that the api.requestedAccessTokenVersion property is set to 1, 2, or null. If you don't need to change it, you can omit this property from the update.
Die Lösung ist dann recht einfach:
Wenn signInAudience auf
AzureADandPersonalMicrosoftAccount festgelegt ist, muss der
Wert 2 lauten.
Microsoft Entra-App-Manifest (Azure AD Graph-Format).
https://learn.microsoft.com/de-de/entra/identity-platform/reference-app-manifest

Danach können Sie dann auch den Wert für "signInAudience" auf "AzureADandPersonalMicrosoftAccount" stellen. Wenn sie auf LiveID-Konten verzichten können, dann können Sie sogar eine Allow-Liste für Tenants pflegen.

So bekommen dann nur Benutzer ein Token, welche im richtigen Tenant sind.
Achtung:
Das sichert ihre App nicht da vor, dass Angreifer mutwillig
falsch formatierte HTTP-POST-Requests an ihre Applikation
senden. Die Eingangsseite muss also hier "sicher" und
"schnell" sein, um solche Angriffe korrekt zu versarbeiten,
zu verifizieren und schnell abzublocken.
Testen Sie daher ihre App zuerst als "Single Tenant App" in ihrem eigenen Tenant, ehe Sie fremde Konten zur Authentifizierung erlauben. Ich muss dann aber auch meine App noch anpassen, den die SSOUrl darf nicht mehr die Tenant-ID enthalten, in der Entra ID dann nach den Benutzern und Apps sucht.
// URL für einen bestimten Tenant $ssoUrl = "https://login.microsoftonline.com/$tenant/saml2"; // URL für alle Tenants und LiveIDs $ssoUrl = "https://login.microsoftonline.com/common/saml2"; // URL für alle Tenants ohne LiveIDs $ssoUrl = "https://login.microsoftonline.com/organizations/saml2"; // URL nur für LiveIDs $ssoUrl = "https://login.microsoftonline.com/consumer/saml2";
Wenn ein Anwender aus einem anderen Tenant nun ihre App verwendet, dann wird er zuerst um seine "Zustimmung" (User Consent) gefragt. Ich warte allen Administratoren aber diese Möglichkeit zu sperren. (Siehe Checkliste Tenant Einrichtung). Benutzer sollten nicht eigenverantwortlich einer App die Berechtigungen auf von ihnen erreichbare Daten gewähren können. Anwender dürfen in der Regel ja auch keine eigenen Programme auf ihrem PC installieren. Sie können aber in Entra ID einen Prozess einrichten, damit Benutzer eine neue App beantragen können.

https://portal.azure.com/#view/Microsoft_AAD_IAM/ConsentPoliciesMenuBlade/~/AdminConsentSettings
- Overview of Admin Consent Workflow -
Microsoft Entra ID
https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/admin-consent-workflow-overview - Configure the admin consent workflow -
Microsoft Entra ID
https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-admin-consent-workflow
Alternativ können sie eigene interne Prozesse definieren. Die Freigabe einer AppID ist einer Anforderung zur Installation einer neuen lokalen Software vergleichbar. Als Administrator können Sie über die URL mit der AppID als ClientID dies einfach erreichen. Für meine SAMLTEST-App wäre dies dann
https://login.microsoftonline.com/common/adminconsent?client_id=4099d059-adaf-4ee1-aa79-af1b961d180b

Das "Unverified" sollte sie bei kommerziellen Applikationen alarmieren. Jede Firme, die etwas auf sich hält, wird seine Domain über das Microsoft Partner Programm verifizieren. Geben Sie bitte nie einer App Rechte, die sie nicht kennen.
Siehe dazu auch Risiko orgweiter Consent
- Grant tenant-wide admin consent to an
application
https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/grant-admin-consent - Configure the admin consent workflow
https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/configure-admin-consent-workflow - Convert single-tenant app to multitenant
on Microsoft Entra ID
https://learn.microsoft.com/en-us/entra/identity-platform/howto-convert-app-to-be-multi-tenant
Nachdem ich die "richtige" SAML2-URL aufrufe und der Admin oder User vorher seinen "Consent" erteilt hat, konnte ich auch Identitäten anderer Tenants und sogar Microsoft Konten zur Anmeldung nutzen.
Hinweis: Ich kann als Webseitenbetreiber
hier nicht heimlich im Hintergrund einen Besucher zu einem
Aufruf der Entra ID-URLs verleiten um ihn aus seiner
Anonymität zu zu holen. Das geht nur, wenn es einen Consent
zu meiner App gibt. Ansonsten bekommt der Benutzer die
Anfrage.
Wenn Sie also eine Webseite besuchen, auf plötzlich eine
Consent-Abfrage kommt, dann sollten Sie skeptisch werden
Anmeldelog im Usertenant JA
Anmeldelog im Apptenant JA
Anmeldeprotokolle
Wenn ein Anwender des Tenant A ein Ticket für eine Applikation in Tenant A anfordert, dann hinterlässt dies eine Spur in den Sign-in Logs. Aber das gilt auch für Anwender aus anderen Identity-Systemen, d.h. anderen Tenants als auch Microsoft-Konten. Hier schaue ich immer erst einmal in die Enterprise Applikation zur App.

Sie sehen hier alle Anwender, die sich an der App authentifiziert haben. Ich habe hier alle drei Klassen (Same Tenant, anderer Tenant, Microsoft Konto) dabei. Im Sign-In-Log des User-Tenants sehe ich die Anmeldung meiner Anwender an einer entsprechenden App.

So kann ich als Administrator erkennen, welche Apps die Benutzer verwenden. Im Anmeldeforest gibt es die Enterprise App, nachdem jemand "Consent" gewährt hat.
Provisioning mit SAML-Token
Die Identität und Authentifizierung ist im Anmeldetenant hinterlegt. Ihre Applikation muss natürlich auch die Anwender "kennen" und viele Applikationen speichern zum Anwender auch Rollen und Einstellungen ab. Wenn Sie die Konten in der Anwendung nicht manuell pflegen wollen, dann sollten Sie einen irgendwie gearteten Verzeichnisabgleich überlegen, damit sie Änderungen bei Benutzern und Gruppen zeitnah mitbekommen. Ihre Applikation kann dazu z.B. per Graph auf ihr Entra ID oder per SCIM von Entra ID über Änderungen informiert werden. Umgekehrt könnten Sie natürlich auch mit eigenen Tools die Informationen in die jeweilige Applikation übertragen
Als "Lite"-Lösung kann ihre Applikation natürlich auch einfach die Informationen aus dem SAML-Token verwenden. Dort steht zumindest schon einmal der Anmeldename und Displayname drin. Über Custom Claim Rules und entsprechende Anforderungen kann ihr App natürlich noch weitere Felder anfordern, die sie dann verwenden können. Ohne Verzeichnisabgleich bekommen Sie aber nie zuverlässig mit, wann ein Benutzer z.B. nicht mehr aktiv ist oder sich der UPN geändert hat. Ihre App würde dann Altlasten weiter mit sich führen und bei Umbenennungen (Heirat/Scheidung) einen neuen doppelten Benutzer anlegen, wenn Sie nicht die Werte aus TenantID und ObjectID des SAML-Token als primären Schlüssel nutzen.
Aber es ist denkbar und nutzbar und als Dienstleister, der nach angelegten Benutzern bezahlt, hätten Sie zumindest kurzfristig sogar einen Vorteil. Zumindest bis der Kunde den Benutzer löscht oder das Konto aufgrund Inaktivität gelöscht wird. Das ist aber knifflig, wenn am Benutzer auch Daten hängen.
Selbst ausprobieren
Ich lasse die PHP-Testseite aktuell noch bereitgestellt. Ihr könnte gerne die URLs entsprechend aufrufen und nach Gewährung des Consent sehr ihr auch euer decodiertes Token.
Hinweis:
Ich behalte mir vor, bei Missbrauch die Seiten ohne
Vorankündigung vom Netz zu nehmen. Ich protokolliere die
Aufrufe und auch die UPNs der SAML-Tokens. Wenn Sie dies
nicht möchten, dann nutzen Sie den Download der Quellen auf
dieser Seite und richten diese in ihrem eigenen Webhosting
ein
Folgende URLs funktionieren wie folgt. Sie nicht "anklickbar". Kopieren Sie die URL und tragen diese in die Adressleiste in ihrem Browser ein.
https://www.msxfaq.de/test/saml/index1.php - Single Tenant und
sollte nur mit Konten aus msxfaqdev.onmicrosoft.com
funktionieren
https://www.msxfaq.de/test/saml/index2.php - Multitenant und
Microsoft Konto (LiveID/Passport).
https://www.msxfaq.de/test/saml/index3.php - Multitenant ohne
Microsoft Konto (LiveID/Passport)
https://www.msxfaq.de/test/saml/index4.php - nur Microsoft Konto (LiveID/Passport)
und sollte mit jedem Entra ID Konto funktionieren
Die erste URL mit index1.php ist für ihren Test wertlos aber die weiteren drei URLs sollten funktionieren.
Weitere Links
- Primary Refresh Token (PRT)
- Seamless Single Sign On
- SAML und Preauthentication
- Risiko orgweiter Consent
- Grant tenant-wide admin consent to an
application
https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/grant-admin-consent - Configure the admin consent workflow
https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/configure-admin-consent-workflow - Convert single-tenant app to multitenant
on Microsoft Entra ID
https://learn.microsoft.com/en-us/entra/identity-platform/howto-convert-app-to-be-multi-tenant
















