Implementeer een identiteitsoplossing met FedCM aan de kant van de identiteitsprovider

De implementatie van FedCM omvat verschillende kernstappen voor zowel Identity Provider (IdP) als Relying Party (RP) . Raadpleeg de documentatie voor meer informatie over de implementatie van FedCM aan de kant van de Relying Party ( RP ) .

IdP's moeten de volgende stappen voltooien om FedCM te implementeren:

  1. Maak een bekend bestand .
  2. Maak een configuratiebestand .
  3. Maak de volgende eindpunten:
  4. Informeer de browser over de aanmeldstatus van de gebruiker .

Een bekend bestand aanmaken

Om te voorkomen dat trackers misbruik maken van de API , moet een bekend bestand worden geserveerd vanuit /.well-known/web-identity van eTLD+1 van de IdP.

Het bekende bestand kan de volgende eigenschappen bevatten:

Eigendom Vereist Beschrijving
provider_urls vereist Array met IdP-configuratiebestandspaden. Genegeerd (maar nog steeds vereist) als accounts_endpoint en login_url zijn opgegeven.
accounts_endpoint aanbevolen, vereist login_url
URL voor het eindpunt van de accounts. Dit maakt ondersteuning voor meerdere configuraties mogelijk, zolang elk configuratiebestand dezelfde login_url en accounts_endpoint URL gebruikt.

Let op: Deze parameter wordt ondersteund vanaf Chrome 132.
login_url aanbevolen, vereist accounts_endpoint De URL van de inlogpagina waarmee de gebruiker zich kan aanmelden bij de IdP. Dit maakt ondersteuning voor meerdere configuraties mogelijk, zolang elk configuratiebestand dezelfde login_url en accounts_endpoint gebruikt.

Let op: de parameter wordt ondersteund vanaf Chrome 132 en later.

Als de IdP-eindpunten bijvoorbeeld worden bediend via https://accounts.idp.example/ , moeten ze een bekend bestand bedienen via https://idp.example/.well-known/web-identity en een IdP-configuratiebestand . Hier is een voorbeeld van de inhoud van een bekend bestand:

  {
    "provider_urls": ["https://accounts.idp.example/config.json"]
  }

IdP's kunnen meerdere configuratiebestanden voor een IdP beheren door accounts_endpoint en login_url in het bekende bestand op te geven. Deze functie kan in de volgende gevallen nuttig zijn:

  • Een IdP moet meerdere verschillende test- en productieconfiguraties ondersteunen.
  • Een IdP moet per regio verschillende configuraties ondersteunen (bijvoorbeeld eu-idp.example en us-idp.example ).

Om meerdere configuraties te ondersteunen (bijvoorbeeld om onderscheid te maken tussen test- en productieomgevingen), moet IdP accounts_endpoint en login_url opgeven:

  {
    // This property is required, but will be ignored when IdP supports
    // multiple configs (when `accounts_endpoint` and `login_url` are
    // specified), as long as `accounts_endpoint` and `login_url` in
    // that config file match those in the well-known file.
    "provider_urls": [ "https://idp.example/fedcm.json" ],

    // Specify accounts_endpoint and login_url properties to support
    // multiple config files.
    // Note: The accounts_endpoint and login_url must be identical
    // across all config files. Otherwise,
    // the configurations won't be supported.
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }

Een IdP-configuratiebestand en eindpunten maken

Het IdP-configuratiebestand bevat een lijst met vereiste eindpunten voor de browser. IdP's moeten één of meerdere configuratiebestanden, inclusief de vereiste eindpunten en URL's, hosten. Alle JSON-reacties moeten worden geleverd met het content-type application/json .

De URL van het configuratiebestand wordt bepaald door de waarden die worden meegegeven aan de navigator.credentials.get() -aanroep die wordt uitgevoerd op een RP . De RP geeft de URL van het configuratiebestand door voor elke identiteitsprovider:

  // Executed on RP's side:
  try {
    const credential = await navigator.credentials.get({
      identity: {
        providers: [
          {
            // To allow users to sign in with the IdP1 using FedCM, RP specifies the IdP's config file URL:
            configUrl: 'https://idp1.example/foo.json', // first IdP
            clientId: '123',
          },
          // To allow users to sign in with the IdP2 using FedCM, RP specifies the IdP's config file URL.
          // Note that multiple IdPs in a single get() are supported from Chrome 136.
          {
            configUrl: 'https://idp2.example/bar.json', // second IdP
            clientId: '456',
          },
        ],
      },
    });

    const token = credential.token;
    // Get the current IdP's configURL to identify which provider the user is signed in with
    const currentIdpConfigUrl = credential.configURL;
    if (currentIdpConfigUrl === 'https://idp1.example/foo.json') {
      // handle the case where the user signed in with idp1
    } else if (currentIdpConfigUrl === 'https://idp2.example/bar.json') {
      // handle the case where the user signed in with idp2
    }
  } catch (error) {
    // handle error
  }

De browser haalt het configuratiebestand op met een GET -verzoek zonder de Origin header of de Referer header. Het verzoek bevat geen cookies en volgt geen omleidingen. Dit voorkomt effectief dat de IdP leert wie het verzoek heeft ingediend en welke RP verbinding probeert te maken. Bijvoorbeeld:

  GET /config.json HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Sec-Fetch-Dest: webidentity

De IdP moet een configuratie-eindpunt implementeren dat reageert met een JSON. De JSON bevat de volgende eigenschappen:

Eigendom Beschrijving
accounts_endpoint (verplicht) URL voor het accounteindpunt .
account_label (optioneel) Aangepaste accountlabelreeks die bepaalt welke accounts moeten worden geretourneerd wanneer dit configuratiebestand wordt gebruikt, bijvoorbeeld: "account_label": "developer" .
Een IdP kan aangepaste accountlabels als volgt implementeren:

Een IdP implementeert bijvoorbeeld het configuratiebestand "https://idp.example/developer-config.json" met "account_label": "developer" . De IdP markeert ook sommige accounts met het label "developer" met behulp van de parameter label_hints in het eindpunt accounts . Wanneer een RP navigator.credentials.get() aanroept met het opgegeven configuratiebestand "https://idp.example/developer-config.json" , worden alleen accounts met het label "developer" geretourneerd.

Let op: aangepaste accountlabels worden ondersteund vanaf Chrome 132.
supports_use_other_account (optioneel) Booleaanse waarde die aangeeft of de gebruiker zich kan aanmelden met een ander account dan waarmee hij is aangemeld (indien de IdP meerdere accounts ondersteunt). Dit geldt alleen voor de actieve modus.
client_metadata_endpoint (optioneel) URL voor het clientmetadata-eindpunt .
id_assertion_endpoint (verplicht) URL voor het ID-bevestigingseindpunt .
disconnect (optioneel) URL voor het ontkoppelingseindpunt .
login_url (verplicht) De URL van de inlogpagina waarmee de gebruiker zich kan aanmelden bij de IdP.
branding (optioneel) Object dat verschillende merkopties bevat.
branding.background_color (optioneel) Branding-optie waarmee de achtergrondkleur van de knop "Doorgaan als..." wordt ingesteld. Gebruik de relevante CSS-syntaxis, namelijk hex-color , hsl() , rgb() of named-color .
branding.color (optioneel) Branding-optie waarmee de tekstkleur van de knop "Doorgaan als..." wordt ingesteld. Gebruik de relevante CSS-syntaxis, namelijk hex-color , hsl() , rgb() of named-color .
branding.icons (optioneel) Array van pictogramobjecten. Deze pictogrammen worden weergegeven in het aanmeldvenster. Het pictogramobject heeft twee parameters:
  • url (verplicht): URL van de pictogramafbeelding. SVG-afbeeldingen worden niet ondersteund.
  • size (optioneel): De applicatie neemt aan dat de pictogramafmetingen vierkant en met één resolutie zijn. Deze waarde moet groter zijn dan of gelijk aan 25 px in de passieve modus en groter dan of gelijk aan 40 px in de actieve modus.

Hier is een voorbeeld van een responstekst van de IdP:

  {
    "accounts_endpoint": "/accounts.example",
    "client_metadata_endpoint": "/client_metadata.example",
    "id_assertion_endpoint": "/assertion.example",
    "disconnect_endpoint": "/disconnect.example",
    "login_url": "/login",
    // When RPs use this config file, only those accounts will be
    //returned that include `developer` label in the accounts endpoint.
    "account_label": "developer",
    "supports_use_other_account": true,
    "branding": {
      "background_color": "green",
      "color": "#FFEEAA",
      "icons": [{
        "url": "https://idp.example/icon.ico",
        "size": 25
      }]
    }
  }

Zodra de browser het configuratiebestand heeft opgehaald, worden er vervolgverzoeken naar de IdP-eindpunten verzonden:

IdP-eindpunten
IdP-eindpunten

Gebruik een ander account

Gebruikers kunnen overschakelen naar een ander account dan het account waarmee ze zijn ingelogd, als de IdP meerdere accounts ondersteunt of als het bestaande account wordt vervangen.

Om de gebruiker in staat te stellen andere accounts te kiezen, moet de IdP deze functie in het configuratiebestand specificeren:

  {
    "accounts_endpoint" : "/accounts.example",
    "supports_use_other_account": true
  }

Accounts-eindpunt

Het accounts-eindpunt van de IdP retourneert een lijst met accounts waarmee de gebruiker is aangemeld bij de IdP. Als de IdP meerdere accounts ondersteunt, retourneert dit eindpunt alle aangemelde accounts.

De browser verzendt een GET -verzoek met cookies met SameSite=None , maar zonder een client_id parameter, de Origin header of de Referer header. Dit voorkomt effectief dat de IdP leert op welke RP de gebruiker probeert in te loggen. Bijvoorbeeld:

  GET /accounts.example HTTP/1.1
  Host: accounts.idp.example
  Accept: application/json
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

Na ontvangst van het verzoek moet de server:

  1. Controleer of het verzoek een Sec-Fetch-Dest: webidentity HTTP-header bevat.
  2. Koppel de sessiecookies aan de ID's van de reeds aangemelde accounts.
  3. Reageer met de lijst met accounts.

De browser verwacht een JSON-antwoord dat een accounts bevat met een reeks accountgegevens met de volgende eigenschappen:

Eigendom Beschrijving
id (verplicht) Unieke ID van de gebruiker.
name De volledige naam van de gebruiker, afhankelijk van zijn/haar landinstellingen en voorkeuren.

Let op: Vanaf Chrome 141 is ten minste één van de parameters name , email , username of tel vereist. In oudere Chrome-versies zijn zowel name als email vereist.
username Een door de gebruiker gekozen gebruikersnaam.

Let op: Vanaf Chrome 141 is minimaal één van de parameters name , email , username of tel vereist.
email E-mailadres van de gebruiker.

Let op: Vanaf Chrome 141 is ten minste één van de parameters name , email , username of tel vereist. In oudere Chrome-versies zijn zowel name als email vereist.
tel Telefoonnummer van de gebruiker.

Let op: Vanaf Chrome 141 is minimaal één van de parameters name , email , username of tel vereist.
picture (optioneel) URL van de avatarafbeelding van de gebruiker.
given_name (optioneel) Voornaam van de gebruiker.
approved_clients (optioneel) Een reeks RP-client-ID's waarmee de gebruiker zich heeft geregistreerd.
login_hints (optioneel) Een array van alle mogelijke filtertypen die de IdP ondersteunt om een ​​account te specificeren. De RP kan navigator.credentials.get() aanroepen met de eigenschap loginHint om het opgegeven account selectief weer te geven.
domain_hints (optioneel) Een array van alle domeinen waaraan het account is gekoppeld. De RP kan navigator.credentials.get() aanroepen met een domainHint -eigenschap om de accounts te filteren.
label_hints (optioneel) Reeks met aangepaste accountlabels waaraan een account is gekoppeld.
Een IdP kan aangepaste accountlabels als volgt implementeren:
  • Geef accountlabels op in het accounteindpunt (met behulp van de parameter label_hints ).
  • Maak voor elk specifiek label een configuratiebestand .

Een IdP implementeert bijvoorbeeld het configuratiebestand https://idp.example/developer-config.json met de specificatie "account_label": "developer" . De IdP markeert ook sommige accounts met het label "developer" met behulp van de parameter label_hints in het eindpunt accounts . Wanneer een RP navigator.credentials.get() aanroept met een opgegeven configuratiebestand https://idp.example/developer-config.json , worden alleen accounts met het label "developer" geretourneerd.

Aangepaste accountlabels verschillen van aanmeldingshints en domeinhints in die zin dat ze volledig worden beheerd door de IdP-server, terwijl de RP alleen het te gebruiken configuratiebestand specificeert.

Let op: aangepaste accountlabels worden ondersteund vanaf Chrome 132.

Voorbeeld van een antwoordtekst:

  {
    "accounts": [{
      "id": "1234",
      "given_name": "John",
      "name": "John Doe",
      "email": "john_doe@idp.example",
      "picture": "https://idp.example/profile/123",
      // Ids of those RPs where this account can be used
      "approved_clients": ["123", "456", "789"],
      // This account has 'login_hints`. When an RP calls `navigator.credentials.get()`
      // with a `loginHint` value specified, for example, `exampleHint`, only those
      // accounts will be shown to the user whose 'login_hints' array contains the `exampleHint`.
      "login_hints": ["demo1", "exampleHint"],
      // This account is labelled. IdP can implement a specific config file for a
      // label, for example, `https://idp.example/developer-config.json`. Like that
      // RPs can filter out accounts by calling `navigator.credentials.get()` with
      // `https://idp.example/developer-config.json` config file.
      "label_hints": ["enterprise", "developer"]
    }, {
      "id": "5678",
      "given_name": "Johnny",
      "name": "Johnny",
      "email": "johnny@idp.example",
      "picture": "https://idp.example/profile/456",
      "approved_clients": ["abc", "def", "ghi"],
      "login_hints": ["demo2"],
      "domain_hints": ["@domain.example"]
    }]
  }

Als de gebruiker niet is aangemeld, reageert u met HTTP 401 (Niet geautoriseerd).

De geretourneerde lijst met accounts wordt door de browser gebruikt en is niet beschikbaar voor de RP.

ID-bevestigingseindpunt

Het ID-assertie-eindpunt van de IdP retourneert een assertie voor de aangemelde gebruiker. Wanneer de gebruiker zich aanmeldt bij een RP-website met behulp van de aanroep navigator.credentials.get() , stuurt de browser een POST verzoek met cookies met SameSite=None en een content-type van application/x-www-form-urlencoded naar dit eindpunt met de volgende informatie:

Eigendom Beschrijving
client_id (verplicht) De client-ID van de RP.
account_id (verplicht) De unieke ID van de aanmeldende gebruiker.
disclosure_text_shown Resulteert in een string van "true" of "false" (in plaats van een boolean). Het resultaat is "false" in de volgende gevallen:
  • Als de openbaarmakingstekst niet werd weergegeven omdat de client-ID van de RP was opgenomen in de lijst met approved_clients -eigenschappen van het antwoord van het accounts-eindpunt .
  • Als de openbaarmakingstekst niet werd weergegeven omdat de browser in het verleden een registratiemoment heeft waargenomen waarbij approved_clients ontbraken.
  • Als de parameter fields niet alle drie de velden ("naam", "e-mail" en "afbeelding") bevat, bijvoorbeeld fields=[ ] of fields=['name', 'picture'] . Dit is nodig voor achterwaartse compatibiliteit met oudere implementaties.

    Let op: Vanaf Chrome 141 kan de openbaarmakingstekst worden weergegeven, zelfs als de waarde disclosure_text_shown "false" is. Om te controleren of de openbaarmakingstekst is weergegeven, controleert u de waarde disclosure_shown_for .
disclosure_shown_for Geeft de velden weer die de browser aan de gebruiker heeft getoond in de openbaarmakingstekst om de gebruiker te laten weten welke gegevens de RP opvraagt ​​bij de IdP.
is_auto_selected Als automatische herauthenticatie wordt uitgevoerd op de RP, geeft is_auto_selected "true" aan. Anders "false" . Dit is nuttig om meer beveiligingsfuncties te ondersteunen. Sommige gebruikers geven bijvoorbeeld de voorkeur aan een hogere beveiligingslaag die expliciete gebruikersbemiddeling vereist bij authenticatie. Als een IdP een tokenaanvraag ontvangt zonder dergelijke bemiddeling, kan deze de aanvraag anders afhandelen. Retourneer bijvoorbeeld een foutcode zodat de RP de FedCM API opnieuw kan aanroepen met mediation: required .
fields (optioneel) Array met strings die de gebruikersinformatie specificeert die de RP de IdP heeft gevraagd te delen. De volgende velden kunnen optioneel worden opgegeven:
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
De browser verzendt fields disclosure_text_shown en disclosure_shown_for en vermeldt de opgegeven velden in het POST-verzoek, zoals in het volgende voorbeeld .

Let op: De Fields API wordt ondersteund door Chrome 132 en hoger. De velden `"gebruikersnaam"` en `"tel"` worden ondersteund vanaf Chrome 141.
params (optioneel) Elk geldig JSON-object waarmee u aanvullende aangepaste sleutel-waardeparameters kunt specificeren, bijvoorbeeld:
  • scope : een tekenreekswaarde met aanvullende machtigingen die RP moet aanvragen, bijvoorbeeld "drive.readonly calendar.readonly"
  • nonce : een willekeurige tekenreeks die door de RP wordt verstrekt om ervoor te zorgen dat het antwoord op deze specifieke aanvraag wordt verzonden. Voorkomt replay-aanvallen.
  • Andere aangepaste sleutel-waardeparameters.
Wanneer de browser een POST-verzoek verzendt, worden de params -waarden geserialiseerd naar JSON en vervolgens procentgecodeerd .

Let op: Parameters API wordt ondersteund door Chrome 132 en later.

Voorbeeld HTTP-header:

  POST /assertion.example HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Content-Type: application/x-www-form-urlencoded
  Cookie: 0x23223
  Sec-Fetch-Dest: webidentity

  // disclosure_text_shown is set to 'false', as the 'name' field value is missing in 'fields' array
  // params value is serialized to JSON and then percent-encoded.
  account_id=123&client_id=client1234&disclosure_text_shown=false&is_auto_selected=true&params=%22%7B%5C%22nonce%5C%22%3A%5C%22nonce-value%5C%22%7D%22.%0D%0A4&fields=email,picture&disclosure_shown_for=email,picture

Na ontvangst van het verzoek moet de server:

  1. Reageer op het verzoek met CORS (Cross-Origin Resource Sharing) .
  2. Controleer of het verzoek een Sec-Fetch-Dest: webidentity HTTP-header bevat.
  3. Vergelijk de Origin header met de RP-oorsprong bepaald door de client_id . Weigeren als ze niet overeenkomen.
  4. Vergelijk account_id met de ID van het reeds aangemelde account. Weigeren als ze niet overeenkomen.
  5. Reageer met een token. Als het verzoek wordt afgewezen, reageer dan met een foutmelding .

De IdP kan bepalen hoe het token wordt uitgegeven. Over het algemeen wordt het ondertekend met informatie zoals de account-ID, client-ID, de oorsprong van de uitgever en de nonce, zodat de RP kan verifiëren of het token authentiek is.

De browser verwacht een JSON-antwoord met de volgende eigenschap:

Eigendom Beschrijving
token Een token is een tekenreeks die beweringen over de authenticatie bevat.
continue_on Omleidings-URL die een aanmeldingsproces in meerdere stappen mogelijk maakt.

Het geretourneerde token wordt door de browser doorgegeven aan de RP, zodat de RP de authenticatie kan valideren.

  {
    // IdP can respond with a token to authenticate the user
    "token": "***********"
  }

Ga door met de functie

De IdP kan een redirect-URL opgeven in de respons van het ID-assertie-eindpunt om een ​​meerstaps aanmeldproces mogelijk te maken. Dit is handig wanneer de IdP aanvullende informatie of machtigingen moet opvragen, bijvoorbeeld:

  • Toestemming om toegang te krijgen tot de server-side bronnen van de gebruiker.
  • Controleren of de contactgegevens actueel zijn.
  • Ouderlijk toezicht.

Het ID-assertie-eindpunt kan een ' continue_on eigenschap retourneren die een absoluut of relatief pad naar het ID-assertie-eindpunt bevat.

  {
    // In the id_assertion_endpoint, instead of returning a typical
    // "token" response, the IdP decides that it needs the user to
    // continue on a dialog window:
    "continue_on": "https://idp.example/continue_on_url"
  }

Als het antwoord de parameter continue_on bevat, wordt een nieuw dialoogvenster geopend dat de gebruiker naar het opgegeven pad navigeert. Na de gebruikersinteractie met de continue_on pagina moet de IdP IdentityProvider.resolve() aanroepen met het token als argument, zodat de belofte van de oorspronkelijke navigator.credentials.get() aanroep kan worden omgezet:

  document.getElementById('example-button').addEventListener('click', async () => {
    let accessToken = await fetch('/generate_access_token.cgi');
    // Closes the window and resolves the promise (that is still hanging
    // in the relying party's renderer) with the value that is passed.
    IdentityProvider.resolve(accessToken);
  });

De browser sluit het dialoogvenster vervolgens automatisch en stuurt het token terug naar de API-aanvrager. Een eenmalige IdentityProvider.resolve() aanroep is de enige manier waarop het bovenliggende venster (RP) en het dialoogvenster (IdP) met elkaar kunnen communiceren.
Als de gebruiker het verzoek afwijst, kan IdP het venster sluiten door IdentityProvider.close() aan te roepen.

  IdentityProvider.close();

De Continuation API vereist expliciete gebruikersinteractie (klikken) om te functioneren. Zo werkt de Continuation API met verschillende mediatiemodi :

  • In passive modus :
    • mediation: 'optional' (standaard): de Continuation API werkt alleen met een gebruikersgebaar, zoals het klikken op een knop op de pagina of in de FedCM-gebruikersinterface. Wanneer automatische herauthenticatie wordt geactiveerd zonder gebruikersgebaar, wordt er geen dialoogvenster geopend en wordt de belofte afgewezen.
    • mediation: 'required' : vraagt ​​de gebruiker altijd om interactie, zodat de Continuation API altijd werkt.
  • In actieve modus :
    • Activering door de gebruiker is altijd vereist. De Continuation API is altijd compatibel.

Als de gebruiker om een ​​of andere reden zijn of haar account in het dialoogvenster heeft gewijzigd (bijvoorbeeld omdat de IdP de functie 'ander account gebruiken' aanbiedt of in delegatiegevallen), krijgt de resolve-aanroep een optioneel tweede argument waarmee iets als het volgende mogelijk is:

  IdentityProvider.resolve(token, {accountId: '1234');

Een foutreactie retourneren

Het id_assertion_endpoint kan ook een "fout"-respons retourneren, die twee optionele velden heeft:

  • code : De IdP kan een van de bekende fouten uit de door OAuth 2.0 gespecificeerde foutenlijst kiezen ( invalid_request , unauthorized_client , access_denied , server_error en temporarily_unavailable ) of een willekeurige tekenreeks gebruiken. In het laatste geval geeft Chrome de fout-UI weer met een algemene foutmelding en geeft de code door aan de RP.
  • url : Hiermee wordt een voor mensen leesbare webpagina met informatie over de fout geïdentificeerd om gebruikers aanvullende informatie over de fout te bieden. Dit veld is nuttig voor gebruikers omdat browsers geen uitgebreide foutmeldingen kunnen bieden in een ingebouwde gebruikersinterface. Bijvoorbeeld: links naar vervolgstappen of contactgegevens van de klantenservice. Als een gebruiker meer wil weten over de foutdetails en hoe deze te verhelpen, kan hij of zij de betreffende pagina in de browserinterface bezoeken voor meer informatie. De URL moet van dezelfde site zijn als de IdP configURL .
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }

Aangepaste accountlabels

Met aangepaste accountlabels kan de IdP gebruikersaccounts voorzien van labels, en de RP kan ervoor kiezen om alleen accounts met specifieke labels op te halen door de configURL voor dat specifieke label op te geven. Dit kan handig zijn wanneer een RP accounts moet filteren op basis van specifieke criteria, bijvoorbeeld om alleen rolspecifieke accounts weer te geven, zoals "developer" of "hr" .

Vergelijkbare filtering is mogelijk met de functies Domeinhint en Aanmeldhint , door deze op te geven in de aanroep navigator.credentials.get() . Aangepaste accountlabels kunnen gebruikers echter filteren door het configuratiebestand op te geven, wat vooral handig is wanneer er meerdere configURL's worden gebruikt. Aangepaste accountlabels verschillen ook doordat ze worden geleverd door de IdP-server, in tegenstelling tot de RP-server, zoals aanmeldings- of domeinhints.

Stel je een IdP voor die onderscheid wil maken tussen "developer" en "hr" accounts. Om dit te bereiken, moet de IdP twee configURL's ondersteunen voor respectievelijk "developer" en "hr" :

  • Het ontwikkelaarsconfiguratiebestand https://idp.example/developer/fedcm.json heeft het label "developer" en het enterpriseconfiguratiebestand https://idp.example/hr/fedcm.json heeft het label "hr" , zoals hieronder:
  // The developer config file at `https://idp.example/developer/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "account_label": "developer"
  }
  // The hr config file at `https://idp.example/hr/fedcm.json`
  {
    "accounts_endpoint": "https://idp.example/accounts",
    "client_metadata_endpoint": "/client_metadata",
    "login_url": "https://idp.example/login",
    "id_assertion_endpoint": "/assertion",
    "account_label": "hr"
  }
  • Bij een dergelijke configuratie moet het bekende bestand accounts_endpoint en login_url bevatten om meerdere configURL's toe te staan:
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • Het algemene IdP -accounteindpunt (in dit voorbeeld https://idp.example/accounts ) retourneert een lijst met accounts die een label_hints eigenschap bevat met toegewezen labels in een array voor elk account:
  {
  "accounts": [{
    "id": "123",
    "given_name": "John",
    "name": "John Doe",
    "email": "john_doe@idp.example",
    "picture": "https://idp.example/profile/123",
    "label_hints": ["developer"]
    }], [{
    "id": "4567",
    "given_name": "Jane",
    "name": "Jane Doe",
    "email": "jane_doe@idp.example",
    "picture": "https://idp.example/profile/4567",
    "label_hints": ["hr"]
    }]
  }

Wanneer een RP wil dat "hr" -gebruikers zich kunnen aanmelden, kunnen ze de configURL https://idp.example/hr/fedcm.json opgeven in de navigator.credentials.get() -aanroep:

  let { token } = await navigator.credentials.get({
    identity: {
      providers: [{
        clientId: '1234',
        nonce: '234234',
        configURL: 'https://idp.example/hr/fedcm.json',
      },
    }
  });

Hierdoor is alleen de account-ID 4567 beschikbaar voor de gebruiker om in te loggen. De account-ID 123 wordt stilzwijgend verborgen door de browser, zodat de gebruiker geen account krijgt dat niet wordt ondersteund door de IdP op deze site.

Aanvullende overwegingen:

  • Labels zijn strings. Als de label_hints array of account_label veld een waarde gebruikt die geen string is, wordt de waarde genegeerd.
  • Als er geen labels zijn opgegeven in de configURL , worden alle accounts weergegeven in de FedCM-accountkiezer.
  • Als er geen labels voor een account zijn opgegeven, wordt dit account alleen weergegeven in de accountkiezer als de configURL ook geen label opgeeft.
  • Als er in de passieve modus geen account overeenkomt met het gevraagde label (vergelijkbaar met de Domeinhint-functie), toont het FedCM-dialoogvenster een aanmeldprompt waarmee de gebruiker zich kan aanmelden bij een IdP-account. In de actieve modus wordt het aanmelddialoogvenster direct geopend.

Eindpunt loskoppelen

Door IdentityCredential.disconnect() aan te roepen, stuurt de browser een cross-origin POST verzoek met cookies met SameSite=None en een content-type van application/x-www-form-urlencoded naar dit disconnect-eindpunt met de volgende informatie:

Eigendom Beschrijving
account_hint Een tip voor het IdP-account.
client_id De client-ID van de RP.
  POST /disconnect.example 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

Na ontvangst van het verzoek moet de server:

  1. Reageer op het verzoek met CORS (Cross-Origin Resource Sharing) .
  2. Controleer of het verzoek een Sec-Fetch-Dest: webidentity HTTP-header bevat.
  3. Vergelijk de Origin header met de RP-oorsprong bepaald door de client_id . Weigeren als ze niet overeenkomen.
  4. Vergelijk account_hint met de ID's van de reeds aangemelde accounts.
  5. Koppel het gebruikersaccount los van de RP.
  6. Reageer naar de browser met de geïdentificeerde gebruikersaccountinformatie in een JSON-indeling.

Een voorbeeld van een JSON-payload ziet er als volgt uit:

  {
    "account_id": "account456"
  }

Als de IdP echter wil dat de browser de verbinding verbreekt met alle accounts die aan de RP zijn gekoppeld, geeft u een tekenreeks door die niet overeenkomt met een account-ID, bijvoorbeeld "*" .

Clientmetadata-eindpunt

Het clientmetadata-eindpunt van de IdP retourneert de metadata van de relying party, zoals het privacybeleid, de servicevoorwaarden en logo-iconen van de RP. RP's dienen vooraf links naar hun privacybeleid en servicevoorwaarden aan de IdP te verstrekken. Deze links worden weergegeven in het aanmeldvenster wanneer de gebruiker zich nog niet bij de RP bij de IdP heeft geregistreerd.

De browser verzendt een GET -verzoek met behulp van de client_id navigator.credentials.get zonder cookies. Bijvoorbeeld:

  GET /client_metadata.example?client_id=1234 HTTP/1.1
  Host: accounts.idp.example
  Origin: https://rp.example/
  Accept: application/json
  Sec-Fetch-Dest: webidentity

Na ontvangst van het verzoek moet de server:

  1. Bepaal de RP voor de client_id .
  2. Reageer met de clientmetagegevens.

De eigenschappen voor het clientmetagegevens-eindpunt omvatten:

Eigendom Beschrijving
privacy_policy_url (optioneel) URL voor RP-privacybeleid.
terms_of_service_url (optioneel) URL van de servicevoorwaarden voor RP.
icons (optioneel) Array van objecten, zoals [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

De browser verwacht een JSON-respons van het eindpunt:

  {
    "privacy_policy_url": "https://rp.example/privacy_policy.html",
    "terms_of_service_url": "https://rp.example/terms_of_service.html",
    "icons": [{
          "url": "https://rp.example/rp-icon.ico",
          "size": 40
      }]
  }

De geretourneerde clientmetagegevens worden door de browser gebruikt en zijn niet beschikbaar voor de RP.

Inlog-URL

Dit eindpunt wordt gebruikt om de gebruiker zich te laten aanmelden bij de IdP.

Met de Login Status API moet de IdP de inlogstatus van de gebruiker doorgeven aan de browser. De status kan echter afwijken, bijvoorbeeld wanneer de sessie verloopt . In een dergelijk scenario kan de browser de gebruiker dynamisch laten inloggen bij de IdP via de URL van de inlogpagina die is opgegeven in de login_url van het IdP-configuratiebestand .

In het FedCM-dialoogvenster wordt een bericht weergegeven waarin u wordt gevraagd u aan te melden, zoals in de volgende afbeelding.

Een FedCM-dialoogvenster waarin wordt voorgesteld om u aan te melden bij de IdP.
Een FedCM-dialoogvenster waarin wordt voorgesteld om u aan te melden bij de IdP.

Wanneer de gebruiker op de knop Doorgaan klikt, opent de browser een dialoogvenster voor de inlogpagina van de IdP.

Een voorbeeld van een FedCM-dialoog.
Een voorbeeld van een dialoogvenster dat wordt weergegeven nadat u op de knop 'Aanmelden bij de IdP' hebt geklikt.

De dialoog is een regulier browservenster met first-party cookies. Wat er ook gebeurt in de dialoog, de IdP bepaalt het en er zijn geen vensterhandles beschikbaar om een ​​cross-origin communicatieverzoek naar de RP-pagina te sturen. Nadat de gebruiker is aangemeld, moet de IdP:

  • Stuur de Set-Login: logged-in header of roep de navigator.login.setStatus("logged-in") API aan om de browser te informeren dat de gebruiker is aangemeld.
  • Roep IdentityProvider.close() aan om het dialoogvenster te sluiten.
Een gebruiker meldt zich aan bij een RP nadat hij zich via FedCM heeft aangemeld bij de IdP.

De browser informeren over de inlogstatus van de gebruiker

De Login Status API is een mechanisme waarmee een website, met name een IdP, de browser informeert over de inlogstatus van de gebruiker bij de IdP. Met deze API kan de browser onnodige verzoeken aan de IdP beperken en potentiële timingaanvallen beperken .

IdP's kunnen de inlogstatus van de gebruiker aan de browser doorgeven door een HTTP-header te verzenden of door een JavaScript API aan te roepen wanneer de gebruiker is aangemeld bij de IdP of wanneer de gebruiker is afgemeld bij al zijn IdP-accounts. Voor elke IdP (geïdentificeerd door de configuratie-URL) houdt de browser een tri-state variabele bij die de inlogstatus vertegenwoordigt met mogelijke waarden:

  • logged-in
  • logged-out
  • unknown (standaard)
Inlogstatus Beschrijving
logged-in Wanneer de inlogstatus van de gebruiker is ingesteld op logged-in , doet de RP die FedCM aanroept verzoeken aan het accounteindpunt van de IdP en worden de beschikbare accounts voor de gebruiker weergegeven in het FedCM-dialoogvenster.
logged-out Wanneer de inlogstatus van de gebruiker logged-out is, mislukt het aanroepen van FedCM zonder dat er een verzoek wordt gedaan aan het accounteindpunt van de IdP.
unknown (standaard) De unknown status wordt ingesteld voordat de IdP een signaal verzendt via de Login Status API. Wanneer de status unknown is, stuurt de browser een verzoek naar het account-eindpunt van de IdP en werkt de status bij op basis van de respons van het account-eindpunt.

Om aan te geven dat de gebruiker is aangemeld, stuurt u een Set-Login: logged-in HTTP-header in een navigatie op het hoogste niveau of een aanvraag voor een subresource op dezelfde site bij de IdP-oorsprong:

  Set-Login: logged-in

U kunt ook de JavaScript-methode navigator.login.setStatus('logged-in') aanroepen vanuit de IdP-oorsprong in een navigatie op het hoogste niveau:

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

De inlogstatus van de gebruiker wordt ingesteld op logged-in .

Om aan te geven dat de gebruiker is afgemeld bij al zijn/haar accounts, stuurt u een Set-Login: logged-out HTTP-header in een navigatie op het hoogste niveau of een aanvraag voor een subresource op dezelfde site bij de IdP-oorsprong:

  Set-Login: logged-out

U kunt ook de JavaScript API navigator.login.setStatus('logged-out') aanroepen vanuit de IdP-oorsprong in een navigatie op het hoogste niveau:

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

De inlogstatus van de gebruiker wordt ingesteld op logged-out .

De unknown status wordt ingesteld voordat de IdP een signaal verzendt via de Login Status API. De browser doet een verzoek aan het account-eindpunt van de IdP en werkt de status bij op basis van de respons van het account-eindpunt:

  • Als het eindpunt een lijst met actieve accounts retourneert, werkt u de status bij naar logged-in en opent u het FedCM-dialoogvenster om deze accounts weer te geven.
  • Als het eindpunt geen accounts retourneert, werk dan de status bij naar logged-out en laat de FedCM-aanroep mislukken.

Laat de gebruiker inloggen via een dynamische inlogstroom

Hoewel de IdP de inlogstatus van de gebruiker blijft doorgeven aan de browser, kan deze niet synchroon lopen, bijvoorbeeld wanneer de sessie verloopt. De browser probeert een verzoek met referenties te verzenden naar het eindpunt van de accounts wanneer de inlogstatus ' logged-in is, maar de server retourneert geen accounts omdat de sessie niet langer beschikbaar is. In een dergelijk scenario kan de browser de gebruiker dynamisch laten inloggen bij de IdP via een dialoogvenster .