Identity provider integration with FedCM
Dieser Artikel beschreibt alle Schritte, die ein Identitätsanbieter (IdP) unternehmen muss, um sich in die Federated Credential Management (FedCM) API zu integrieren.
Schritte zur IdP-Integration
Um sich in FedCM zu integrieren, muss ein IdP Folgendes tun:
- Eine bekannte Datei bereitstellen, um den IdP zu identifizieren.
- Eine Konfigurationsdatei und Endpunkte bereitstellen für die Kontenliste und die Ausstellung von Bestätigungen (und optional, Client-Metadaten).
- Den Anmeldestatus aktualisieren mithilfe der Login Status API.
Eine bekannte Datei bereitstellen
Es gibt ein potenzielles Datenschutzproblem, bei dem ein IdP erkennen kann, ob ein Benutzer eine RP ohne ausdrückliche Zustimmung besucht hat. Dies hat Tracking-Auswirkungen, daher muss ein IdP eine bekannte Datei bereitstellen, um seine Identität zu verifizieren und dieses Problem zu mildern.
Die gut bekannte Datei wird über eine unautorisierte GET
-Anfrage angefordert, die keine Umleitungen verfolgt. Dies verhindert effektiv, dass der IdP erfährt, wer die Anfrage gestellt hat und welche RP eine Verbindung versucht.
Die bekannte Datei muss vom eTLD+1 des IdP unter /.well-known/web-identity
bereitgestellt werden. Zum Beispiel, wenn die IdP-Endpunkte unter https://accounts.idp.beispiel/
bereitgestellt werden, müssen sie eine bekannte Datei unter https://idp.beispiel/.well-known/web-identity
bereitstellen. Der Inhalt der bekannten Datei sollte die folgende JSON-Struktur haben:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
Das Mitglied provider_urls
sollte ein Array von URLs enthalten, die auf gültige IdP-Konfigurationsdateien verweisen, mit denen RPs interagieren können. Die Array-Länge ist derzeit auf ein Element begrenzt.
Der HTTP-Header Sec-Fetch-Dest
Alle Anfragen, die vom Browser über FedCM gesendet werden, enthalten einen
-Header. Alle IdP-Endpunkte, die autorisierte Anfragen empfangen (d.h. Sec-Fetch-Dest
: webidentityaccounts_endpoint
und id_assertion_endpoint
), müssen bestätigen, dass dieser Header enthalten ist, um sich gegen CSRF-Angriffe zu schützen.
Eine Konfigurationsdatei und Endpunkte bereitstellen
Die IdP-Konfigurationsdatei listet die Endpunkte auf, die der Browser benötigt, um den Identitätsföderationsprozess zu verarbeiten und die Anmeldungen zu verwalten. Die Endpunkte müssen mit der Konfiguration origen sein.
Der Browser macht eine unautorisierte Anfrage nach der Konfigurationsdatei über die GET
-Methode, die keine Weiterleitungen verfolgt. Dies verhindert effektiv, dass der IdP erfährt, wer die Anfrage gestellt hat und welche RP eine Verbindung versucht.
Die Konfigurationsdatei (gehostet unter https://accounts.idp.beispiel/config.json
in unserem Beispiel) sollte die folgende JSON-Struktur haben:
{
"accounts_endpoint": "/accounts.php",
"client_metadata_endpoint": "/client_metadata.php",
"id_assertion_endpoint": "/assertion.php",
"login_url": "/login",
"branding": {
"background_color": "green",
"color": "0xFFEEAA",
"icons": [
{
"url": "https://idp.example/icon.ico",
"size": 25
}
]
}
}
Die Eigenschaften sind wie folgt:
accounts_endpoint
-
Die URL für den Kontenlisten-Endpunkt, der eine Liste von Konten zurückgibt, bei denen der Benutzer derzeit beim IdP angemeldet ist. Der Browser verwendet diese, um eine Liste von Anmeldeoptionen zu erstellen, die dem Benutzer in der browserbereitgestellten FedCM-Benutzeroberfläche angezeigt werden.
client_metadata_endpoint
Optional-
Die URL für den Endpunkt der Client-Metadaten, die URLs bereitstellt, die auf die Metadaten und die Nutzungsbedingungen des RP verweisen und in der FedCM-Benutzeroberfläche verwendet werden sollen.
id_assertion_endpoint
-
Die URL für den ID-Bestätigungs-Endpunkt, welcher, wenn gültige Benutzeranmeldeinformationen gesendet werden, mit einem Validierungstoken antworten sollte, das das RP verwenden kann, um die Authentifizierung zu validieren.
login_url
-
Die Anmeldeseite URL, um sich beim IdP anzumelden.
branding
Optional-
Enthält Markierungsinformationen, die in der vom Browser bereitgestellten FedCM-Benutzeroberfläche verwendet werden, um das Aussehen nach dem Wunsch des IdP anzupassen.
Die folgende Tabelle fasst die verschiedenen Anfragen zusammen, die von der FedCM API gemacht werden:
Endpunkt/Ressource | Methode | Autorisiert (mit Cookies) | Enthält Origin |
---|---|---|---|
well-known /config.json |
GET |
Nein | Nein |
accounts_endpoint |
GET |
Ja | Nein |
client_metadata_endpoint |
GET |
Nein | Ja |
id_assertion_endpoint |
POST |
Ja | Ja |
Hinweis: Eine Beschreibung des FedCM-Flusses, in dem auf diese Endpunkte zugegriffen wird, finden Sie unter FedCM Anmeldefluss.
Hinweis: Keine der von der FedCM API an die hier detaillierten Endpunkte gesendeten Anfragen erlauben das Nachverfolgen von Weiterleitungen, um Datenschutz zu gewährleisten.
Der Kontenlisten-Endpunkt
Der Browser sendet autorisierte Anfragen (d.h. mit einem Cookie, das den angemeldeten Benutzer identifiziert) an diesen Endpunkt über die GET
-Methode. Die Anfrage hat kein client_id
-Parameter, Origin
-Header oder Referer
-Header. Dies verhindert effektiv, dass der IdP erfährt, zu welcher RP sich der Benutzer anzumelden versucht. Die zurückgegebene Kontenliste ist RP-neutral.
Zum Beispiel:
GET /accounts.php HTTP/1.1
Host: idp.example
Accept: application/json
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
Die Antwort auf eine erfolgreiche Anfrage gibt eine Liste aller IdP-Konten zurück, mit denen der Benutzer derzeit angemeldet ist (nicht spezifisch für eine bestimmte RP), mit einer JSON-Struktur, die dem folgenden Muster entspricht:
{
"accounts": [
{
"id": "john_doe",
"given_name": "John",
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"approved_clients": ["123", "456", "789"],
"login_hints": ["john_doe", "john_doe@idp.example"]
},
{
"id": "johnny",
"given_name": "Johnny",
"name": "Johnny",
"email": "johnny@idp.example",
"picture": "https://idp.example/profile/456",
"approved_clients": ["abc", "def", "ghi"],
"login_hints": ["johnny", "johnny@idp.example"]
}
]
}
Dies beinhaltet die folgenden Informationen:
id
-
Die eindeutige ID des Benutzers.
name
-
Der Familienname des Benutzers.
email
-
Die E-Mail-Adresse des Benutzers.
given_name
Optional-
Der Vorname des Benutzers.
picture
Optional-
Die URL des Avatarbilds des Benutzers.
approved_clients
Optional-
Ein Array von RP-Clients, bei denen der Benutzer registriert ist.
login_hints
Optional-
Ein Array von Zeichenfolgen, die das Konto darstellen. Diese Zeichenfolgen werden verwendet, um die Liste der Kontenoptionen zu filtern, die der Browser dem Benutzer zur Anmeldung anbietet. Dies erfolgt, wenn die
loginHint
-Eigenschaft innerhalb vonidentity.providers
in einem verwandtenget()
-Aufruf bereitgestellt wird. Jedes Konto mit einer Zeichenfolge in seinemlogin_hints
-Array, das mit dem bereitgestelltenloginHint
übereinstimmt, wird aufgenommen.
Hinweis: Wenn der Benutzer bei keinen IdP-Konten angemeldet ist, sollte der Endpunkt mit HTTP 401 (Unauthorized) antworten.
Der Client-Metadaten-Endpunkt
Der Browser sendet unautorisierte Anfragen an diesen Endpunkt über die GET
-Methode, wobei die clientId
, die im get()
-Aufruf übergeben wird, als Parameter dient.
Zum Beispiel:
GET /client_metadata.php?client_id=1234 HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Accept: application/json
Sec-Fetch-Dest: webidentity
Die Antwort auf eine erfolgreiche Anfrage umfasst URLs, die auf die Metadaten und Nutzungsbedingungsseiten des RP verweisen, um in der vom Browser bereitgestellten FedCM-Benutzeroberfläche verwendet zu werden. Dies sollte der unten gesehenen JSON-Struktur folgen:
{
"privacy_policy_url": "https://rp.example/privacy_policy.html",
"terms_of_service_url": "https://rp.example/terms_of_service.html"
}
Der ID-Bestätigungs-Endpunkt
Der Browser sendet autorisierte Anfragen an diesen Endpunkt über die POST
-Methode mit einem Inhaltstyp von application/x-www-form-urlencoded
. Die Anfrage enthält auch eine Nutzlast mit Details über die versuchte Anmeldung und das zu validierende Konto.
Es sollte folgendermaßen aussehen:
POST /assertion.php HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity
account_id=123&client_id=client1234&nonce=Ct60bD&disclosure_text_shown=true&is_auto_selected=true
Eine Anfrage an diesen Endpunkt wird als Ergebnis davon gesendet, dass ein Benutzer ein Konto zur Anmeldung aus der relevanten Browser-Oberfläche auswählt. Wenn gültige Benutzeranmeldeinformationen gesendet werden, sollte dieser Endpunkt mit einem Validierungstoken antworten, das das RP verwenden kann, um den Benutzer auf seinem eigenen Server zu validieren, entsprechend den von dem IdP verwendeten Anweisungen für die Identitätsföderation. Sobald das RP den Benutzer validiert, können sie ihn anmelden, ihn für ihren Dienst registrieren usw.
{
"token": "***********"
}
Die Anfrage-Nutzlast enthält die folgenden Parameter:
client_id
-
Die RP-Client-ID (die der
clientId
aus der ursprünglichenget()
-Anfrage entspricht). account_id
-
Die eindeutige ID des Benutzerkontos, das angemeldet werden soll (die der Benutzer-ID aus der Antwort des Kontenlisten-Endpunkts entspricht).
nonce
Optional-
Der Anfrage-Nonce, bereitgestellt vom RP.
disclosure_text_shown
-
Eine Zeichenfolge
"true"
oder"false"
, die angibt, ob der Offenlegungstext angezeigt wurde oder nicht. Der Offenlegungstext ist die Information, die dem Benutzer gezeigt wird (welche die Nutzungsbedingungen und Datenschutzrichtlinien-Links enthalten kann, wenn bereitgestellt), wenn der Benutzer beim IdP angemeldet ist, aber kein Konto speziell bei der aktuellen RP hat (in diesem Fall müsste er sich entschließen, "Weiter machen als..." mit seiner IdP-Identität und dann ein entsprechendes Konto bei der RP erstellen). is_auto_selected
-
Eine Zeichenfolge
"true"
oder"false"
, die angibt, ob die Anmeldevalidierungsanfrage als Ergebnis der automatischen Neuauthentifizierung ohne Benutzervermittlung ausgegeben wurde. Dies kann auftreten, wenn derget()
-Aufruf mit einermediation
-Option von"optional"
oder"silent"
erfolgt. Es ist nützlich für den IdP zu wissen, ob eine automatische Neuauthentifizierung stattgefunden hat, für die Leistungsauswertung und falls höhere Sicherheit gewünscht wird. Zum Beispiel könnte der IdP einen Fehlercode zurückgeben, der dem RP mitteilt, dass es eine ausdrückliche Benutzervermittlung benötigt (mediation="required"
).
Hinweis:
Wenn der get()
-Aufruf erfolgreich ist, wird der is_auto_selected
-Wert auch über die [
IdentityCredential.isAutoSelected](/de/docs/Web/API/IdentityCredential/isAutoSelected)
-Eigenschaft dem RP mitgeteilt.
ID-Bestätigungs-Fehlerantworten
Wenn der IdP keinen Token ausstellen kann — zum Beispiel, wenn der Client unautorisiert ist — wird der ID-Bestätigungs-Endpunkt mit einer Fehlerantwort antworten, die Informationen über die Art des Fehlers enthält. Zum Beispiel:
{
"error": {
"code": "access_denied",
"url": "https://idp.example/error?type=access_denied"
}
}
Die Fehlerantwortfelder sind wie folgt:
code
Optional-
Eine Zeichenfolge. Dies kann ein bekannter Fehler aus der OAuth 2.0 spezifizierten Fehlerliste sein oder eine beliebige Zeichenfolge.
url
Optional-
Eine URL. Dies sollte eine Webseite sein, die menschenlesbare Informationen über den Fehler enthält, um den Benutzern zu zeigen, wie z.B. wie der Fehler behoben werden kann oder wie der Kunde kontaktiert werden kann. Die URL muss gleichseitig mit der IdP-Konfigurations-URL sein.
Diese Informationen können auf verschiedene Weisen verwendet werden:
- Der Browser kann eine benutzerdefinierte Benutzeroberfläche anzeigen, um dem Benutzer zu mitteilen, was schiefgelaufen ist (siehe die Chrome-Dokumentation für ein Beispiel). Beachten Sie jedoch, dass der IdP-Server offensichtlich keine Informationen zurückgeben kann, wenn die Anfrage fehlschlug, weil der IdP-Server nicht verfügbar ist. In solchen Fällen wird der Browser dies über eine generische Nachricht melden.
- Der zugehörige RP
navigator.credentials.get()
-Aufruf, der zur Anmeldung verwendet wird, wird seine Promise mit einemIdentityCredentialError
zurückweisen, der die Fehlerinformationen enthält. Ein RP kann diesen Fehler abfangen und dann die benutzerdefinierte Benutzeroberfläche des Browsers mit einigen Informationen ergänzen, um dem Benutzer zu helfen, in einem zukünftigen Anmeldeversuch erfolgreich zu sein.
Anmeldestatus aktualisieren mithilfe der Login Status API
Die Login Status API ermöglicht es einem IdP, einen Browser über seinen Anmeldestatus in diesem bestimmten Browser zu informieren — damit meinen wir "ob irgendwelche Benutzer beim IdP im aktuellen Browser angemeldet sind oder nicht". Der Browser speichert diesen Zustand für jeden IdP; die FedCM-API verwendet ihn, um die Anzahl der Anfragen an den IdP zu reduzieren (weil keine Zeit mit Anfragen nach Konten verschwendet werden muss, wenn keine Benutzer beim IdP angemeldet sind). Es mildert auch potenzielle Timing-Angriffe.
Für jeden bekannten IdP (identifiziert durch seine Konfigurations-URL) speichert der Browser eine tri-staatliche Variable, die den Anmeldestatus mit drei möglichen Werten darstellt:
"logged-in"
: Der IdP hat mindestens ein Benutzerkonto angemeldet. Beachten Sie, dass zu diesem Zeitpunkt das RP und der Browser nicht wissen, welcher Benutzer das ist. Informationen über spezifische Benutzer werden später im FedCM-Fluss vomaccounts_endpoint
des IdP zurückgegeben."logged-out"
: Alle IdP-Konten sind derzeit abgemeldet."unknown"
: Der Anmeldestatus dieses IdP ist nicht bekannt. Dies ist der Standardwert.
Anmeldestatus setzen
Der IdP sollte seinen Anmeldestatus aktualisieren, wenn sich ein Benutzer beim IdP an- oder abmeldet. Dies kann auf zwei verschiedene Arten geschehen:
-
Der
Set-Login
HTTP-Antwortheader kann in einer Top-Level-Navigation oder einer gleichartigen Subresource-Anfrage gesetzt werden:httpSet-Login: logged-in Set-Login: logged-out
-
Die Methode
Navigator.login.setStatus()
kann von der IdP-Quelle aufgerufen werden:js/* Set logged-in status */ navigator.login.setStatus("logged-in"); /* Set logged-out status */ navigator.login.setStatus("logged-out");
Wie sich der Anmeldestatus auf den föderierten Anmeldefluss auswirkt
Wenn eine RP versucht, sich föderiert anzumelden, wird der Anmeldestatus überprüft:
- Wenn der Anmeldestatus
"logged-in"
ist, wird eine Anfrage an den Kontenlisten-Endpunkt des IdP gestellt und verfügbare Konten zur Anmeldung werden dem Benutzer im browserbereitgestellten FedCM-Dialog angezeigt. - Wenn der Anmeldestatus
"logged-out"
ist, wird die von der FedCMget()
-Anfrage zurückgegebene Promise ohne Anfrage an den Kontenlisten-Endpunkt abgelehnt. In einem solchen Fall liegt es am Entwickler, den Ablauf zu handhaben, indem der Benutzer beispielsweise aufgefordert wird, sich bei einem geeigneten IdP anzumelden. - Wenn der Anmeldestatus
"unknown"
ist, wird eine Anfrage an den Kontenlisten-Endpunkt des IdP gestellt und der Anmeldestatus wird basierend auf der Antwort aktualisiert:- Wenn der Endpunkt eine Liste verfügbarer Konten zur Anmeldung zurückgibt, aktualisieren Sie den Status auf
"logged-in"
und zeigen die Anmeldeoptionen im browserbereitgestellten FedCM-Dialog an. - Wenn der Endpunkt keine Konten zurückgibt, aktualisieren Sie den Status auf
"logged-out"
; die von der FedCMget()
-Anfrage zurückgegebene Promise wird dann abgelehnt.
- Wenn der Endpunkt eine Liste verfügbarer Konten zur Anmeldung zurückgibt, aktualisieren Sie den Status auf
Was, wenn der Anmeldestatus des Browsers und der IdP nicht synchron sind?
Trotz der Login Status API, die den Browser über den Anmeldestatus des IdP informiert, ist es möglich, dass Browser und IdP nicht synchron sind. Zum Beispiel könnten IdP-Sitzungen ablaufen, was bedeutet, dass alle Benutzerkonten abgemeldet sind, aber der Anmeldestatus weiterhin auf "logged-in"
gesetzt ist (die Anwendung konnte den Anmeldestatus nicht auf "logged-out"
setzen). In einem solchen Fall wird, wenn eine föderierte Anmeldung versucht wird, eine Anfrage an den Kontenlisten-Endpunkt des IdP gestellt, jedoch keine verfügbaren Konten zurückgegeben, da die Sitzung nicht mehr verfügbar ist.
Wenn dies geschieht, kann der Browser einem Benutzer dynamisch erlauben, sich durch Öffnen der Anmeldeseite des IdP in einem Dialog beim IdP anzumelden (die Anmelde-URL befindet sich in der Konfigurationsdatei des IdP als login_url
). Die genaue Natur dieses Ablaufs hängt vom Browser ab; beispielsweise handelt Chrome es wie folgt.
Sobald der Benutzer beim IdP angemeldet ist, sollte der IdP:
- Den Browser darüber informieren, dass der Benutzer sich angemeldet hat, indem der Anmeldestatus gesetzt wird auf
"logged-in"
. - Den Anmeldedialog durch Aufrufen der Methode
IdentityProvider.close()
schließen.
Siehe auch
- Federated Credential Management API auf developers.google.com (2023)