A partir de Chrome 126, los desarrolladores pueden comenzar a ejecutar una prueba de origen para un paquete de funciones de la API de Federated Credential Management (FedCM) para computadoras que habilitan algunos casos de uso de Authorization. El paquete consta de la API de Continuation y la API de Parameters, que habilitan una experiencia similar a un flujo de autorización de OAuth que incluye un diálogo de permisos proporcionado por un proveedor de identidad (IdP). El paquete también incluye otros cambios, como la API de Fields, varias configURLs y las etiquetas personalizadas de la cuenta. A partir de Chrome 126, también presentamos una prueba de origen para la API de Storage Access (SAA) que otorga automáticamente solicitudes de SAA si el usuario accedió correctamente con FedCM en el pasado.
Prueba de origen: paquete de la API de Continuation de FedCM
El paquete de la API de Continuation de FedCM consta de varias extensiones de FedCM:
- API de Continuation
- API de Parameters
- API de Fields
- Varias configURLs
- Etiquetas personalizadas de la cuenta
API de Continuation
Puedes ver una demostración de la API en Glitch.
La API de Continuation permite que el extremo de aserción de ID del IdP muestre de manera opcional una URL que FedCM renderizará para permitir que el usuario continúe con un flujo de acceso de varios pasos. Esto permite que el IdP solicite al usuario que otorgue a la parte de confianza (RP) permisos más allá de lo que es posible en la IU de FedCM existente, como el acceso a los recursos del servidor del usuario.
Por lo general, el extremo de aserción de ID muestra un token necesario para la autenticación.
{
"token": "***********"
}
Sin embargo, con la API de Continuation, el extremo de aserción de ID puede mostrar una propiedad continue_on
que incluya una ruta de acceso absoluta o una ruta relativa al extremo de aserción de 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=..."
}
En cuanto el navegador recibe la respuesta continue_on
, se abre una nueva ventana emergente que lleva al usuario a la ruta especificada.
Después de que el usuario interactúe con la página (por ejemplo, otorga más permisos para compartir información adicional con el RP), la página del IdP puede llamar a IdentityProvider.resolve()
para resolver la llamada a navigator.credentials.get()
original y mostrar un token como argumento.
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);
});
El navegador cierra la ventana emergente por sí mismo y muestra el token al llamador de la API.
Si el usuario rechaza la solicitud, puedes llamar a IdentityProvider.close()
para cerrar la ventana.
IdentityProvider.close();
Si, por algún motivo, el usuario cambió su cuenta en la ventana emergente (por ejemplo, el IdP ofrece una función "cambiar de usuario" o, en casos de delegación), la llamada de resolución toma un segundo argumento opcional que permite algo como lo siguiente:
IdentityProvider.resolve(token, {accountId: '1234');
API de Parameters
La API de Parameters permite que el RP proporcione parámetros adicionales al extremo de aserción de ID. Con la API de Parameters, los RP pueden pasar parámetros adicionales al IdP para solicitar permisos para recursos más allá del acceso básico. El usuario autorizaría estos permisos a través de un flujo de UX controlado por IdP que se inicia a través de la API de Continuation.
Para usar la API, agrega parámetros a la propiedad params
como un objeto en la llamada a 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',
}
},
}
});
A los nombres de las propiedades del objeto params
se les antepone param_
. En el ejemplo anterior, la propiedad de los parámetros contiene IDP_SPECIFIC_PARAM
como '1'
, foo
como 'BAR'
, ETC
como 'MOAR'
y scope
como 'calendar.readonly photos.write'
.
Esto se traducirá como param_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
en el cuerpo HTTP de la solicitud:
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¶m_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
Obtén permisos de forma dinámica
En general, para los usuarios, es más útil solicitar permisos cuando los necesitan, en lugar de cuando el desarrollador cree que son más fáciles de implementar. Por ejemplo, es preferible solicitar permiso para acceder a una cámara cuando el usuario está a punto de tomar una foto en lugar de solicitar permiso tan pronto como el usuario llega al sitio web. La misma práctica se aplica a los recursos del servidor. Solicita permisos solo cuando los necesite el usuario. Esto se denomina "autorización dinámica".
Para solicitar autorización de forma dinámica con FedCM, el IdP puede hacer lo siguiente:
- Llama a
navigator.credentials.get()
con los parámetros obligatorios que el IdP puede comprender, comoscope
. - El extremo de aserción de ID confirma que el usuario ya accedió y responde con una URL
continue_on
. - El navegador abre una ventana emergente con la página de permisos del IdP en la que se solicita permiso adicional que coincide con los permisos solicitados.
- Una vez que el IdP autoriza a través de
IdentityProvider.resolve()
, se cierra la ventana, y la llamada anavigator.credentials.get()
original del RP obtiene un token relevante o un código de autorización para que el RP pueda intercambiarlo por un token de acceso adecuado.
API de Fields
La API de Fields permite que el RP declare los atributos de la cuenta para solicitar al IdP, de modo que el navegador pueda renderizar una IU de divulgación adecuada en el diálogo de FedCM. Es responsabilidad del IdP incluir los campos solicitados en el token que se muestra. Considera solicitar un "perfil básico" en OpenID Connect en comparación con "permisos" en OAuth.
![Mensaje de divulgación en el modo widget.](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-126-with-disclosure-widget.jpg?authuser=6&hl=es)
![Mensaje de divulgación en el modo de botones.](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-126-with-disclosure-button.jpg?authuser=6&hl=es)
Para usar la API de Fields, agrega parámetros a la propiedad fields
como un array en la llamada a navigator.credentials.get()
. Por ahora, los campos pueden contener 'name'
, 'email'
y 'picture'
, pero se pueden expandir para incluir más valores en el futuro.
Una solicitud con fields
se vería de la siguiente manera:
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 solicitud HTTP al extremo de aserción de ID incluye el parámetro fields
especificado por RP, con el parámetro disclosure_text_shown
configurado como true
si no se trata de un usuario recurrente, y los campos que el navegador divulgó al usuario en un parámetro 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 el RP necesita acceder a cualquier dato adicional del IdP, como acceso a un calendario, esto debe manejarse con un parámetro personalizado como se mencionó antes. El IdP muestra una URL continue_on
para solicitar permiso.
Si fields
es un array vacío, la solicitud se verá de la siguiente manera:
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
es un array vacío, el usuario-agente omitirá la IU de divulgación.
![El mensaje de divulgación no se muestra en el modo widget. En el flujo de botones, se omite por completo la IU de divulgación.](https://developers-dot-devsite-v2-prod.appspot.com/static/privacy-sandbox/assets/images/blog/fedcm-126-without-disclosure-widget.jpg?authuser=6&hl=es)
Esto ocurre incluso si la respuesta del extremo de las cuentas no contiene un ID de cliente que coincida con el RP en approved_clients
.
En este caso, el disclosure_text_shown
enviado al extremo de aserción de ID es
falso en el cuerpo 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
Varias configURL
Varias configURLs permiten que los IdP admitan varios archivos de configuración para un IdP. Para ello, especifica accounts_endpoint
y login_url
en el archivo conocido, al igual que en los archivos de configuración.
Si se agregan accounts_endpoint
y login_url
al archivo conocido, los provider_urls
se ignoran para que el IdP pueda admitir varios archivos de configuración.
Si no es así, provider_urls
seguirá funcionando para que sea retrocompatible.
El archivo conocido que admite varias configURL puede verse de la siguiente manera:
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Esto nos permite lo siguiente:
- Mantener la compatibilidad con versiones anteriores y posteriores con archivos conocidos existentes y la versión anterior de los navegadores que ya se implementaron de forma interna.
- Tener una cantidad arbitraria de archivos de configuración, siempre que todos apunten a los mismos
accounts_endpoint
ylogin_url
- No tienes la oportunidad de que la entropía se agregue a la solicitud de recuperación con credenciales realizada al
accounts_endpoint
, ya que debe especificarse en el nivel "well-known".
La compatibilidad con varias configURLs es opcional, y las implementaciones de FedCM existentes pueden permanecer iguales.
Etiquetas personalizadas de la cuenta
Las etiquetas de cuenta personalizadas permiten que los IdP de FedCM anoten las cuentas para que los RP puedan filtrarlas especificando la etiqueta en un archivo de configuración. Se pueden filtrar de manera similar si se usan la API de Domain Hint y la API de Hint de acceso si se los especifica en la llamada a navigator.credentials.get()
, pero las etiquetas personalizadas de la cuenta pueden filtrar a los usuarios si especifican el archivo de configuración, lo que es especialmente útil cuando se usan varias configURLs. Las etiquetas de cuenta personalizadas también son diferentes en el sentido de que se proporcionan desde el servidor de IdP, a diferencia de la RP, como sugerencias de acceso o dominio.
Ejemplo
Un IdP admite dos configURLs para consumidores y empresas, respectivamente. El archivo de configuración del consumidor tiene una etiqueta 'consumer'
, y el archivo de configuración empresarial tiene una etiqueta 'enterprise'
.
Con esta configuración, el archivo conocido incluye accounts_endpoint
y login_url
para permitir varias configURL.
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Cuando se proporciona accounts_endpoint
en el archivo conocido, provider_urls
se ignora. La RP puede apuntar directamente a los archivos de configuración respectivos en la llamada a navigator.credentials.get()
.
El archivo de configuración del consumidor está en https://idp.example/fedcm.json
, que incluye la propiedad accounts
que especifica 'consumer'
mediante 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"
}
}
El archivo de configuración de la empresa se encuentra en https://idp.example/enterprise/fedcm.json
, que incluye la propiedad accounts
que especifica 'enterprise'
mediante 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"
}
}
El extremo de cuentas común del IdP (en este ejemplo, https://idp.example/accounts
) muestra una lista de cuentas que incluye una propiedad de etiquetas con labels
asignado en un array para cada cuenta.
La siguiente es una respuesta de ejemplo para un usuario que tiene dos cuentas. Uno es para consumidores y el otro es para empresas:
{
"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"]
}]
}
Cuando un RP quiere permitir que los usuarios de 'enterprise'
accedan, pueden especificar la configURL 'enterprise'
'https://idp.example/enterprise/fedcm.json'
en la llamada navigator.credentials.get()
:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
nonce: '234234',
configURL: 'https://idp.example/enterprise/fedcm.json',
},
}
});
Como resultado, solo el ID de la cuenta de '4567'
está disponible para que el usuario acceda. El navegador oculta el ID de la cuenta de '123'
de forma silenciosa para que el usuario no reciba una cuenta que no sea compatible con el IdP en este sitio.
Prueba de origen: FedCM como indicador de confianza para la API de Storage Access
Chrome 126 está iniciando una prueba de origen de FedCM como indicador de confianza para la API de acceso al almacenamiento. Con este cambio, un otorgamiento de permiso previo a través de FedCM se convierte en un motivo válido para aprobar automáticamente una solicitud de acceso al almacenamiento por parte de las APIs de acceso a almacenamiento.
Esto es útil cuando un iframe incorporado quiere acceder a recursos personalizados; por ejemplo, si idp.example está incorporado en rp.example y necesita mostrar un recurso personalizado. Si el navegador restringe el acceso a cookies de terceros, incluso si el usuario accedió a rp.example mediante idp.example con FedCM, el iframe idp.example incorporado no podrá solicitar recursos personalizados porque las solicitudes no incluirán cookies de terceros.
Para lograrlo, idp.example necesita obtener un permiso de acceso al almacenamiento a través de su iframe incorporado en el sitio web, y esto solo se puede obtener mediante un mensaje de permiso.
Con FedCM como un indicador de confianza para la API de Storage Access, las verificaciones de permisos de la API de Storage Access no solo aceptan el otorgamiento de permisos otorgado por una solicitud de acceso al almacenamiento, sino también el otorgamiento de permisos otorgado por un mensaje de 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();
Una vez que el usuario accede con FedCM, el permiso se otorga de forma automática siempre que la autenticación de FedCM esté activa. Esto significa que, cuando el usuario se desconecte, se mostrará un mensaje en la solicitud de permiso.
Participar en la prueba de origen
Puedes probar el paquete de la API de Continuation de FedCM de manera local activando una marca de Chrome
chrome://flags#fedcm-authz
en Chrome 126 o versiones posteriores. También puedes probar el FedCM como un indicador de confianza para la API de Storage Access de forma local. Para ello, activa #fedcm-with-storage-access-api
en Chrome 126 o una versión posterior.
Estas funciones también están disponibles como pruebas de origen. Las pruebas de origen te permiten probar funciones nuevas y proporcionar comentarios sobre su usabilidad, practicidad y eficacia. Para obtener más información, consulta Comienza a usar las pruebas de origen.
Para probar la prueba de origen del paquete de la API de Continuation de FedCM, crea dos tokens de prueba de origen:
- Regístrate para la prueba. Incorpora el token en el origen del IdP.
- Regístrate en la prueba de origen con la casilla de verificación correspondiente a terceros marcada. Sigue las instrucciones que se indican en Cómo registrar una prueba de origen de terceros para la RP para incorporar el token en ella.
Si quieres habilitar la API de Continuation junto con el flujo de botones, habilita también la prueba de origen de la API de Button Mode:
- Regístrate en la prueba de origen como un tercero. Sigue las instrucciones que aparecen en Registra una prueba de origen de terceros para la RP para incorporar el token de la RP.
A fin de probar el FedCM como indicador de confianza para la prueba de origen de la API de Storage Access, haz lo siguiente:
- Regístrate en la prueba de origen. Incorpora el token en el origen del IdP.
La prueba de origen del paquete de la API de Continuation y el FedCM como indicador de confianza para la prueba de origen de la API de Storage Access están disponibles a partir de la versión 126 de Chrome.
Registra una prueba de origen de terceros para el RP
- Ve a la página de registro de la prueba de origen.
- Haz clic en el botón Register y completa el formulario para solicitar un token.
- Ingresa el origen del IdP como Web Origin.
- Verifica la coincidencia con terceros para insertar el token con JavaScript en otros orígenes.
- Haz clic en Enviar.
- Incorpora el token emitido en el sitio web de un tercero.
Para incorporar el token en un sitio web de terceros, agrega el siguiente código a la biblioteca de JavaScript o al SDK del IdP que se entrega desde el origen del IdP.
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
Reemplaza TOKEN_GOES_HERE
por tu propio token.