Implémenter une solution d'identité avec FedCM côté fournisseur d'identité

L'implémentation de FedCM comprend plusieurs étapes de base pour le fournisseur d'identité (IdP) et la partie de confiance (RP). Consultez la documentation pour savoir comment implémenter FedCM côté fournisseur d'identité.

Les IdPs doivent suivre les étapes suivantes pour implémenter FedCM :

Créer un fichier well-known

Pour empêcher les trackers d'utiliser l'API de manière abusive, un fichier .well-known doit être diffusé à partir de /.well-known/web-identity de l'eTLD+1 de l'IdP.

Le fichier connu peut inclure les propriétés suivantes :

Propriété Requis Description
provider_urls required Tableau des chemins d'accès aux fichiers de configuration IdP. Ignoré (mais toujours obligatoire) si accounts_endpoint et login_url sont spécifiés.
accounts_endpoint recommandé, nécessite login_url
URL du point de terminaison des comptes. Cela permet de prendre en charge plusieurs configurations, à condition que chaque fichier de configuration utilise la même URL login_url et accounts_endpoint.

Remarque : Le paramètre est compatible avec Chrome 132 et les versions ultérieures.
login_url recommandé, nécessite accounts_endpoint L'URL de la page de connexion permettant à l'utilisateur de se connecter à l'IdP. Cela permet de prendre en charge plusieurs configurations, à condition que chaque fichier de configuration utilise les mêmes login_url et accounts_endpoint.

Remarque : Le paramètre est compatible à partir de Chrome 132.

Par exemple, si les points de terminaison de l'IdP sont diffusés sous https://accounts.idp.example/, ils doivent également diffuser un fichier well-known à l'adresse https://idp.example/.well-known/web-identity, ainsi qu'un fichier de configuration IdP. Voici un exemple de contenu de fichier connu :

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

Les IdP peuvent accepter plusieurs fichiers de configuration pour un IdP en spécifiant accounts_endpoint et login_url dans le fichier well-known. Cette fonctionnalité peut être utile dans les cas suivants :

  • Un IdP doit être compatible avec plusieurs configurations de test et de production.
  • Un IdP doit être compatible avec différentes configurations par région (par exemple, eu-idp.example et us-idp.example).

Pour prendre en charge plusieurs configurations (par exemple, pour faire la différence entre un environnement de test et un environnement de production), l'IdP doit spécifier accounts_endpoint et login_url :

  {
    // 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"
  }

Créer un fichier de configuration IdP et des points de terminaison

Le fichier de configuration IdP fournit une liste des points de terminaison requis pour le navigateur. Les IdP doivent héberger un ou plusieurs fichiers de configuration, ainsi que les points de terminaison et les URL requis. Toutes les réponses JSON doivent être diffusées avec le type de contenu application/json.

L'URL du fichier de configuration est déterminée par les valeurs fournies à l'appel navigator.credentials.get() exécuté sur un RP. Le RP transmettra l'URL du fichier de configuration pour chaque fournisseur d'identité :

  // 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
  }

Le navigateur récupère le fichier de configuration avec une requête GET sans les en-têtes Origin ni Referer. La requête ne contient pas de cookies et ne suit pas les redirections. Cela empêche efficacement le fournisseur d'identité de savoir qui a envoyé la demande et quel fournisseur de services tente de se connecter. Exemple :

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

Le FIP doit implémenter un point de terminaison de configuration qui répond avec un JSON. Le JSON inclut les propriétés suivantes :

Propriété Description
accounts_endpoint (obligatoire) URL du point de terminaison des comptes.
account_label (facultatif) Chaîne de libellé de compte personnalisé, qui détermine les comptes à renvoyer lorsque ce fichier de configuration est utilisé, par exemple : "account_label": "developer".
Un IdP peut implémenter un libellé de compte personnalisé comme suit :

Par exemple, un IdP implémente un fichier de configuration "https://idp.example/developer-config.json" avec "account_label": "developer" spécifié. Le fournisseur d'identité marque également certains comptes avec le libellé "developer" à l'aide du paramètre label_hints dans le point de terminaison des comptes. Lorsqu'un RP appelle navigator.credentials.get() avec le fichier de configuration "https://idp.example/developer-config.json" spécifié, seuls les comptes portant le libellé "developer" sont renvoyés.

Remarque : Les libellés de compte personnalisés sont compatibles à partir de Chrome 132.
supports_use_other_account (facultatif) Valeur booléenne indiquant si l'utilisateur peut se connecter avec un compte différent de celui avec lequel il est actuellement connecté (si le fournisseur d'identité accepte plusieurs comptes). Cela ne s'applique qu'au mode actif.
client_metadata_endpoint (facultatif) URL du point de terminaison des métadonnées client.
id_assertion_endpoint (obligatoire) URL du point de terminaison d'assertion d'identité.
disconnect (facultatif) URL du point de terminaison de déconnexion.
login_url (obligatoire) L'URL de la page de connexion permettant à l'utilisateur de se connecter à l'IdP.
branding (facultatif) Objet contenant différentes options de branding.
branding.background_color (facultatif) Option de branding qui définit la couleur d'arrière-plan du bouton "Continuer en tant que…". Utilisez la syntaxe CSS appropriée, à savoir hex-color, hsl(), rgb() ou named-color.
branding.color (facultatif) Option de personnalisation qui définit la couleur du texte du bouton "Continuer en tant que…". Utilisez la syntaxe CSS appropriée, à savoir hex-color, hsl(), rgb() ou named-color.
branding.icons (facultatif) Tableau d'objets d'icône. Ces icônes s'affichent dans la boîte de dialogue de connexion. L'objet icône comporte deux paramètres :
  • url (obligatoire) : URL de l'image de l'icône. Il n'est pas compatible avec les images SVG.
  • size (facultatif) : dimensions de l'icône, supposées être carrées et à résolution unique. Ce nombre doit être supérieur ou égal à 25 px en mode passif et supérieur ou égal à 40 px en mode actif.

Voici un exemple de corps de réponse de l'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
      }]
    }
  }

Une fois que le navigateur a récupéré le fichier de configuration, il envoie les requêtes suivantes aux points de terminaison IdP :

Points de terminaison IdP
Points de terminaison IdP

Utiliser un autre compte

Les utilisateurs peuvent passer à un compte différent de celui avec lequel ils sont actuellement connectés, si le fournisseur d'identité prend en charge plusieurs comptes ou le remplacement du compte existant.

Pour permettre à l'utilisateur de choisir d'autres comptes, l'IdP doit spécifier cette fonctionnalité dans le fichier de configuration :

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

Point de terminaison "Accounts"

Le point de terminaison des comptes de l'IdP renvoie la liste des comptes auxquels l'utilisateur est connecté sur l'IdP. Si le fournisseur d'identité accepte plusieurs comptes, ce point de terminaison renverra tous les comptes connectés.

Le navigateur envoie une requête GET avec des cookies avec SameSite=None, mais sans paramètre client_id, en-tête Origin ni en-tête Referer. Cela empêche efficacement le fournisseur d'identité de savoir à quel fournisseur de services l'utilisateur tente de se connecter. Exemple :

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

Lors de la réception de la demande, le serveur doit :

  1. Vérifiez que la requête contient un en-tête HTTP Sec-Fetch-Dest: webidentity.
  2. Faites correspondre les cookies de session aux ID des comptes déjà connectés.
  3. Répondez en fournissant la liste des comptes.

Le navigateur attend une réponse JSON qui inclut une propriété accounts avec un tableau d'informations sur le compte, avec les propriétés suivantes :

Propriété Description
id (obligatoire) ID unique de l'utilisateur.
name Nom complet de l'utilisateur en fonction de ses paramètres régionaux et de ses préférences.

Remarque : À partir de Chrome 141, au moins l'un des paramètres name, email, username ou tel est requis. Dans les versions antérieures de Chrome, name et email sont obligatoires.
username Nom d'utilisateur choisi par l'utilisateur.

Remarque : À partir de Chrome 141, au moins l'un des paramètres name, email, username ou tel est requis.
email Adresse e-mail de l'utilisateur.

Remarque : À partir de Chrome 141, au moins l'un des paramètres name, email, username ou tel est requis. Dans les versions antérieures de Chrome, name et email sont obligatoires.
tel Numéro de téléphone de l'utilisateur.

Remarque : À partir de Chrome 141, au moins l'un des paramètres name, email, username ou tel est requis.
picture (facultatif) URL de l'image de l'avatar de l'utilisateur.
given_name (facultatif) Prénom de l'utilisateur.
approved_clients (facultatif) Tableau des ID client RP auxquels l'utilisateur s'est inscrit.
login_hints (facultatif) Tableau de tous les types de filtres possibles que l'IdP accepte pour spécifier un compte. Le RP peut appeler navigator.credentials.get() avec la propriété loginHint pour afficher de manière sélective le compte spécifié.
domain_hints (facultatif) Tableau de tous les domaines auxquels le compte est associé. Le RP peut appeler navigator.credentials.get() avec une propriété domainHint pour filtrer les comptes.
label_hints (facultatif) Tableau de libellés de compte personnalisés auxquels un compte est associé.
Un IdP peut implémenter un libellé de compte personnalisé comme suit :
  • Spécifiez les libellés de compte dans le point de terminaison des comptes (à l'aide du paramètre label_hints).
  • Créez un fichier de configuration pour chaque libellé spécifique.

Par exemple, un IdP implémente un fichier de configuration https://idp.example/developer-config.json avec "account_label": "developer" spécifié. Le fournisseur d'identité marque également certains comptes avec le libellé "developer" à l'aide du paramètre label_hints dans le point de terminaison des comptes. Lorsqu'un RP appelle navigator.credentials.get() avec un fichier de configuration https://idp.example/developer-config.json spécifié, seuls les comptes portant le libellé "developer" sont renvoyés.

Les libellés de compte personnalisés sont différents de l'indice de connexion et de l'indice de domaine, car ils sont entièrement gérés par le serveur IdP, et le RP ne spécifie que le fichier de configuration à utiliser.

Remarque : Les libellés de compte personnalisés sont compatibles à partir de Chrome 132.

Exemple de corps de réponse :

  {
    "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"]
    }]
  }

Si l'utilisateur n'est pas connecté, répondez avec HTTP 401 (Non autorisé).

La liste des comptes renvoyée est utilisée par le navigateur et ne sera pas disponible pour le fournisseur d'identité.

Point de terminaison d'assertion d'identité

Le point de terminaison d'assertion d'identité de l'IdP renvoie une assertion pour l'utilisateur connecté. Lorsque l'utilisateur se connecte à un site Web RP à l'aide de l'appel navigator.credentials.get(), le navigateur envoie une requête POST avec des cookies contenant SameSite=None et un type de contenu application/x-www-form-urlencoded à ce point de terminaison avec les informations suivantes :

Propriété Description
client_id (obligatoire) Identifiant client du RP.
account_id (obligatoire) Identifiant unique de l'utilisateur qui se connecte.
disclosure_text_shown Le résultat est une chaîne de "true" ou "false" (plutôt qu'une valeur booléenne). Le résultat est "false" dans les cas suivants :
  • Si le texte de divulgation ne s'est pas affiché, c'est parce que l'ID client du RP était inclus dans la liste des propriétés approved_clients de la réponse du point de terminaison des comptes.
  • Si le texte d'information n'a pas été affiché, car le navigateur a observé un moment d'inscription dans le passé en l'absence de approved_clients.
  • Si le paramètre fields n'inclut pas les trois champs ("name", "email" et "picture"), par exemple fields=[ ] ou fields=['name', 'picture']. Cela est nécessaire pour assurer la rétrocompatibilité avec les anciennes implémentations.

    Remarque : À partir de Chrome 141, le texte de divulgation peut s'afficher même si la valeur disclosure_text_shown est "false". Pour vérifier si le texte de divulgation a été affiché, vérifiez plutôt la valeur disclosure_shown_for.
disclosure_shown_for Liste les champs que le navigateur a affichés à l'utilisateur dans le texte de divulgation pour l'informer des données que le RP demande à l'IdP.
is_auto_selected Si une réauthentification automatique est effectuée sur le RP, is_auto_selected indique "true". Sinon, il est défini sur "false". Cela permet de prendre en charge davantage de fonctionnalités liées à la sécurité. Par exemple, certains utilisateurs peuvent préférer un niveau de sécurité plus élevé qui nécessite une médiation explicite de l'utilisateur lors de l'authentification. Si un fournisseur d'identité reçoit une demande de jeton sans cette médiation, il peut la traiter différemment. Par exemple, renvoyez un code d'erreur afin que le RP puisse appeler à nouveau l'API FedCM avec mediation: required.
fields (facultatif) Tableau de chaînes spécifiant les informations utilisateur que le RP a demandé à l'IdP de partager. Les champs suivants peuvent être spécifiés de manière facultative :
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
Le navigateur enverra fields, disclosure_text_shown et disclosure_shown_for listant les champs spécifiés dans la requête POST, comme dans l'exemple suivant.

Remarque : L'API Fields est compatible avec Chrome 132 et les versions ultérieures. Les champs"username" et"tel" sont compatibles à partir de Chrome 141.
params (facultatif) Tout objet JSON valide permettant de spécifier des paramètres clé-valeur personnalisés supplémentaires, par exemple :
  • scope : valeur de chaîne contenant les autorisations supplémentaires que le RP doit demander, par exemple "drive.readonly calendar.readonly"
  • nonce : chaîne aléatoire fournie par le RP pour s'assurer que la réponse est émise pour cette requête spécifique. Empêche les attaques par relecture.
  • Autres paramètres de clé-valeur personnalisés.
Lorsque le navigateur envoie une requête POST, la valeur params est sérialisée au format JSON, puis encodée en pourcentage.

Remarque : L'API Parameters est compatible avec Chrome 132 et versions ultérieures.

Exemple d'en-tête HTTP :

  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

Lors de la réception de la demande, le serveur doit :

  1. Répondez à la requête avec CORS (Cross-Origin Resource Sharing).
  2. Vérifiez que la requête contient un en-tête HTTP Sec-Fetch-Dest: webidentity.
  3. Faites correspondre l'en-tête Origin à l'origine RP déterminée par client_id. Refusez-les s'ils ne correspondent pas.
  4. Faites correspondre account_id à l'ID du compte déjà connecté. Refusez-les s'ils ne correspondent pas.
  5. Répondez avec un jeton. Si la requête est refusée, répondez avec une réponse d'erreur.

Le fournisseur d'identité peut décider de la manière dont il émet le jeton. En général, il est signé avec des informations telles que l'ID de compte, l'ID client, l'origine de l'émetteur et le nonce, afin que la RP puisse vérifier l'authenticité du jeton.

Le navigateur attend une réponse JSON qui inclut la propriété suivante :

Propriété Description
token Un jeton est une chaîne contenant des revendications sur l'authentification.
continue_on URL de redirection permettant une procédure de connexion en plusieurs étapes.

Le jeton renvoyé est transmis au RP par le navigateur, afin que le RP puisse valider l'authentification.

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

Continuer sur une fonctionnalité

Le fournisseur d'identité peut fournir une URL de redirection dans la réponse du point de terminaison d'assertion d'identité pour activer un flux de connexion en plusieurs étapes. Cela est utile lorsque le fournisseur d'identité doit demander des informations ou des autorisations supplémentaires, par exemple :

  • Autorisation d'accéder aux ressources côté serveur de l'utilisateur.
  • Vérification que les coordonnées sont à jour.
  • Contrôle parental.

Le point de terminaison d'assertion d'identité peut renvoyer une propriété continue_on qui inclut un chemin absolu ou relatif vers le point de terminaison d'assertion d'identité.

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

Si la réponse contient le paramètre continue_on, une nouvelle fenêtre pop-up s'ouvre et redirige l'utilisateur vers le chemin d'accès spécifié. Après l'interaction de l'utilisateur avec la page continue_on, l'IdP doit appeler IdentityProvider.resolve() avec le jeton transmis en tant qu'argument afin que la promesse de l'appel navigator.credentials.get() d'origine puisse être résolue :

  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);
  });

Le navigateur fermera ensuite automatiquement le pop-up et renverra le jeton à l'appelant de l'API. Un appel IdentityProvider.resolve() unique est le seul moyen pour la fenêtre parente (RP) et la fenêtre pop-up (IdP) de communiquer.
Si l'utilisateur refuse la demande, l'IdP peut fermer la fenêtre en appelant IdentityProvider.close().

  IdentityProvider.close();

L'API Continuation nécessite une interaction explicite de l'utilisateur (clics) pour fonctionner. Voici comment l'API Continuation fonctionne avec différents modes de médiation :

  • En mode passive :
    • mediation: 'optional' (par défaut) : l'API Continuation ne fonctionnera qu'avec un geste de l'utilisateur, par exemple en cliquant sur un bouton de la page ou sur l'UI FedCM. Lorsque la réauthentification automatique est déclenchée sans geste de l'utilisateur, aucune fenêtre pop-up n'est ouverte et la promesse est rejetée.
    • mediation: 'required' : demande toujours à l'utilisateur d'interagir, de sorte que l'API Continuation fonctionne toujours.
  • En mode actif :
    • L'activation de l'utilisateur est toujours requise. L'API Continuation est toujours compatible.

Si, pour une raison quelconque, l'utilisateur a modifié son compte dans le pop-up (par exemple, si le fournisseur d'identité propose une fonction "utiliser un autre compte", ou dans les cas de délégation), l'appel de résolution accepte un deuxième argument facultatif permettant quelque chose comme :

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

Renvoyer une réponse d'erreur

L'id_assertion_endpoint peut également renvoyer une réponse "error" (erreur), qui comporte deux champs facultatifs :

  • code : le fournisseur d'identité peut choisir l'une des erreurs connues de la liste des erreurs spécifiées OAuth 2.0 (invalid_request, unauthorized_client, access_denied, server_error et temporarily_unavailable) ou utiliser n'importe quelle chaîne arbitraire. Dans ce cas, Chrome affiche l'interface utilisateur d'erreur avec un message d'erreur générique et transmet le code au RP.
  • url : identifie une page Web lisible par l'utilisateur contenant des informations sur l'erreur afin de fournir des détails supplémentaires aux utilisateurs. Ce champ est utile aux utilisateurs, car les navigateurs ne peuvent pas fournir de messages d'erreur détaillés dans une UI intégrée. Par exemple, des liens vers les étapes suivantes ou les coordonnées du service client. Si un utilisateur souhaite en savoir plus sur les détails de l'erreur et sur la façon de la corriger, il peut consulter la page fournie dans l'interface utilisateur du navigateur. L'URL doit appartenir au même site que l'configURL de l'IdP.
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }

Libellés de compte personnalisés

Avec les libellés de compte personnalisés, l'IdP peut annoter les comptes utilisateur avec des libellés, et le RP peut choisir de n'extraire que les comptes portant des libellés spécifiques en spécifiant le configURL pour ce libellé. Cela peut être utile lorsqu'un RP doit filtrer les comptes selon des critères spécifiques, par exemple pour n'afficher que les comptes spécifiques à un rôle tels que "developer" ou "hr".

Un filtrage similaire est possible à l'aide des fonctionnalités Indice de domaine et Indice de connexion, en les spécifiant dans l'appel navigator.credentials.get(). Toutefois, les libellés de compte personnalisés peuvent filtrer les utilisateurs en spécifiant le fichier de configuration, ce qui est particulièrement utile lorsque plusieurs configURLs sont utilisées. Les libellés de compte personnalisés sont également différents, car ils sont fournis par le serveur IdP, et non par le RP, comme les indices de connexion ou de domaine.

Prenons l'exemple d'un IdP qui souhaite faire la différence entre les comptes "developer" et "hr". Pour ce faire, l'IdP doit être compatible avec deux configURL pour "developer" et "hr", respectivement :

  • Le fichier de configuration pour les développeurs https://idp.example/developer/fedcm.json comporte un libellé "developer", et le fichier de configuration pour les entreprises https://idp.example/hr/fedcm.json comporte un libellé "hr", comme suit :
  // 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"
  }
  • Avec une telle configuration, le fichier well-known doit inclure accounts_endpoint et login_url pour autoriser plusieurs configURLs :
  {
    "provider_urls": [ "https://idp.example/fedcm.json" ],
    "accounts_endpoint": "https://idp.example/accounts",
    "login_url": "https://idp.example/login"
  }
  • Le point de terminaison des comptes de l'IdP commun (https://idp.example/accounts dans cet exemple) renvoie une liste de comptes qui inclut une propriété label_hints avec des libellés attribués dans un tableau pour chaque compte :
  {
  "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"]
    }]
  }

Lorsqu'un fournisseur d'identité souhaite autoriser les utilisateurs "hr" à se connecter, il peut spécifier le configURL https://idp.example/hr/fedcm.json dans l'appel navigator.credentials.get() :

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

Par conséquent, seul l'ID de compte 4567 est disponible pour la connexion de l'utilisateur. L'ID de compte de 123 est masqué par le navigateur afin que l'utilisateur ne reçoive pas de compte non compatible avec le fournisseur d'identité sur ce site.

Autres points à prendre en compte :

  • Les libellés sont des chaînes. Si le tableau label_hints ou le champ account_label utilise une valeur qui n'est pas une chaîne, cette valeur est ignorée.
  • Si aucun libellé n'est spécifié dans configURL, tous les comptes s'affichent dans le sélecteur de compte FedCM.
  • Si aucun libellé n'est spécifié pour un compte, ce compte ne s'affichera dans le sélecteur de compte que si configURL ne spécifie pas non plus de libellé.
  • Si aucun compte ne correspond au libellé demandé en mode passif (comme la fonctionnalité d'indice de domaine), la boîte de dialogue FedCM affiche une invite de connexion, qui permet à l'utilisateur de se connecter à un compte IdP. Pour le mode actif, la fenêtre pop-up de connexion s'ouvre directement.

Déconnecter un point de terminaison

En appelant IdentityCredential.disconnect(), le navigateur envoie une requête POST cross-origin avec des cookies avec SameSite=None et un type de contenu application/x-www-form-urlencoded à ce point de terminaison de déconnexion avec les informations suivantes :

Propriété Description
account_hint Indice pour le compte IdP.
client_id Identifiant client du 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

Lors de la réception de la demande, le serveur doit :

  1. Répondez à la requête avec CORS (Cross-Origin Resource Sharing).
  2. Vérifiez que la requête contient un en-tête HTTP Sec-Fetch-Dest: webidentity.
  3. Faites correspondre l'en-tête Origin à l'origine RP déterminée par client_id. Refusez-les s'ils ne correspondent pas.
  4. Faites correspondre account_hint aux ID des comptes déjà connectés.
  5. Dissociez le compte utilisateur du RP.
  6. Répondez au navigateur en lui fournissant les informations du compte utilisateur identifié au format JSON.

Voici un exemple de charge utile JSON de réponse :

  {
    "account_id": "account456"
  }

En revanche, si le fournisseur d'identité souhaite que le navigateur déconnecte tous les comptes associés au RP, transmettez une chaîne qui ne correspond à aucun ID de compte, par exemple "*".

Point de terminaison des métadonnées client

Le point de terminaison des métadonnées du client de l'IdP renvoie les métadonnées de la partie de confiance, telles que les règles de confidentialité, les conditions d'utilisation et les icônes de logo de la partie de confiance. Les RP doivent fournir à l'IdP des liens vers leurs règles de confidentialité et leurs conditions d'utilisation à l'avance. Ces liens s'affichent dans la boîte de dialogue de connexion lorsque l'utilisateur ne s'est pas encore inscrit sur le RP avec l'IdP.

Le navigateur envoie une requête GET à l'aide de client_id navigator.credentials.get sans cookies. Exemple :

  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

Lors de la réception de la demande, le serveur doit :

  1. Déterminez le RP pour client_id.
  2. Répondez avec les métadonnées du client.

Les propriétés du point de terminaison des métadonnées client incluent les suivantes :

Propriété Description
privacy_policy_url (facultatif) URL des règles de confidentialité du RP.
terms_of_service_url (facultatif) URL des conditions d'utilisation de la RP.
icons (facultatif) Tableau d'objets, comme [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

Le navigateur s'attend à recevoir une réponse JSON du point de terminaison :

  {
    "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
      }]
  }

Les métadonnées client renvoyées sont utilisées par le navigateur et ne seront pas disponibles pour le RP.

URL de connexion

Ce point de terminaison permet à l'utilisateur de se connecter à l'IdP.

Avec l'API Login Status, l'IdP doit informer le navigateur de l'état de connexion de l'utilisateur. Toutefois, l'état peut être désynchronisé, par exemple lorsque la session expire. Dans ce cas, le navigateur peut permettre à l'utilisateur de se connecter dynamiquement à l'IdP via l'URL de la page de connexion spécifiée avec le login_url du fichier de configuration de l'IdP.

La boîte de dialogue FedCM affiche un message suggérant une connexion, comme illustré dans l'image suivante.

Boîte de dialogue FedCM suggérant de se connecter à l'IdP.
Boîte de dialogue FedCM suggérant de se connecter au fournisseur d'identité.

Lorsque l'utilisateur clique sur le bouton Continuer, le navigateur ouvre une fenêtre pop-up pour la page de connexion du fournisseur d'identité.

Exemple de boîte de dialogue FedCM.
Exemple de boîte de dialogue affichée après avoir cliqué sur le bouton de connexion à l'IdP.

La boîte de dialogue est une fenêtre de navigateur standard qui contient des cookies propriétaires. Tout ce qui se passe dans la boîte de dialogue dépend de l'IdP. Aucune poignée de fenêtre n'est disponible pour envoyer une demande de communication cross-origin à la page RP. Une fois l'utilisateur connecté, le fournisseur d'identité doit :

  • Envoyez l'en-tête Set-Login: logged-in ou appelez l'API navigator.login.setStatus("logged-in") pour informer le navigateur que l'utilisateur est connecté.
  • Appelez IdentityProvider.close() pour fermer la boîte de dialogue.
Un utilisateur se connecte à un RP après s'être connecté à l'IdP à l'aide de FedCM.

Informer le navigateur de l'état de connexion de l'utilisateur

L'API Login Status est un mécanisme qui permet à un site Web, en particulier un IdP, d'informer le navigateur de l'état de connexion de l'utilisateur sur l'IdP. Grâce à cette API, le navigateur peut réduire les requêtes inutiles envoyées au fournisseur d'identité et atténuer les potentielles attaques par temporisation.

Les IdP peuvent signaler l'état de connexion de l'utilisateur au navigateur en envoyant un en-tête HTTP ou en appelant une API JavaScript lorsque l'utilisateur est connecté à l'IdP ou lorsqu'il est déconnecté de tous ses comptes IdP. Pour chaque IdP (identifié par son URL de configuration), le navigateur conserve une variable à trois états représentant l'état de connexion avec les valeurs possibles suivantes :

  • logged-in
  • logged-out
  • unknown (par défaut)
État de connexion Description
logged-in Lorsque l'état de connexion de l'utilisateur est défini sur logged-in, le RP qui appelle FedCM envoie des requêtes au point de terminaison des comptes de l'IdP et affiche les comptes disponibles à l'utilisateur dans la boîte de dialogue FedCM.
logged-out Lorsque l'état de connexion de l'utilisateur est logged-out, l'appel de FedCM échoue silencieusement sans envoyer de requête au point de terminaison des comptes du fournisseur d'identité.
unknown (par défaut) L'état unknown est défini avant que l'IdP n'envoie un signal à l'aide de l'API Login Status. Lorsque l'état est unknown, le navigateur envoie une requête au point de terminaison des comptes du fournisseur d'identité et met à jour l'état en fonction de la réponse du point de terminaison des comptes.

Pour indiquer que l'utilisateur est connecté, envoyez un en-tête HTTP Set-Login: logged-in dans une requête de navigation de premier niveau ou une requête de sous-ressource de même site à l'origine de l'IdP :

  Set-Login: logged-in

Vous pouvez également appeler la méthode JavaScript navigator.login.setStatus('logged-in') depuis l'origine du fournisseur d'identité dans une navigation de premier niveau :

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

L'état de connexion de l'utilisateur sera défini sur logged-in.

Pour indiquer que l'utilisateur est déconnecté de tous ses comptes, envoyez un en-tête HTTP Set-Login: logged-out dans une requête de navigation de premier niveau ou une requête de sous-ressource de même site à l'origine du fournisseur d'identité :

  Set-Login: logged-out

Vous pouvez également appeler l'API JavaScript navigator.login.setStatus('logged-out') depuis l'origine du fournisseur d'identité dans une navigation de premier niveau :

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

L'état de connexion de l'utilisateur sera défini sur logged-out.

L'état unknown est défini avant que l'IdP n'envoie un signal à l'aide de l'API Login Status. Le navigateur envoie une requête au point de terminaison des comptes de l'IdP et met à jour l'état en fonction de la réponse du point de terminaison des comptes :

  • Si le point de terminaison renvoie une liste de comptes actifs, définissez l'état sur logged-in et ouvrez la boîte de dialogue FedCM pour afficher ces comptes.
  • Si le point de terminaison ne renvoie aucun compte, définissez l'état sur logged-out et faites échouer l'appel FedCM.

Autoriser l'utilisateur à se connecter via un flux de connexion dynamique

Même si le fournisseur d'identité informe en permanence le navigateur de l'état de connexion de l'utilisateur, il peut être désynchronisé, par exemple lorsque la session expire. Le navigateur tente d'envoyer une requête avec identifiants au point de terminaison des comptes lorsque l'état de connexion est logged-in, mais le serveur ne renvoie aucun compte, car la session n'est plus disponible. Dans ce cas, le navigateur peut permettre à l'utilisateur de se connecter dynamiquement à l'IdP via une fenêtre pop-up.

Étapes suivantes

Implémentez FedCM pour vos RP et distribuez le SDK JavaScript. Mettez à jour vos RP en évitant de les implémenter vous-même.
Découvrez comment configurer votre environnement et déboguer votre implémentation.