Links
Screencast
Vorbemerkungen
AAD B2C wird grob gesagt so konfiguriert, dass man sich in einer Art Stammdatenbereich Dinge zurechtbaut, die man dann später im Rahmen der Policies “zusammenstrickt” und somit nutzt. Beide Themen werden in diesem Artikel behandelt. Das Ganze wäre ziemlich unverständlich, wenn ich nicht auch gleich ein einfaches Beispiel zur Nutzung beisteuern würde. Daher endet dieser Artikel in einer Anleitung für die Erstellung einer einfachen Website mit AAD-B2C-Authentifizierung über das Visual Studio.
Identity Provider
Bei einem neu erzeugten AAD B2C ist standardmäßig erst einmal immer ein sog. “Local account” eingerichtet. Es gibt hier die beiden Optionen “Email” und “Username”. “Email” ist hier der Standard:
Um jetzt zu verstehen, was “Local accounts” bedeutet, sollte man sich bewusst machen, wie OpenId (die hinter B2C liegende Technologie) auf einer sehr hohen Ebene funktioniert:
Den meisten bekannt dürfte die Spielart sein, bei der man einen sozialen Account benutzt, um sich gegen irgend eine Webseite zu authentifizieren. Hierbei stellt der Anbieter des sozialen Kontos (z.B. Facebook) einen OpenId-Server bereit. Die eigene Webseite leitet dann Authentifizierungs-Request an diesen Server per OAuth 2.0 weiter und vertraut der Aussage dieses Servers dann. Alle Benutzerinformationen verbleiben auf Seiten des Anbieters und werden auch nur dort gepflegt.
“Local accounts” bedeutet nun in unserem Kontext, dass es möglich sein soll, sich mit Benutzerinformationen zu registrieren und anzumelden, die durch Microsoft im AAD B2C gespeichert werden. Wir brauchen uns also nicht um Details, wie sicheres Speichern von Kennwörtern, Kennwort-Vergessen-Umsetzung, Mail-Validierung etc. kümmern.
AAD B2C kann nicht ohne lokale Accounts konfiguriert werden!
Der Übersicht halber möchte ich noch kurz die zum aktuellen Zeipunkt (Dezember 2018) verfügbaren Social Identity Provider aus Abb. 2 aufführen:
- Microsoft Account (früher Live ID)
- Amazon
- GitHub
In Abb. 2 ist AAD als Option unter “Custom” aufgeführt. Wir kommen noch zu benutzerdefinierten Providern. An dieser Stelle soll der Hinweis reichen, dass die gelisteten sozialen Netzwerke nur fertig konfigurierte Templates darstellen. Mit benutzerdefinierten Providern kann man beliebige OpenId-konforme Identity Provider erstellen.
Identity Provider am Beispiel von Google
Um exemplarisch die Vorgehensweise für die Anbindung an ein soziales Netzwerk zu zeigen, werde ich hier anhand von Google Schritt für Schritt erläutern, was zu tun ist. Die Details hängen natürlich vom jeweiligen Provider ab und müssen in dessen Doku nachgelesene werden.
1. Zugriff auf Google erhalten
Zunächst müssen wir auf der Seite von Google bekannt machen, dass da gleich ein AAD B2C das Recht haben soll, Benutzer von Google authentifizieren zu lassen. Dazu benötigt man einen eigenen Account bei Google mit dem man sich dann auf der Google Developer Console anmeldet.
Im oberen Bereich sollte man nun ein neues Projekt bei Google anlegen:
Als nächstes ist links im Hauptmenu der Punkt “Anmeldedaten” auszuwählen:
Bei einem neuen Projekt muss zunächst die OAuth-Basiseinstellung vorgenommen werden:
- Der
Name der Anwendung
kann frei gewählt werden - Man kann (und sollte) ein
Logo der Anwendung
auswählen, weil dies später dem End-Benutzer angezeigt wird, wenn Google in “unserem” Namen eine Authentifizierung durchführen soll - Als
Authorisierte Domain
mussb2clogin.com
eingetragen werden, weil dies die Ursprungsdomain der Anfragen des AAD B2C an Google sein wird. - Nach einem Klick auf
Speichern
geht es weiter mit der Einrichtung der Anmeldedaten.
In Abb. 5 ist der Reiter Anmeldedaten
oben zu sehen. Wenn also der Einrichtungs-Assistent nicht von allein auf dieses Tab geht, kann man es selbst immer wieder anklicken und muss dann den Button zur Anlage neuer Login-Daten anklicken. Wie auch immer, jetzt sollte folgender Dialog erscheinen:
- Als
Anwendungstyp
wirdWebanwendung
gewählt. - Ein frei wählbarer
Name
wird vergeben. - Unter
Authortisierte JavaScript-Quellen
wirdhttps://[TENANTNAME].b2clogin.com
eingegeben. Da mein Tenant “codingfreaks” benannt wurde, wähle ich alsohttps://codingfreaks.b2clogin.com
. Es handelt sich hier technisch um eine CORS-Einstellung, sodass also keine entsprechenden Fehler im Browser erscheinen, weil Google unsere AAD-B2C-Domain nicht als valide Quelle anerkennt. - Unter
Autorisierte Weiterleitungs-URIs
muss nun noch eine URL mit dem Musterhttps://[TENANTNAME].b2clogin.com/[TENANTNAME].onmicrosoft.com/oauth2/authresp
eingetragen werden. Hier ist es wichtig darauf zu achten, dass der Name des Tenants 2 mal ersetzt werden muss. In meinem Beispiel alsohttps://codingfreaks.b2clogin.com/codingfreaks.onmicrosoft.com/oauth2/authresp
Nachdem man in diesem Dialog auf Speichern geklickt hat, erscheint der folgende Dialog:
Die beiden Zeichenketten kopiert man sich nun am Besten irgendwohin und weiter gehts.
2. Social Provider im AAD B2C einrichten
Zurück im AAD-B2C-Portal gilt es nun, den Google-Provider einzurichten. Das ist nun denkbar einfach.
Zunächst im AAD-B2C-Blade auf Providers auf Identity Providers
klicken und hier dann Add
auswählen:
Es erscheint ein Dialog in dem wir zuerst einen Namen für den Provider vergeben (sinnvollerweise hier “Google”) und dann als eigentlichen Provider Google
auswählen:
Sobald wir bei der Provider-Auswahl “OK” klicken, erscheint ein dritter Step für das Setup des Providers. Hier tragen wir nun die zuvor aus Google kopierten Informationen ein:
Nach einem Klick auf “OK” ist der Provider fertig eingerichtet.
Policies
Fassen wir bis hierhin zusammen. Wir haben nun AAD B2C mitgeteilt, dass wir 2 unterscheidliche Authentifizierungen zulassen möchten. Zunächst verwaltet AAD B2C eigene Accounts und zwar mit einer E-Mail-Adresse als Benutzernamen. Außerdem ist nun das B2C mit Google verbunden.
Als nächstes müssen wir nun dem B2C mitteilen, welche Einstellungen bei einem Login-Versuch gelten sollen. Das erledigen wir mit sog. Policies. Es gibt insgesamt 6 Policy-Typen. Wir konzentrieren uns in diesem Teil erst einmal auf 2 von ihnen:
Sign-up or sign-in-policy
: Dieser Policytyp ist eine Kombination aus den ebenfalls vorhandenen Policy-TypenSign-up
und (Überraschung!)Sign-in
.Password reset policy
: Wird angewandt, wenn ein Benutzer sein Kennwort vergessen hat und dieses dann invalidiert.
Was sind denn nun aber Policies? Policies definieren einen Satz von Regeln, die im AAD B2C gespeichert werden. Je Policy-Typ können beliebig viele Policies angelegt werden. Die Anwendung entscheidet später, mit welcher Policy sie sich z.B. anmelden will. In Policies können folgende Einstellungen vordefiniert werden:
- Identity Provider die in einer Policy verwendet werden sollen.
- Definition von Details zu einer Policy (z.B., welche Informationen vom Benutzer während eines Logins gesammelt werden sollen). Diese variieren je nach Policy-Typ.
- Auswahl der Attribute, die als Claims an die Anwendung zurückgegeben werden sollen.
- OAuth-Einstellungen (z.B. Token-Timeouts)
- Nutzung von Multi-Faktor-Authentifizierung
- Anpassungen des User-Interfaces, das AAD B2C dem Benutzer während des jeweiligen Vorganges anzeigt (siehe Abb. 2 grüner Dialog in der Mitte)
- Internationalisierung (welche Sprachen soll der Dialog unterstützen)
Zum letzten Punkt ist festzuhalten, dass Microsoft aktuell folgende Locales unterstützt:
- bn-IN (Indien)
- cs (Tschechisch)
- da (Dänisch)
- de (Deutsch)
- el (Griechisch)
- en (Englisch)
- es (Spanisch)
- fi (Finnish)
- fr (Französisch)
- gu (Gujarati)
- hi (Hindi)
- hu (Ungarisch)
- it (Italienisch)
- ja (Japanisch)
- kn (Kannada - nicht das Land!)
- ko (Koreanisch)
- ml (Malayalam)
- mr (Marathi)
- ms (Malayisch)
- nb (Norwegisch)
- nl (Niederländisch)
- pa (Punjabi)
- pl (Polnisch)
- pt-BR (Portugiesisch - Brasilien)
- pt-PT (Portugiesisch - Portugal)
- ro (Rumänisch)
- ru (Russisch)
- sk (Slowenisch)
- sv (Schwedisch)
- ta (Tamilisch)
- te (Telugu)
- th (Thai)
- tr (Türkisch)
- zh-Hans (Chinesisch einfach)
- zh-Hant (Chinesisch traditionell)
Da sollte für jeden Bedarf etwas dabei sein. Aber Achtung: Die unterstützten Locales berücksichtigen natürlich nur die Teile des UI, die von Microsoft bereit gestellt werden. Schaltet man also die UI Customization
einer Policy ein, muss man sich um die Umsetzung der eigenen Inhalte selbst kümmern (wird Bestandteil eines eigenen Artikels).
Kurz gesagt definiert also eine Policy, wie sich ein Benutzer an einer Anwendung authentifiziert, die diese Policy nutzt. Dieses Konzept macht AAD B2C ziemlich flexibel, weil z.B. ein Admin die Policies anlegt und kommuniziert und ein Entwickler sie dann einfach nur konfiguriert (unten mehr dazu.)
Policy für Sign-In und Sign-Up anlegen
Wie oben erwähnt, brauchen wir zum Glück nicht 2 Policies anlegen, um die Login-Experience eines Users abzudecken. Es reicht, im Portal unter Sign-up or sign-in policies
auf Add
zu klicken:
Im ersten Schritt des Assistenten vergeben wir zunächst einen sprechenden Namen. Achtung: die Policy in meinem Beispiel in Abb. 12 wird später “B2C_1_” als Präfix bekommen. Das hätte Microsoft ruhig irgendwie im UI kenntlich machen können, und daher sage ich es hier. Also fängt jeder Policy-Name, die wir erstellen in Wahrheit mit der Zeichenkette “B2C_1_” an!
In Abb. 12 ist auch gleich zu sehen, dass ich die Provider “Google” und “Email signup” zulasse. Diese Policy wird dem User also die Wahl lassen, mit welchem der Provider er sich bei uns anmelden/registrieren möchte.
Je nach Szenario kann es wichtig sein, welche Informationen der Registrierungs-Prozess von einem Benutzer abfragt. Hier könnte man jetzt DSGVO-Alarm rufen! Ich bin kein Datenschutz-Experte und rate Euch daher nur: Weniger ist hier Mehr. Fragt also nur ab, was Ihr in Eurer Anwendung auch wirklich braucht. In meinem Beispiel möchte ich die Mail-Adresse der Eindeutigkeit halber und den Displayname der Darstellung wegen sammeln lassen. Alle anderen Informationen sind also optional.
Diese Settings sind bei einer Registrierung des Users über den internen Prozess noch relativ klar. Das User-Interface wird nur diese Infos abfragen. Bei einem Social Provider bedeutet es, dass das AAD B2C diese Infos gern vom Provider geliefert haben möchte. Achtet also darauf, dass Ihr hier nichts eintragt, was z.B. Google gar nicht liefern kann.
Nun müssen wir noch die sog. Application Claims
definieren:
Ich habe mich lange mit dem Begriff “Claim” im Kontext der Authentifizierung herumgeschlagen. Vereinfacht ausgedrückt ist ein Claim einfach eine Information, die in einem OAuth-Token mit drin steckt, der ja als Antwort von einem OpenId-Server an den Client gesendet wird. OAuth-Token (oder Bearer-Token oder JWT-Token oder wie auch immer) sind codierte Datenstrukturen, die man ohne Probleme dekodieren kann. Sie enthalten bestimmte Pflichtfelder, wie den Aussteller, die Gülktigkeitsdauer etc. aber halt auch zusätzliche Daten, die für die eigentliche Anwendung nützlich sein können.
Ich hake hier wieder die Mail und den Anzeigenamen an, damit meine Anwendung diese Infos aus dem Token lesen kann und ich nicht noch irgendeine API oder Datenbank danach “fragen” muss.
Die Einstellungen für Token, session & SSO config
, Multifactor authentication
, Page UI customization
, Password complexity
und Language customization
belasse ich für diese Teil der Serie auf Default und klicke auf Create
.
Nach ein paar Sekunden erscheint unsere neue Policy in der Liste:
Policy für Kennwort-Rücksendung anlegen
Wie später noch zu sehen sein wird, ist das Anlegen mindestens einer Password-Reset-Policy immer eine gute Idee. Also ans Werk.
Der nun erscheinende Assistent unterscheidet sich leicht von dem vorherigen:
Man kann gut erkennen, dass der Schritt für die Definition der Signup attributes
nicht dabei ist. Macht auch keinen Sinn, weil wir hier ja keine Sign-Up policy definieren. Also zunächst wieder einen griffigen Namen und dann die Auswahl der Provider.
Abb. 17 zeigt, dass “Google” hier nicht verfügbar ist. Auch logisch, wenn man sich bewusst macht, dass ein Google-Benutzer seinen Kennwort-Reset wenn überhaupt, dann bei Google auf der Seite vornimmt. Wir haben damit (OpenId sei dank) nichts mehr zu schaffen.
Die einzige weitere Einstellung, die ich vornehme ist, dass ich als Claim die Mail-Adresse angebe:
Das mache ich nur, falls ich in diesem Prozesschritt in der eigentlichen Anwendung Zugriff auf diese Info brauche.
Das war’s schon. Ein Klick auf Create
erzeugt nun auch diese Policy.
Anwendung anlegen
Der vorerst letzte Schritt im Azure Portal ist nun das Anlegen einer Application
im AAD-B2C-Portal. Das ist im Prinzip das Gleiche, wie wir weiter ob bei Google durchgeführt haben. Hier war das B2C eine Anwendung, die Benutzer durch Google authentifiziert haben will. D.h., dass B2C die OpenId-Schnittstelle von Google benutzen will und dafür muss man B2C bei Google als Anwendung registrieren.
Für unsere (noch zu schreibende) Anwendung wird das Gleiche gelten. Sie möchte das AAD B2C benutzen, um sich keine Gedanken mehr über die eigentliche Authentifizierung machen zu müssen. Damit sie genau das aber darf, muss sie im B2C bekannt sein. Genau dies werden wir jetzt veranlassen.
Im AAD-B2C-Blade kann man unter Applications
wieder auf Add
klicken:
Der sich öffnende Assistent muss nun noch ausgefüllt werden, wobei wir uns die Einstellungen hier im Moment erst einmal nur “wünschen”, denn es gibt ja noch keine App:
- Der
Name
ist völlig frei wählbar, sollte aber im besten Fall dem Titel der späteren Anwendung entsprechen. - Ich gebe an, dass es sich um eine
Web App / Web API
handelt. Das sind Begriffe aus dem Azure-Umfeld und deshalb möchte ich hier darauf hinweisen, dass AAD B2C in keinster Weise auf Azure-gehostete Dienste beschränkt ist. Es agiert selbst als standard-konformer OpenId-Server und daher stelle ich hier einfach nur ein, dass meine Anwendung etwas ist, dass über eine URL kommt. Dadurch spare ich mir im weiteren Verlauf die Definition eines Kennworts, weil das Kennwort die URL selbst ist. - Als
Reply URL
trage ich hier einfachhttps://localhost:44301/signin-oidc
ein. Das muss ich erklären. Ich erstelle hier eine App für mein lokales Debugging. Ich lege also fest, dass ich wenn ich die App testen will erwarte, dass diese lokal auf Port 44301 laufen wird. Ich erwarte außerdem, dass diese App mir “/signin-oidc” als Rückruf-Adresse liefert. Tut sie das nicht, wird AAD B2C einen Fehler schmeißen. Das heißt aber nicht, dass eine View “/signin-oidc” auf meiner Webanwendung geben muss!
Alle anderen Einstellungen lassen wir zunächst auf den Standard-Werten und klicken fröhlich auf Create
.
Das Ergebnis sollte dann ungefähr so aussehen:
Anwendung anlegen und testen
Der letzte Schritt in diesem Teil der Serie bietet nun endlich den Schulterschluss zwischen AAD B2C und der Entwicklerwelt - in meinem Fall wie immer Visual Studio. Wir legen einfach mal los.
Der schnellste Weg zum Glück ist File
-> New Project
-> ASP.NET Core Web Application
:
Der entscheidende Dialog ist nun der ASP.NET-Web-Konfigurator:
Ich wähle als Anwendungs-Template “Web Application”, damit wir einen Benutzer-Flow zu sehen bekommen. Ein Klick auf Change Authentication
bringt das Authentifizierungs-Setup.
Hier ist es wichtig zunächst links Individual User Accounts
auszuwählen. Wir wollen uns ja nicht auf Windows verlassen oder direkt einem Azure AD beitreten. Als Methode wählen wir dann ganz oben Connect to an existing user store in the cloud
aus. Meiner Meinung nach hätte Microsoft das ruhig irgendwie nach B2C benennen können, aber wer bin ich schon!
Die Optionen, die jetzt zum Vorschein kommen, sollten uns vertraut erscheinen:
- Der
Domain Name
ist der FQDN unseres AAD-B2C-Tenants, also [TENANTNAME].onmicrosoft.com (Ich werde in späteren Teilen noch etwas zu den Suffixen sagen). - Die
Application Id
ist die GUID aus Abb. 21, die bei der Erzeugung unserer App im AAD B2C generiert wurde. - Der
Callback Path
steht schon auf/signin-oidc
. Das ist so eine Art Quasi-Standard für OAuth-Callback-Adressen und daher hatte ich ihn bei der Einrichtung der App bereits verwendet. Der ”/” bedeutet hier, dass die komplette URL aus der Server-URL und dann diesem Pfad bestehen wird und passt somit zu unseren Einstellungen in der AAD-B2C-App. - Bei
Sign-up or Sign-in Policy
trage ich den Namen der entsprechenden Policy aus AAD B2C ein (also “B2C_1_sign_up_or_in”). - Bei
Reset Password Policy
trage ich den Namen der entsprechenden Policy aus AAD B2C ein (also “B2C_1_password_reset”).
Wie man sieht, ist die Angabe der beiden Policies zwingend erforderlich weshalb ich das im Schritt oben bereits rein genommen hatte.
Nachdem der Assistent abgeschlossen ist, müssen wir im Visual Studio eigentlich nur 2 Dinge im Auge behalten:
Die Datei launchSetting.json
im Ordner Properties
.
Diese Datei steuert in .NET-Core-Projekten, was passieren soll, wenn man eine Debugging-Session im VS startet. Sie ist so anzupassen, dass alle Ports richtig liegen und somit zu unseren AAD-B2C-Einstellungen passen:
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44301",
"sslPort": 44301
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"MyApp": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:44301",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Wie man sieht, habe ich den Port 44301 überall eingetragen. Soweit, so gut, könnte man denken, doch bei mir erscheint mit diesen Einstellungen nach einem beherzten F5
nur:
Toll!! Offensichtlich ist auf meinem System 44301 reserviert. Also muss ich den Port ändern! Also erst einmal an den 3 Stellen in Listing 1 44302 eintragen und F5
drücken.
Jetzt geht zwar die Webseite auf, doch bevor ich auf “Sign In” klicke, muss ich noch die Einstellungen im AAD B2C auf den neuen Port anpassen.
Im Azure-Portal klicke ich dazu auf meine Application:
Ich ersetze also den Port “44301” durch “44302”.
Zurück im Visual Studio kann ich nun tatsächlich F5
en:
Das ist schon mal genau das, was ich mit Google erreichen wollte. Man sieht schön, wie nach dem Klick auf “Google” im AAD-B2C-Standard-UI der Redirect zu Google erscheint und Google wiederum einen sog. “Consent” von mir einfordert. Die meisten kennen diese Bestätigung, die uns auch gleich mitteilt, welche Informationen die App haben möchte (Mail und Display name).
Doch wie sieht es mit dem anderen Identity Provider (E-Mail) aus? Debor wir das testen, sehen wir uns doch mal an, was nach der Registrierung (Sign-Up und Sign-In) über Google in AAD B2C angekommen ist.
Im AAD-B2C-Blade kann man Benutzer unter Users
verwalten:
In meinem Fall ist der obere Benutzer der, den ich gerade per Google authentifiziert habe. Er hat entsprechend als Quelle “Google” eingetragen. Dies entspricht dem Namen des Identity Providers. Darunter sieht man einen Benutzer mit der Quelle External Azure Active Directory
. Diesen Benutzer gibt es, weil das der Admin-User ist, mit dem ich das AAD B2C ursprünglich angelegt habe (siehe Teil 1).
Nun zu dem anderen Provider, der durch das AAD B2C selbst verwaltet wird. Ich logge mich aus der Session aus und wähle nach erneutem Klick auf “Sign In” nun den zweiten Weg. Dazu klicke ich auf der Sign-In-Page auf den Link “Sign up now” ganz unten. Dies öffnet den folgenden Dialog:
Ich muss zunächst eine Mail-Adresse eingeben und dann auf den Send verification code
-Button klicken. Sobald ich das tue, ändert sich der Dialog und eine Mail geht an die oben eingegebene Adresse raus. Sie enthält einen 6-stelligen Code und der wiederum muss in das neu erschienene Textfeld eingetragen werden:
Danach füllt man das Formular einfach weiter aus. Microsoft setzt dabei dankenswerterweise per default bereits einen anständigen Kennwort-Standard:
Beachten sollte man auch, dass unsere Policy greift und neben der Mail-Adresse nur den Display name einfordert:
Nach Klick auf Create
ist alles korrekt eingerichtet:
was man übrigens auch sofort im AAD-B2C-Portal prüfen kann:
Der neue Benutzer hat als Quelle Azure Active Directory
was uns also anzeigt, dass dies ein Benutzer ist, der durch das AAD B2C selbst verwaltet wird.
Fazit und Ausblick
Zugegeben, das war mal wieder ein mächtig langer Beitrag für einen Blog, aber ich wollte unbedingt ein vollständiges Bild vermitteln und wenigstens ein paar mögliche Stolpersteine (Ports) aufzeigen. Die meisten Probleme treten erfahrungsgemäß übrigens durch Tip- und Copy&Paste-Fehler auf. Die Technologie selbst ist recht stabil und wir setzen sie durchaus erfolgreich in Projekten ein.
Im nächsten Teil möchte ich mich mit der Einbindung eines Azure Active Directory als Identity Provider befassen und auch auf die Limitierungen in diesem Bereich eingehen.