FedCM-Updates: Login Status API, Error API und Auto-selected Flag API

Über Chrome 120 wird die Login Status API für FedCM veröffentlicht. Mit der Login Status API (früher bekannt als IdP Sign-in Status API) können Websites, insbesondere Identitätsanbieter, dem Browser signalisieren, wenn sich ihre Nutzer an- und abmelden. Dieses Signal wird von FedCM verwendet, um ein Problem mit stillen Timing-Angriffen zu beheben. Dadurch kann FedCM ganz ohne Drittanbieter-Cookies arbeiten. Dieses Update befasst sich mit den letzten verbleibenden nicht abwärtskompatiblen Änderungen, die wir im Rahmen unseres Arbeitsumfangs im ursprünglichen Intent to Ship of FedCM identifiziert haben.

Die Login Status API verbessert zwar den Datenschutz und die Nutzerfreundlichkeit, ist nach dem Versand jedoch nicht abwärtskompatibel. Wenn Sie bereits eine FedCM-Implementierung haben, müssen Sie sie anhand der folgenden Anleitung aktualisieren.

Außerdem werden in Chrome zwei neue Funktionen im Federated Credential Management (FedCM) veröffentlicht:

  • Error API: Nutzer werden benachrichtigt, wenn ihr Anmeldeversuch mit einer nativen UI anhand der Serverantwort vom Endpunkt für ID-Assertions fehlschlägt (sofern vorhanden).
  • Auto-Selected Flag API: Der Identitätsanbieter (Identity Provider, IdP) und die vertrauende Partei (Relying Party, RP) wird benachrichtigt, wenn im Ablauf automatisch Anmeldedaten ausgewählt wurden.

Login Status API

Die Login Status API ist ein Mechanismus, mit dem eine Website, insbesondere ein IdP, den Browser über den Anmeldestatus des Nutzers beim IdP informiert. Mit dieser API kann der Browser unnötige Anfragen an den IdP reduzieren und potenzielle Timing-Angriffe abschwächen.

Browser über den Anmeldestatus des Nutzers informieren

IdPs können den Anmeldestatus des Nutzers dem Browser signalisieren, indem sie einen HTTP-Header senden oder eine JavaScript API aufrufen, wenn der Nutzer beim IdP angemeldet ist oder der Nutzer von allen IdP-Konten abgemeldet ist. Für jeden IdP (identifiziert durch seine Konfigurations-URL) behält der Browser eine Drei-Status-Variable bei, die den Anmeldestatus mit den möglichen Werten logged-in, logged-out und unknown darstellt. Der Standardstatus ist unknown.

Wenn Sie signalisieren möchten, dass der Nutzer angemeldet ist, senden Sie einen Set-Login: logged-in-HTTP-Header in einer Navigation der obersten Ebene oder einer Anfrage für eine Unterressourcen desselben Ursprungs:

Set-Login: logged-in

Alternativ können Sie die JavaScript API navigator.login.setStatus('logged-in') vom IdP-Ursprung aus aufrufen:

navigator.login.setStatus('logged-in');

Bei diesen Aufrufen wird der Anmeldestatus des Nutzers als logged-in erfasst. Wenn der Anmeldestatus des Nutzers auf logged-in gesetzt ist, sendet der RP, der FedCM aufruft, Anfragen an den Endpunkt der Kontenliste des IdP und zeigt dem Nutzer die verfügbaren Konten im FedCM-Dialogfeld an.

Wenn Sie signalisieren möchten, dass der Nutzer aus allen seinen Konten abgemeldet ist, senden Sie den HTTP-Header Set-Login: logged-out in einer Navigation der obersten Ebene oder einer Anfrage für eine Unterressource desselben Ursprungs:

Set-Login: logged-out

Alternativ können Sie die JavaScript API navigator.login.setStatus('logged-out') aus dem IdP-Ursprung aufrufen:

navigator.login.setStatus('logged-out');

Bei diesen Aufrufen wird der Anmeldestatus des Nutzers als logged-out erfasst. Wenn der Anmeldestatus des Nutzers logged-out lautet, schlägt das Aufrufen des FedCM unbemerkt fehl, ohne eine Anfrage an den Endpunkt der Kontenliste des IdP zu senden.

Der Status unknown wird festgelegt, bevor der IdP ein Signal über die Login Status API sendet. Wir haben diesen Status zur besseren Umstellung eingeführt, da sich ein Nutzer möglicherweise bereits beim Versand dieser API beim IdP angemeldet hat. Der IdP hat möglicherweise keine Gelegenheit, dies dem Browser zu signalisieren, wenn FedCM zum ersten Mal aufgerufen wird. In diesem Fall senden wir eine Anfrage an den Endpunkt der Kontenliste des IdP und aktualisieren den Status anhand der Antwort des Endpunkts der Kontenliste:

  • Wenn der Endpunkt eine Liste aktiver Konten zurückgibt, aktualisieren Sie den Status auf logged-in und öffnen Sie das FedCM-Dialogfeld, um diese Konten anzuzeigen.
  • Wenn der Endpunkt keine Konten zurückgibt, aktualisieren Sie den Status auf logged-out und schlagen Sie den FedCM-Aufruf fehl.

Was passiert, wenn die Nutzersitzung abläuft? Ermöglichen Sie den Nutzern, sich über einen dynamischen Anmeldevorgang anzumelden.

Auch wenn der IdP dem Browser den Anmeldestatus des Nutzers immer wieder mitteilt, kann der Status nicht synchron sein, z. B. wann die Sitzung abläuft. Der Browser versucht, eine Anfrage mit Anmeldedaten an den Endpunkt der Kontenliste zu senden, wenn der Anmeldestatus logged-in lautet. Der Server gibt jedoch keine Konten zurück, da die Sitzung nicht mehr verfügbar ist. In einem solchen Szenario kann der Browser dem Nutzer dynamisch erlauben, sich über ein Dialogfeld beim IdP anzumelden.

Im FedCM-Dialogfeld wird eine Nachricht angezeigt, die eine Anmeldung vorschlägt, wie in der folgenden Abbildung dargestellt.

Ein FedCM-Dialogfeld mit der Empfehlung, sich beim IdP anzumelden.
Ein FedCM-Dialogfeld mit der Empfehlung, sich beim IdP anzumelden.

Wenn der Nutzer auf die Schaltfläche Weiter klickt, wird im Browser ein Dialogfeld für die Anmeldeseite des IdP geöffnet.

Ein Beispieldialog.
Beispieldialogfeld, das nach dem Klicken auf die Schaltfläche „Beim IdP anmelden“ angezeigt wird.

Die Anmeldeseiten-URL wird mit login_url als Teil der IdP-Konfigurationsdatei angegeben.

{
  "accounts_endpoint": "/auth/accounts",
  "client_metadata_endpoint": "/auth/metadata",
  "id_assertion_endpoint": "/auth/idtokens",
  "login_url": "/login"
  }
}

Das Dialogfeld ist ein normales Browserfenster mit eigenen Cookies. Was im Dialogfeld geschieht, hängt vom IdP ab. Es sind keine Fenster-Handles verfügbar, um eine ursprungsübergreifende Kommunikationsanfrage an die RP-Seite zu senden. Nach der Anmeldung des Nutzers führt der IdP folgende Schritte aus:

  • Senden Sie den Header Set-Login: logged-in oder rufen Sie die navigator.login.setStatus("logged-in") API auf, um den Browser darüber zu informieren, dass der Nutzer angemeldet ist.
  • Rufen Sie IdentityProvider.close() auf, um das Dialogfeld zu schließen.
Ein Nutzer meldet sich in einem RP an, nachdem er sich über FedCM beim IdP angemeldet hat.
Ein Nutzer meldet sich in einem RP an, nachdem er sich über FedCM beim IdP angemeldet hat.

Sie können das Verhalten der Login Status API in unserer Demo ausprobieren.

  1. Tippen Sie auf die Schaltfläche Zum IdP gehen und anmelden.
  2. Melde dich mit einem beliebigen Konto an.
  3. Wählen Sie im Drop-down-Menü Kontostatus die Option Sitzung abgelaufen aus.
  4. Tippen Sie auf die Schaltfläche Persönliche Daten aktualisieren.
  5. Tippen Sie auf die Schaltfläche Zum RP-Test mit FedCM starten.

Sie sollten die Anmeldung beim IdP über das Modulverhalten beobachten können.

Fehler-API

Wenn Chrome eine Anfrage an den Endpunkt der ID-Assertion sendet (z. B. wenn ein Nutzer auf der FedCM-UI auf die Schaltfläche Continue as klickt oder die automatische erneute Authentifizierung ausgelöst wird), kann der IdP aus legitimen Gründen möglicherweise kein Token ausstellen. Wenn der Client beispielsweise nicht autorisiert ist, ist der Server vorübergehend nicht verfügbar usw. Derzeit lehnt Chrome die Anfrage im Hintergrund ab, wenn solche Fehler auftreten, und benachrichtigt das RP nur, indem das Promise abgelehnt wird.

Mit der Error API benachrichtigt Chrome den Nutzer über eine native UI mit den vom IdP bereitgestellten Fehlerinformationen.

Ein FedCM-Dialogfeld mit der Fehlermeldung, nachdem der Anmeldeversuch des Nutzers fehlgeschlagen ist. Der String ist dem Fehlertyp zugeordnet.
Ein FedCM-Dialogfeld mit der Fehlermeldung, nachdem der Anmeldeversuch des Nutzers fehlgeschlagen ist. Der String ist dem Fehlertyp zugeordnet.

IdP-HTTP-API

In der id_assertion_endpoint-Antwort kann der IdP ein Token an den Browser zurückgeben, wenn es auf Anfrage ausgegeben werden kann. Wenn in diesem Angebot kein Token ausgestellt werden kann, kann der IdP eine „Fehler“-Antwort zurückgeben, die zwei neue optionale Felder enthält:

  1. code
  2. url
// id_assertion_endpoint response
{
  "error": {
     "code": "access_denied",
     "url": "https://idp.example/error?type=access_denied"
  }
}

Beim Code kann der IdP einen der bekannten Fehler aus der für OAuth 2.0 angegebenen Fehlerliste [invalid_request, unauthorized_client, access_denied, server_error und temporarily_unavailable] auswählen oder einen beliebigen String verwenden. Wenn Letzteres der Fall ist, rendert Chrome die Fehler-UI mit einer generischen Fehlermeldung und übergibt den Code an das RP.

Für url wird eine für Menschen lesbare Webseite mit Informationen zum Fehler identifiziert, um Nutzern zusätzliche Informationen über den Fehler bereitzustellen. Dieses Feld ist hilfreich für Nutzer, da Browser in einer nativen UI keine ausführlichen Fehlermeldungen ausgeben können. Zum Beispiel Links für die nächsten Schritte, Kontaktinformationen für den Kundenservice usw. Wenn Nutzer mehr über die Fehlerdetails und deren Behebung erfahren möchten, können sie die bereitgestellte Seite über die Browser-Benutzeroberfläche aufrufen. Die URL muss von derselben Website wie der IdP configURL stammen.

try {
  const cred = await navigator.credentials.get({
    identity: {
      providers: [
        {
          configURL: 'https://idp.example/manifest.json',
          clientId: '1234',
        },
      ],
    }
  });
} catch (e) {
  const code = e.code;
  const url = e.url;
}

API für automatische Auswahl

mediation: optional ist das standardmäßige Verhalten bei der Vermittlung für Nutzer in der Credential Management API. Sie löst nach Möglichkeit die automatische erneute Authentifizierung aus. Die automatische erneute Authentifizierung kann jedoch aus Gründen, die nur dem Browser bekannt sind, nicht verfügbar sein. In diesem Fall wird der Nutzer möglicherweise aufgefordert, sich mit expliziter Nutzervermittlung anzumelden. Dabei handelt es sich um einen Ablauf mit anderen Attributen.

  • Wenn ein API-Aufrufer ein ID-Token erhält, hat er keinen Einblick, ob dies das Ergebnis eines Ablaufs der automatischen erneuten Authentifizierung war. Das erschwert es ihnen, die API-Leistung zu bewerten und die UX entsprechend zu verbessern.
  • Aus Sicht des IdP können sie ebenfalls nicht feststellen, ob eine automatische erneute Authentifizierung zur Leistungsbewertung stattgefunden hat oder nicht. Außerdem kann eine explizite Vermittlung der Nutzer dazu beitragen, mehr sicherheitsrelevante Funktionen zu unterstützen. Einige Nutzer bevorzugen beispielsweise eine höhere Sicherheitsstufe, die eine explizite Nutzervermittlung bei der Authentifizierung erfordert. Wenn ein IdP eine Tokenanfrage ohne eine solche Vermittlung erhält, kann er die Anfrage anders verarbeiten. Sie können beispielsweise einen Fehlercode zurückgeben, sodass der RP die FedCM API noch einmal mit mediation: required aufrufen kann.

Daher ist es für Entwickler von Vorteil, den Ablauf der automatischen erneuten Authentifizierung sichtbar zu machen.

Mit der Auto-selected Flag API gibt Chrome an, ob durch Tippen auf die Schaltfläche Weiter als sowohl mit IdP als auch mit RP eine explizite Nutzerberechtigung erhalten wurde, wenn eine automatische erneute Authentifizierung oder eine explizite Vermittlung stattgefunden hat. Die Freigabe erfolgt erst, nachdem die Nutzerberechtigung für die IdP/RP-Kommunikation gewährt wurde.

IdP-Freigabe

Damit die Informationen an die IdP-Berechtigung zum Posten des Nutzers weitergegeben werden können, fügt Chrome is_auto_selected=true in die POST-Anfrage ein, die an id_assertion_endpoint gesendet wird:

POST /fedcm_assertion_endpoint 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=Ct0D&disclosure_text_shown=true&is_auto_selected=true

RP-Freigabe

Der Browser kann die Informationen über IdentityCredential an den RP in isAutoSelected weitergeben:

const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/manifest.json',
      clientId: '1234'
    }]
  }
});

if (cred.isAutoSelected !== undefined) {
  const isAutoSelected = cred.isAutoSelected;
}

Reagieren und Feedback geben

Wenn du Feedback hast oder während des Tests Probleme auftreten, kannst du diese unter crbug.com einreichen.

Foto von Girl with red hat auf Unsplash