Mises à jour FedCM: Phases d'évaluation pour le bundle de l'API Continuation et octroi automatique de l'API Storage Access

À partir de Chrome 126, les développeurs peuvent commencer à exécuter une phase d'évaluation d'origine pour un ensemble de fonctionnalités de l'API Federated Credential Management (FedCM) pour ordinateur de bureau qui permettent certains cas d'utilisation d'autorisation. Le bundle se compose de l'API Continuation et de l'API Parameters, qui permettent une expérience semblable à un flux d'autorisation OAuth impliquant une boîte de dialogue d'autorisation fournie par un fournisseur d'identité (IdP). Le bundle inclut également d'autres modifications telles que l'API Fields, plusieurs configURL et des libellés de compte personnalisés. À partir de Chrome 126, nous lançons également une phase d'évaluation pour l'API Storage Access (SAA) qui accorde automatiquement les requêtes SAA si l'utilisateur s'est déjà connecté à l'aide de FedCM.

Phase d'évaluation de l'origine : groupe d'API FedCM Continuation

Le bundle d'API de continuation FedCM se compose de plusieurs extensions FedCM :

API Continuation

Un utilisateur se connecte à l'RP, puis s'autorise via le mode bouton.

Vous pouvez consulter une démonstration de l'API sur Glitch.

L'API Continuation permet au point de terminaison d'assertion d'ID du fournisseur d'identité de renvoyer éventuellement une URL que FedCM affichera pour permettre à l'utilisateur de poursuivre un flux de connexion en plusieurs étapes. Cela permet au fournisseur d'identité de demander à l'utilisateur d'accorder à la partie de confiance des autorisations autres que celles qui sont possibles dans l'interface utilisateur FedCM existante, telles que l'accès aux ressources côté serveur de l'utilisateur.

En règle générale, le point de terminaison d'assertion d'identité renvoie un jeton requis pour l'authentification.

{
  "token": "***********"
}

Toutefois, avec l'API Continuation, le point de terminaison d'assertion d'ID peut renvoyer une propriété continue_on qui inclut un chemin absolu ou un chemin relatif vers le point de terminaison d'assertion d'ID.

{
  // In the id_assertion_endpoint, instead of returning a typical
  // "token" response, the IdP decides that it needs the user to
  // continue on a pop-up window:
  "continue_on": "/oauth/authorize?scope=..."
}

Dès que le navigateur reçoit la réponse continue_on, une nouvelle fenêtre pop-up s'ouvre et redirige l'utilisateur vers le chemin d'accès spécifié.

Une fois que l'utilisateur a interagi avec la page (par exemple, en accordant une autorisation supplémentaire pour partager des informations supplémentaires avec le RP), la page du fournisseur d'identité peut appeler IdentityProvider.resolve() pour résoudre l'appel navigator.credentials.get() d'origine et renvoyer un jeton en tant qu'argument.

document.getElementById('allow_btn').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 ferme ensuite automatiquement la fenêtre pop-up et renvoie le jeton à l'appelant de l'API.

Si l'utilisateur refuse la requête, vous pouvez fermer la fenêtre en appelant IdentityProvider.close().

IdentityProvider.close();

Si, pour une raison quelconque, l'utilisateur a modifié son compte dans la fenêtre pop-up (par exemple, le fournisseur d'identité propose une fonction "changer d'utilisateur" ou dans les cas de délégation), l'appel de résolution accepte un second argument facultatif qui autorise un élément semblable à celui-ci:

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

API Parameters

L'API Parameters permet au RP de fournir des paramètres supplémentaires au point de terminaison d'assertion d'identité. Avec l'API Parameters, les RP peuvent transmettre des paramètres supplémentaires au fournisseur d'identité afin de demander des autorisations pour des ressources autres que la connexion de base. L'utilisateur autorise ces autorisations via un flux d'expérience utilisateur contrôlé par l'IdP, qui est lancé via l'API Continuation.

Pour utiliser l'API, ajoutez des paramètres à la propriété params en tant qu'objet dans l'appel navigator.credentials.get().

let {token} = await navigator.credentials.get({
  identity: {
    providers: [{
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      // Key/value pairs that need to be passed from the
      // RP to the IdP but that don't really play any role with
      // the browser.
      params: {
        IDP_SPECIFIC_PARAM: '1',
        foo: 'BAR',
        ETC: 'MOAR',
        scope: 'calendar.readonly photos.write',
      }
    },
  }
});

Les noms de propriété de l'objet params sont précédés de param_. Dans l'exemple ci-dessus, la propriété params contient IDP_SPECIFIC_PARAM sous la forme '1', foo sous la forme 'BAR', ETC sous la forme 'MOAR' et scope sous la forme 'calendar.readonly photos.write'. Il sera traduit par param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write dans le corps HTTP de la requête:

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=234234&disclosure_text_shown=false&param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write

Obtenir les autorisations de manière dynamique

En général, il est plus utile pour les utilisateurs de demander des autorisations lorsque cela est nécessaire, plutôt que lorsque le développeur estime qu'elles sont plus faciles à implémenter. Par exemple, il est préférable de demander l'autorisation d'accéder à une caméra lorsque l'utilisateur est sur le point de prendre une photo plutôt que de demander l'autorisation dès qu'il accède au site Web. La même pratique s'applique aux ressources de serveur. Ne demandez les autorisations que lorsqu'elles sont nécessaires pour l'utilisateur. C'est ce que l'on appelle l'"autorisation dynamique".

Pour demander l'autorisation de manière dynamique avec FedCM, le fournisseur d'identité peut:

  1. Appelez navigator.credentials.get() avec les paramètres obligatoires que l'IDP peut comprendre, tels que scope.
  2. Le point de terminaison d'assertion d'identité confirme que l'utilisateur est déjà connecté et répond avec une URL continue_on.
  3. Le navigateur ouvre une fenêtre pop-up avec la page d'autorisation de l'IDP demandant une autorisation supplémentaire correspondant aux champs d'application demandés.
  4. Une fois autorisée via IdentityProvider.resolve() par le fournisseur d'identité, la fenêtre est fermée et l'appel navigator.credentials.get() d'origine de la RP obtient un jeton approprié ou un code d'autorisation afin que la RP puisse l'échanger avec un jeton d'accès approprié.

API Fields

L'API Fields permet à la RP de déclarer des attributs de compte à demander au fournisseur d'identité afin que le navigateur puisse afficher une UI de divulgation appropriée dans la boîte de dialogue FedCM. Il appartient au fournisseur d'identité d'inclure les champs demandés dans le jeton renvoyé. Envisagez de demander un "profil de base" dans OpenID Connect plutôt que des "champs d'application" dans OAuth.

Message d'information en mode widget.
Message d'information en mode widget.
Message de divulgation en mode bouton.
Message d'information en mode bouton.

Pour utiliser l'API Fields, ajoutez des paramètres à la propriété fields en tant que tableau dans l'appel navigator.credentials.get(). Pour le moment, les champs peuvent contenir 'name', 'email' et 'picture', mais ils pourront être étendus pour inclure d'autres valeurs à l'avenir.

Une requête avec fields se présente comme suit :

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: ['name', 'email', 'picture'],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

La requête HTTP envoyée au point de terminaison d'assertion d'ID inclut le paramètre fields spécifié par le RP, avec le paramètre disclosure_text_shown défini sur true s'il ne s'agit pas d'un utilisateur connu, ainsi que les champs que le navigateur a divulgués à l'utilisateur dans un paramètre disclosure_shown_for :

POST /id_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=234234&disclosure_text_shown=true&fields=email,name,picture&disclosure_shown_for=email,name,picture

Si la RP a besoin d'accéder à des données supplémentaires du fournisseur d'identité, telles que l'accès à un agenda, cela doit être géré avec un paramètre personnalisé, comme indiqué ci-dessus. Le fournisseur d'identité renvoie une URL continue_on pour demander l'autorisation.

Si fields est un tableau vide, la requête se présente comme suit :

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: [],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

Si fields est un tableau vide, le user-agent ignore l'interface utilisateur de divulgation.

Le message d'information ne s'affiche pas en mode widget. Dans le flux de boutons, l'UI d'informations est complètement ignorée.
Le message de divulgation ne s'affiche pas en mode widget. Lors du parcours du bouton, l'interface utilisateur du communiqué est complètement ignorée.

C'est le cas même si la réponse du point de terminaison des comptes ne contient pas d'ID client correspondant à la RP dans approved_clients.

Dans ce cas, le disclosure_text_shown envoyé au point de terminaison de l'assertion d'ID est défini sur "false" dans le corps HTTP:

POST /id_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=234234&disclosure_text_shown=false

Plusieurs configURL

L'utilisation de plusieurs configURL permet aux fournisseurs d'identité d'accepter plusieurs fichiers de configuration, en spécifiant accounts_endpoint et login_url dans le fichier connu de la même manière que dans les fichiers de configuration.

Si accounts_endpoint et login_url sont ajoutés au fichier well-known, les provider_urls sont ignorés afin que le fournisseur d'identité puisse prendre en charge plusieurs fichiers de configuration. Si ce n'est pas le cas, provider_urls continue de prendre effet pour assurer la rétrocompatibilité.

Le fichier bien connu qui prend en charge plusieurs configURL peut se présenter comme suit:

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

que nous utilisons aux fins suivantes :

  1. Assurer la rétrocompatibilité avec les fichiers connus existants et la version antérieure des navigateurs déjà déployés.
  2. disposer d'un nombre arbitraire de fichiers de configuration, à condition qu'ils pointent tous vers les mêmes accounts_endpoint et login_url ;
  3. Vous n'avez pas la possibilité d'ajouter l'entropie à la requête d'extraction avec identifiants effectuée à accounts_endpoint, car elle doit être spécifiée au niveau ".well-known".

La prise en charge de plusieurs configURL est facultative, et les implémentations FedCM existantes peuvent rester les mêmes.

Libellés de compte personnalisés

Les libellés de compte personnalisés permettent aux fournisseurs d'identité FedCM d'annoter les comptes afin que les tiers assujettis à des restrictions puissent les filtrer en spécifiant le libellé dans un fichier de configuration. Un filtrage similaire a été possible à l'aide de l'API Domain Hint et de l'API Login Hint en les spécifiant dans l'appel navigator.credentials.get(), mais 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és. Les libellés de compte personnalisés sont également différents en ce sens qu'ils sont fournis par le serveur de l'IDP, et non par le RP, comme les indications de connexion ou de domaine.

Exemple

Un IdP accepte deux configURL, l'une pour les consommateurs et l'autre pour les entreprises. Le fichier de configuration du client a un libellé 'consumer' et le fichier de configuration de l'entreprise un libellé 'enterprise'.

Avec une telle configuration, le fichier bien connu inclut accounts_endpoint et login_url pour autoriser plusieurs configURL.

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

Lorsque les accounts_endpoint sont fournies dans le fichier well-known, les provider_urls sont ignorées. Le RP peut pointer directement vers les fichiers de configuration respectifs dans l'appel navigator.credentials.get().

Le fichier de configuration du consommateur se trouve à l'emplacement https://idp.example/fedcm.json, qui inclut la propriété accounts qui spécifie 'consumer' à l'aide de include.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "consumer"
  }
}

Le fichier de configuration d'entreprise se trouve dans https://idp.example/enterprise/fedcm.json, qui inclut la propriété accounts qui spécifie 'enterprise' à l'aide de include.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/enterprise/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "enterprise"
  }
}

Le point de terminaison des comptes de l'IDP commun (https://idp.example/accounts dans cet exemple) renvoie une liste de comptes incluant une propriété de libellés avec un labels attribué dans un tableau pour chaque compte. Voici un exemple de réponse pour un utilisateur disposant de deux comptes. L'un est destiné aux consommateurs et l'autre aux entreprises :

{
 "accounts": [{
   "id": "123",
   "given_name": "John",
   "name": "John Doe",
   "email": "john_doe@idp.example",
   "picture": "https://idp.example/profile/123",
   "labels": ["consumer"]
  }], [{
   "id": "4567",
   "given_name": "Jane",
   "name": "Jane Doe",
   "email": "jane_doe@idp.example",
   "picture": "https://idp.example/profile/4567",
   "labels": ["enterprise"]
  }]
}

Lorsqu'un tiers assujetti à des restrictions souhaite autoriser les utilisateurs de 'enterprise' à se connecter, il peut spécifier l'URL configURL 'enterprise' 'https://idp.example/enterprise/fedcm.json' dans l'appel navigator.credentials.get():

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

Par conséquent, seul l'ID de compte '4567' est disponible pour que l'utilisateur puisse se connecter. L'ID de compte '123' est masqué en mode silencieux par le navigateur afin que l'utilisateur ne dispose pas d'un compte non compatible avec l'IdP sur ce site.

Phase d'évaluation de l'origine : FedCM en tant que signal de confiance pour l'API Storage Access

Chrome 126 lance une phase d'évaluation de FedCM en tant que signal de confiance pour l'API Storage Access. Avec cette modification, une autorisation préalable accordée via FedCM devient une raison valable d'approuver automatiquement une demande d'accès au stockage par les API Storage Access.

Cette fonctionnalité est utile lorsqu'un iFrame intégré souhaite accéder à des ressources personnalisées : par exemple, si idp.example est intégré à rp.example et doit afficher une ressource personnalisée. Si le navigateur limite l'accès aux cookies tiers, même si l'utilisateur est connecté à rp.example à l'aide de idp.example avec FedCM, l'iFrame idp.example intégré ne pourra pas demander de ressources personnalisées, car les requêtes n'incluront pas de cookies tiers.

Pour ce faire, idp.example doit obtenir une autorisation d'accès au stockage via son iFrame intégré au site Web. Cette autorisation ne peut être obtenue que via une invite d'autorisation.

Avec FedCM comme signal de confiance pour l'API Storage Access, les vérifications d'autorisation de l'API Storage Access acceptent non seulement l'octroi d'autorisation donné par une invite d'accès au stockage, mais aussi l'autorisation accordée par une invite FedCM.

// In top-level rp.example:

// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/fedcm.json',
      clientId: '123',
    }],
  },
  mediation: 'optional',
});

// In an embedded IdP iframe:

// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();

// This returns `true`.
const hasAccess = await document.hasStorageAccess();

Une fois l'utilisateur connecté à FedCM, l'autorisation est automatiquement accordée tant que l'authentification FedCM est active. Cela signifie qu'une fois l'utilisateur déconnecté, une invite s'affichera pour demander l'autorisation.

Participer à la phase d'évaluation

Vous pouvez tester le bundle de l'API FedCM Continuation en local en activant un indicateur Chrome chrome://flags#fedcm-authz dans Chrome 126 ou version ultérieure. Vous pouvez également tester FedCM en tant que signal de confiance pour l'API Storage Access localement en activant #fedcm-with-storage-access-api dans Chrome 126 ou version ultérieure.

Ces fonctionnalités sont également disponibles en phase d'évaluation. Les phases d'évaluation vous permettent de tester de nouvelles fonctionnalités et de donner votre avis sur leur facilité d'utilisation, leur utilité et leur efficacité. Pour en savoir plus, consultez Premiers pas avec les phases d'évaluation.

Pour essayer la phase d'évaluation du bundle de l'API FedCM Continuation, créez deux jetons d'évaluation d'origine:

Si vous souhaitez activer l'API Continuation avec le flux de boutons, activez également l'essai d'origine de l'API Button Mode:

Pour essayer FedCM en tant que signal de confiance pour l'essai Origin Trial de l'API Storage Access:

La phase d'évaluation du bundle d'API Continuation et FedCM en tant que signal de confiance pour la phase d'évaluation de l'API Storage Access sont disponibles à partir de Chrome 126.

Enregistrer une phase d'évaluation d'origine tierce pour le RP

  1. Accédez à la page d'enregistrement du test d'origine.
  2. Cliquez sur le bouton Register (S'inscrire) et remplissez le formulaire pour demander un jeton.
  3. Saisissez l'origine du fournisseur d'identité (IdP) sur Web Origin (Origine Web).
  4. Cochez la case "Correspondance tierce" pour injecter le jeton avec JavaScript sur d'autres origines.
  5. Cliquez sur Envoyer.
  6. Intégrez le jeton émis sur un site Web tiers.

Pour intégrer le jeton à un site Web tiers, ajoutez le code suivant à la bibliothèque JavaScript ou au SDK du fournisseur d'identité diffusé à partir de son origine.

const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);

Remplacez TOKEN_GOES_HERE par votre propre jeton.