Integration des Identitätsanbieters mit FedCM
Dieser Artikel beschreibt alle Schritte, die ein Identitätsanbieter (IdP) unternehmen muss, um sich in die Federated Credential Management (FedCM) API zu integrieren.
IdP-Integrationsschritte
Um sich in FedCM zu integrieren, muss ein IdP Folgendes tun:
- Eine well-known Datei bereitstellen, um den IdP zu identifizieren.
- Eine Konfigurationsdatei und Endpunkte bereitstellen für die Kontenliste und die Ausgabe von Assertionen (optional auch Client-Metadaten).
- Seinen Anmeldestatus aktualisieren mithilfe der Login Status API.
Eine well-known Datei bereitstellen
Es gibt ein mögliches Datenschutzproblem, bei dem ein IdP feststellen kann, ob ein Nutzer eine relying party (RP) ohne ausdrückliche Zustimmung besucht hat. Dies hat Implikationen für das Tracking, sodass ein IdP verpflichtet ist, eine well-known Datei bereitzustellen, um seine Identität zu verifizieren und dieses Problem zu mindern.
Die well-known Datei wird über einen nicht authentifizierten GET-Anruf angefordert, der keine Weiterleitungen verfolgt. Dies verhindert effektiv, dass der IdP erfährt, wer die Anfrage gestellt hat und welche RP versucht, eine Verbindung herzustellen.
Die well-known Datei muss vom eTLD+1 des IdP unter /.well-known/web-identity bereitgestellt werden. Wenn zum Beispiel die IdP-Endpunkte unter https://accounts.idp.example/ bereitgestellt werden, müssen sie eine well-known Datei unter https://idp.example/.well-known/web-identity bereitstellen. Der Inhalt der well-known Datei sollte die folgende JSON-Struktur haben:
{
"provider_urls": ["https://accounts.idp.example/config.json"]
}
Das provider_urls-Element sollte ein Array von URLs enthalten, das auf gültige IdP-Konfigurationsdateien verweist, die von RPs genutzt werden können, um mit dem IdP zu interagieren. Die Länge des Arrays ist aktuell auf eins begrenzt.
Der Sec-Fetch-Dest HTTP-Header
Alle Anfragen, die vom Browser über FedCM gesendet werden, enthalten einen Header. Alle IdP-Endpunkte, die authentifizierte Anfragen erhalten (d.h. Sec-Fetch-Dest: webidentityaccounts_endpoint und id_assertion_endpoint), müssen sicherstellen, dass dieser Header enthalten ist, um gegen CSRF-Angriffe zu schützen.
Eine Konfigurationsdatei und Endpunkte bereitstellen
Die IdP-Konfigurationsdatei bietet eine Liste der Endpunkte, die der Browser benötigt, um den Identitätsföderationsfluss zu verarbeiten und die Anmeldungen zu verwalten. Die Endpunkte müssen ursprungsgleich mit der Konfiguration sein.
Der Browser führt eine nicht authentifizierte Anfrage für die Konfigurationsdatei über die GET-Methode aus, die keine Weiterleitungen verfolgt. Dies verhindert effektiv, dass der IdP erfährt, wer die Anfrage gestellt hat und welche RP versucht, eine Verbindung herzustellen.
Die Konfigurationsdatei (beispielsweise gehostet unter https://accounts.idp.example/config.json) sollte die folgende JSON-Struktur haben:
{
"accounts_endpoint": "/accounts.php",
"account_label": "developer",
"supports_use_other_account": true,
"client_metadata_endpoint": "/client_metadata.php",
"disconnect_endpoint": "/disconnect.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 Endpunkt der Kontenliste, der eine Liste von Konten zurückgibt, bei denen der Nutzer derzeit beim IdP angemeldet ist. Der Browser verwendet diese, um eine Liste von Anmeldeoptionen zu erstellen, die dem Nutzer in der browserbereitgestellten FedCM-Benutzeroberfläche angezeigt wird.
account_labelOptional-
Ein String, der, falls vorhanden, einen Identifikator für eine Teilmenge von Konten angibt, die zurückgegeben werden sollen, wenn dieser IdP für die föderierte Authentifizierung verwendet wird. Wenn ein
get()-Anruf gemacht wird, werden nur Konten zurückgegeben, die in ihrenlabel_hints-Parametern mit diesem String übereinstimmen, von dem Kontenendpunkt. supports_use_other_accountOptional-
Ein boolescher Wert, der standardmäßig
falseist; wenn er auftruegesetzt ist, bedeutet dies, dass Benutzer sich mit einem anderen Konto anmelden können als dem, mit dem sie derzeit angemeldet sind (wenn der IdP mehrere Konten unterstützt). Dies gilt nur fürget()-Anrufe, die den aktiven Modus angeben.Hinweis: In der Anmeldeoberfläche des Browsers wird dies wahrscheinlich als eine Art "Anderes Konto wählen"-Schaltfläche erscheinen.
client_metadata_endpointOptional-
Die URL für den Client-Metadatenendpunkt, der URLs zu den Metadatenseiten und den Nutzungsbedingungen der RP bereitstellt, die in der FedCM-Benutzeroberfläche verwendet werden sollen.
disconnect_endpointOptional-
Die URL für den Disconnect-Endpunkt, der von der RP verwendet wird, um die Verbindung zum IdP über die
IdentityCredential.disconnect()-Methode zu trennen. id_assertion_endpoint-
Die URL für den ID-Assertions-Endpunkt, der bei Empfang gültiger Benutzeranmeldeinformationen mit einem Validierungstoken antworten sollte, das die RP verwenden kann, um die Authentifizierung zu validieren.
login_url-
Die Anmeldeseiten-URL, über die sich der Nutzer beim IdP anmelden kann.
brandingOptional-
Enthält Branding-Informationen, die in der browserbereitgestellten FedCM-Benutzeroberfläche verwendet werden, um deren Erscheinungsbild nach Wunsch des IdP anzupassen. Die bereitgestellte Symbolgröße muss mindestens
25(25px) im passiven Modus und mindestens40(40px) im aktiven Modus sein (siehe Aktiver versus passiver Modus für weitere Details).
Die folgende Tabelle fasst die verschiedenen Anfragen zusammen, die von der FedCM API gemacht werden:
| Endpunkt/Ressource | Methode | Mit Anmeldedaten (mit Cookies) | Enthält Origin |
|---|---|---|---|
well-known/config.json |
GET |
Nein | Nein |
accounts_endpoint |
GET |
Ja | Nein |
client_metadata_endpoint |
GET |
Nein | Ja |
disconnect_endpoint |
POST |
Ja | Ja |
id_assertion_endpoint |
POST |
Ja | Ja |
Hinweis: Eine Beschreibung des FedCM-Ablaufs, bei dem diese Endpunkte aufgerufen werden, finden Sie unter FedCM-Anmeldevorgang.
Hinweis: Keine der von der FedCM API an die hier beschriebenen Endpunkte gestellten Anfragen ermöglicht es aus Datenschutzgründen, Weiterleitungen zu folgen.
Der Kontenliste-Endpunkt
Der Browser sendet authentifizierte Anfragen (d.h. mit einem Cookie, das den angemeldeten Benutzer identifiziert) an diesen Endpunkt über die GET-Methode. Die Anfrage hat keinen client_id-Parameter, Origin-Header oder Referer-Header. Dies verhindert effektiv, dass der IdP erfährt, bei welcher RP der Nutzer sich anmelden möchte. Die zurückgegebene Kontenliste ist RP-agnostisch.
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, bei denen der Nutzer derzeit angemeldet ist (nicht spezifisch für eine bestimmte RP), mit einer JSON-Struktur, die der folgenden entspricht:
{
"accounts": [
{
"id": "elaina_maduro",
"given_name": "Elaina",
"name": "Elaina Maduro",
"email": "elaina_maduro@idp.example",
"tel": "+491234567890",
"username": "elaina420",
"picture": "https://idp.example/profile/123",
"approved_clients": ["123", "456", "789"],
"domain_hints": ["rp1.example.com", "rp3.example.com"],
"label_hints": ["developer", "admin"],
"login_hints": ["elaina_maduro", "elaina_maduro@idp.example"]
},
{
"id": "elly",
"given_name": "Elly",
"username": "elly123",
"email": "Elly@idp.example",
"picture": "https://idp.example/profile/456",
"approved_clients": ["abc", "def", "ghi"],
"domain_hints": ["rp1.example.com", "rp2.example.com"],
"label_hints": ["developer", "test"],
"login_hints": ["elly", "elly@idp.example"]
}
]
}
Dies umfasst die folgenden Informationen, wobei name, email, username und tel optional sind, aber mindestens eines von ihnen vorhanden und nicht leer sein muss.
id-
Die eindeutige ID des Benutzers.
nameOptional-
Der Familienname des Benutzers.
emailOptional-
Die E-Mail-Adresse des Benutzers.
telOptional-
Die Telefonnummer des Benutzers. Kann in jedem Format sein.
usernameOptional-
Der Benutzername des Benutzers.
given_nameOptional-
Der Vorname des Benutzers.
pictureOptional-
Die URL des Benutzer-Avatar-Bildes.
approved_clientsOptional-
Ein Array von RP-Clients, bei denen der Benutzer registriert ist.
domain_hintsOptional-
Ein Array von Domains, mit denen das Konto verknüpft ist. Die RP kann einen
get()-Anruf mit einerdomainHint-Eigenschaft machen, um die zurückgegebenen Konten nach Domain zu filtern. label_hintsOptional-
Ein Array von Strings, die Labels spezifizieren, die Kontotypen definieren, mit denen das Konto identifiziert wird. Wenn die Konfigurationsdatei einen
account_labelangibt, werden nur Konten zurückgegeben, die dieses Label in ihrenlabel_hintsenthalten. login_hintsOptional-
Ein Array von Strings, die das Konto darstellen. Diese Strings werden verwendet, um die Liste der Kontooptionen zu filtern, die der Browser dem Benutzer zum Anmelden anbietet. Dies geschieht, wenn die
loginHint-Eigenschaft innerhalb vonidentity.providersin einem zugehörigenget()-Anruf bereitgestellt wird. Jedes Konto mit einem String in seinemlogin_hints-Array, der mit dem bereitgestelltenloginHintübereinstimmt, wird eingeschlossen.
Hinweis: Wenn der Benutzer in keinem IdP-Konto angemeldet ist, sollte der Endpunkt mit HTTP 401 (Unauthorized) antworten.
Der Client-Metadatenendpunkt
Der Browser sendet unautorisierte Anfragen an diesen Endpunkt über die GET-Methode, wobei der clientId im get()-Anruf als Parameter übergeben wird.
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 enthält URLs, die auf die Metadaten- und Nutzungsbedingungen der RP-Seiten verweisen, die in der browserbereitgestellten FedCM-Benutzeroberfläche verwendet werden sollen. Dies sollte der folgenden JSON-Struktur entsprechen:
{
"privacy_policy_url": "https://rp.example/privacy_policy.html",
"terms_of_service_url": "https://rp.example/terms_of_service.html"
}
Der Disconnect-Endpunkt
Durch Aufrufen von IdentityCredential.disconnect() sendet der Browser eine Cross-Origin-POST-Anfrage mit Cookies und einem Content-Type von application/x-www-form-urlencoded an den Disconnect-Endpunkt mit den folgenden Informationen:
account_hint-
Ein String, der einen Konto-Hinweis angibt, den der IdP verwendet, um das Konto zu identifizieren, das getrennt werden soll.
client_id-
Ein String, der den Client-Identifikator der RP angibt.
Zum Beispiel:
POST /disconnect HTTP/1.1
Host: idp.example
Origin: rp.example
Content-Type: application/x-www-form-urlencoded
Cookie: 0x123
Sec-Fetch-Dest: webidentity
account_hint=account456&client_id=rp123
Beim Empfangen der Anfrage sollte der IdP-Server:
-
Auf die Anfrage mit CORS (Cross-Origin Resource Sharing) antworten.
-
Überprüfen, ob die Anfrage einen
Sec-Fetch-DestHTTP-Header mit der Direktivewebidentityenthält. -
Den
Origin-Header gegen den RP-Ursprung, der durch dieclient_idbestimmt wird, abgleichen. Das Versprechen wird abgelehnt, wenn sie nicht übereinstimmen. -
Das Konto finden, das dem
account_hintentspricht. -
Das Benutzerkonto von der Liste der verbundenen Konten der RP trennen.
-
Mit der identifizierten
account_iddes Benutzers im JSON-Format antworten:json{ "account_id": "account456" }
Hinweis:
Wenn der IdP alle mit der RP verbundenen Konten trennen möchte, kann er einen String übergeben, der mit keiner account_id übereinstimmt, zum Beispiel "account_id": "*".
Der ID-Assertions-Endpunkt
Der Browser sendet authentifizierte 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 den Anmeldeversuch und das Konto, das validiert werden soll.
Es sollte etwa so 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 der Benutzerwahl eines Kontos zum Anmelden in der relevanten Browser-Benutzeroberfläche gesendet. Wenn gültige Benutzeranmeldeinformationen gesendet werden, sollte dieser Endpunkt mit einem Validierungstoken antworten, das die RP verwenden kann, um den Benutzer auf ihrem eigenen Server zu validieren, gemäß den Anweisungen, die vom IdP für die Identitätsföderation bereitgestellt werden. Sobald die RP den Benutzer validiert hat, kann sie ihn anmelden oder ihn bei ihrem Dienst registrieren usw.
{
"token": "***********"
}
Die Anfrage-Nutzlast enthält die folgenden Parameter:
client_id-
Der Client-Identifikator der RP (der mit dem
clientIdaus dem ursprünglichenget()-Anruf übereinstimmt). account_id-
Die eindeutige ID des Benutzerkontos, das angemeldet werden soll (die mit der
iddes Benutzers aus der Antwort des Kontenlisten-Endpunkts übereinstimmt). nonceOptional-
Die Anforderungs-Nonce, die von der RP bereitgestellt wird.
disclosure_text_shown-
Ein String
"true"oder"false", der angibt, ob der Offenlegungstext angezeigt wurde oder nicht. Der Offenlegungstext ist die dem Benutzer angezeigte Information (die Links zu den Nutzungsbedingungen und der Datenschutzrichtlinie enthalten kann, falls vorhanden), wenn der Benutzer beim IdP angemeldet ist, aber kein spezielles Konto auf der aktuellen RP hat (in diesem Fall müsste er "Fortfahren als..." seine IdP-Identität wählen und dann ein entsprechendes Konto auf der RP erstellen). is_auto_selected-
Ein String
"true"oder"false", der angibt, ob die Authentifizierungsvalidierungsanfrage als Ergebnis der automatischen Neuauthentifizierung durchgeführt wurde, d.h. ohne Benutzermediation. Dies kann auftreten, wenn derget()-Anruf mit einermediation-Option von"optional"oder"silent"gestellt wird. Es ist nützlich für den IdP zu wissen, ob eine automatische Neuauthentifizierung stattgefunden hat, um die Leistung zu bewerten und für den Fall, dass höhere Sicherheit gewünscht wird. Beispielsweise könnte der IdP einen Fehlercode zurückgeben, der der RP mitteilt, dass eine explizite Benutzermediation erforderlich ist (mediation="required").
Hinweis:
Wenn der get()-Anruf erfolgreich ist, wird der is_auto_selected-Wert auch der RP über die IdentityCredential.isAutoSelected-Eigenschaft mitgeteilt.
CORS-Header für den ID-Assertions-Endpunkt
Die Antwort des ID-Assertions-Endpunkts muss die Access-Control-Allow-Origin- und Access-Control-Allow-Credentials-Header enthalten, und der Access-Control-Allow-Origin muss den Ursprung des Anfragestellers beinhalten:
Access-Control-Allow-Origin: https://rp.example
Access-Control-Allow-Credentials: true
Beachten Sie, dass der Access-Control-Allow-Origin auf den spezifischen Ursprung des Anfragestellers (der RP) gesetzt werden muss und nicht der Platzhalterwert * sein darf.
Ohne diese Header wird die Anfrage mit einem Netzwerksfehler fehlschlagen.
Fehlerantworten des ID-Assertions-Endpunkts
Wenn der IdP kein Token ausstellen kann — zum Beispiel, wenn der Client nicht autorisiert ist — antwortet der ID-Assertions-Endpunkt mit einer Fehlerantwort, die Informationen über die Art des Fehlers enthält. Zum Beispiel:
{
"error": {
"code": "access_denied",
"url": "https://idp.example/error?type=access_denied"
}
}
Die Felder der Fehlerantwort sind wie folgt:
codeOptional-
Ein String. Dies kann entweder ein bekannter Fehler aus der OAuth 2.0 spezifizierten Fehlerliste sein oder ein beliebiger String.
urlOptional-
Eine URL. Dies sollte eine Webseite sein, die menschenlesbare Informationen über den Fehler enthält, die den Benutzern angezeigt werden, z.B. wie der Fehler behoben werden kann oder wie der Kundendienst kontaktiert werden kann. Die URL muss ursprungsgleich mit der Konfigurations-URL des IdP sein.
Diese Informationen können auf verschiedene Arten verwendet werden:
- Der Browser kann dem Benutzer eine benutzerdefinierte Benutzeroberfläche anzeigen, die ihm mitteilt, was schief gelaufen ist (siehe die Chrome-Dokumentation für ein Beispiel). Beachten Sie, dass, wenn die Anfrage fehlgeschlagen ist, weil der IdP-Server nicht verfügbar ist, er offensichtlich keine Informationen zurückgeben kann. In solchen Fällen wird der Browser dies über eine generische Nachricht melden.
- Der zugehörige RP-
navigator.credentials.get()](/de/docs/Web/API/CredentialsContainer/get)-Anruf, der zur Anmeldeversuchung verwendet wurde, wird das Versprechen mit einemIdentityCredentialErrorablehnen, der die Fehlerinformationen enthält. Eine RP kann diesen Fehler abfangen und dann die vom Browser bereitgestellte benutzerdefinierte Benutzeroberfläche mit einigen Informationen ergänzen, um dem Benutzer zu helfen, bei einem zukünftigen Anmeldeversuch erfolgreich zu sein.
Aktualisieren des Anmeldestatuses mit der Login Status API
Die Login Status API ermöglicht es einem IdP, einem Browser mitzuteilen, ob er einen Anmeldestatus in diesem speziellen Browser hat — damit meinen wir, "ob irgendwelche Benutzer beim IdP in dem aktuellen Browser angemeldet sind oder nicht". Der Browser speichert diesen Status für jeden IdP; die FedCM API verwendet ihn dann, um die Anzahl der Anfragen an den IdP zu reduzieren (da es nicht notwendig ist, Konten anzufordern, wenn keine Benutzer beim IdP angemeldet sind). Es mindert auch potenzielle Timing-Angriffe.
Für jeden bekannten IdP (identifiziert durch seine Konfigurations-URL) führt der Browser eine Drei-Zustand-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 RP und Browser nicht wissen, welcher Benutzer das ist. Informationen zu spezifischen Benutzern werden später im FedCM-Ablauf vom IdP-accounts_endpointzurückgegeben."logged-out": Alle IdP-Konten sind derzeit abgemeldet."unknown": Der Anmeldestatus dieses IdP ist nicht bekannt. Dies ist der Standardwert.
Festlegen des Anmeldestatus
Der IdP sollte seinen Anmeldestatus aktualisieren, wenn sich ein Benutzer beim IdP anmeldet oder abmeldet. Dies kann auf zwei verschiedene Arten geschehen:
-
Der
Set-LoginHTTP-Antwort-Header kann in einer obersten Navigation oder einer ursprungsgleichen Subressource-Anfrage gesetzt werden:httpSet-Login: logged-in Set-Login: logged-out -
Die
Navigator.login.setStatus()-Methode kann vom IdP-Ursprung aus aufgerufen werden:js/* Set logged-in status */ navigator.login.setStatus("logged-in"); /* Set logged-out status */ navigator.login.setStatus("logged-out");
Wie der Anmeldestatus den föderierten Anmeldevorgang beeinflusst
Wenn ein RP eine föderierte Anmeldung versucht, wird der Anmeldestatus überprüft:
- Wenn der Anmeldestatus eines IdP
"logged-in"ist, wird eine Anfrage an den Kontenlisten-Endpunkt gesendet und verfügbare Konten zur Anmeldung werden dem Benutzer im browserbereitgestellten FedCM-Dialog angezeigt. - Wenn alle Anmeldestatus der IdPs
"logged-out"sind, wird das Versprechen, das von der FedCMget()-Anfrage zurückgegeben wird, abgelehnt, ohne eine Anfrage an den Kontenlisten-Endpunkt zu senden. In einem solchen Fall liegt es an dem Entwickler, den Ablauf zu handhaben, zum Beispiel indem er den Benutzer auffordert, sich bei einem geeigneten IdP anzumelden. - Wenn der Anmeldestatus eines IdP
"unknown"ist, wird eine Anfrage an den Kontenlisten-Endpunkt gesendet und der Anmeldestatus je nach Antwort aktualisiert:- Wenn der Endpunkt eine Liste verfügbarer Konten zur Anmeldung zurückgibt, aktualisieren Sie den Status auf
"logged-in"und zeigen Sie die Anmeldeoptionen dem Benutzer im browserbereitgestellten FedCM-Dialog an. - Wenn der Endpunkt keine Konten zurückgibt, aktualisieren Sie den Status auf
"logged-out"; das Versprechen, das von der FedCMget()-Anfrage zurückgegeben wird, wird abgelehnt, wenn keine anderenlogged-inIdPs verfügbar sind.
- Wenn der Endpunkt eine Liste verfügbarer Konten zur Anmeldung zurückgibt, aktualisieren Sie den Status auf
Was passiert, wenn der Browser- und IdP-Anmeldestatus nicht synchronisiert sind?
Trotz der Möglichkeit der Login Status API, den Browser über den IdP-Anmeldestatus zu informieren, ist es möglich, dass der Browser und ein IdP nicht synchron sind. Beispielsweise können die IdP-Sitzungen ablaufen, was bedeutet, dass alle Benutzerkonten abgemeldet werden, aber der Anmeldestatus immer noch auf "logged-in" gesetzt ist (die Anwendung konnte den Anmeldestatus nicht auf "logged-out" setzen). In einem solchen Fall, wenn eine föderierte Anmeldung versucht wird, wird eine Anfrage an den Kontenlisten-Endpunkt des IdP gestellt, aber keine verfügbaren Konten werden zurückgegeben, da die Sitzung nicht mehr verfügbar ist.
In einem solchen Fall kann der Browser einem Benutzer dynamisch ermöglichen, sich bei einem IdP anzumelden, indem er die Anmeldeseite des IdP in einem Dialog öffnet (die Anmelde-URL befindet sich in der Konfigurationsdatei des IdP login_url). Die genaue Art dieses Ablaufs liegt im Ermessen des Browsers; beispielsweise behandelt Chrome es wie folgt.
Sobald der Benutzer beim IdP angemeldet ist, sollte der IdP:
- Den Browser darüber informieren, dass der Benutzer angemeldet wurde, indem der Anmeldestatus gut auf
"logged-in"gesetzt wird. - Den Anmeldedialog schließen, indem die
IdentityProvider.close()-Methode aufgerufen wird.
Siehe auch
- Federated Credential Management API auf developer.chrome.com (2023)