No Chrome 126, os desenvolvedores podem começar a executar um teste de origem para um pacote de recursos da API Federated Credential Management (FedCM) para computadores que permitem alguns casos de uso de autorização. O pacote consiste na API Continuation e na API Parameters, que permitem uma experiência semelhante a um fluxo de autorização OAuth, envolvendo uma caixa de diálogo de permissão fornecida pelo provedor de identidade (IdP). O pacote também inclui outras alterações, como a API Fields, vários configURLs e rótulos de conta personalizados. No Chrome 126, também estamos lançando um teste de origem para a API Storage Access (SAA), que concede automaticamente solicitações de SAA se o usuário já tiver feito login usando o FedCM no passado.
Teste de origem: pacote da API FedCM Continuation
O pacote da API de continuação do FedCM consiste em várias extensões do FedCM:
API de continuação
Confira uma demonstração da API no Glitch.
A API de continuação permite que o endpoint de declaração de ID do IdP retorne, opcionalmente, um URL que o FedCM vai renderizar para permitir que o usuário continue um fluxo de login de várias etapas. Isso permite que o IdP solicite que o usuário conceda à parte confiável (RP) permissões além do que é possível na interface do FedCM atual, como acesso aos recursos do lado do servidor do usuário.
Normalmente, o endpoint de declaração de ID retorna um token necessário para autenticação.
{
"token": "***********"
}
No entanto, com a API de continuação, o endpoint de declaração
de ID pode
retornar uma propriedade continue_on
que inclui um caminho absoluto ou
relativo para o endpoint de declaração 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=..."
}
Assim que o navegador recebe a resposta continue_on
, uma nova janela pop-up
é aberta e direciona o usuário para o caminho especificado.
Depois que o usuário interage com a página, por exemplo, concedendo mais permissão
para compartilhar informações extras com a RP, a página do IdP pode chamar
IdentityProvider.resolve()
para resolver a chamada navigator.credentials.get()
original
e retornar um token como um 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);
});
Em seguida, o navegador fechará o pop-up e retornará o token para o autor da chamada de API.
Se o usuário rejeitar a solicitação, você poderá fechar a janela chamando
IdentityProvider.close()
.
IdentityProvider.close();
Se, por algum motivo, o usuário tiver mudado a conta no pop-up (por exemplo, o IdP oferece uma função "alternar usuário" ou, em casos de delegação), a chamada de resolução usará um segundo argumento opcional que permite algo como:
IdentityProvider.resolve(token, {accountId: '1234');
API Parameters
A API Parameters permite que a RP forneça outros parâmetros ao endpoint de declaração de ID. Com a API Parameters, as RPs podem transmitir outros parâmetros ao IdP para solicitar permissões para recursos além do login básico. O usuário autorizaria essas permissões usando um fluxo de UX controlado pelo IdP que é iniciado pela API de continuação.
Para usar a API, adicione parâmetros à propriedade params
como um objeto na chamada 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',
}
},
}
});
Os nomes de propriedades no objeto params
são prefixados com param_
. No
exemplo acima, a propriedade params contém IDP_SPECIFIC_PARAM
como '1'
, foo
como 'BAR'
, ETC
como 'MOAR'
e scope
como 'calendar.readonly photos.write'
.
Isso será traduzido como param_IDP_SPECIFIC_PARAM=1¶m_foo=BAR¶m_ETC=MOAR¶m_scope=calendar.readonly%20photos.write
no corpo HTTP da solicitação:
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
Receber permissões dinamicamente
Em geral, para os usuários, é mais útil solicitar permissões quando elas são necessárias, e não quando o desenvolvedor acha que é mais fácil de implementar. Por exemplo, é preferível pedir permissão para acessar uma câmera quando o usuário está prestes a tirar uma foto do que pedir permissão assim que o usuário acessa o site. A mesma prática se aplica aos recursos do servidor. Solicite permissões apenas quando elas forem necessárias para o usuário. Isso é chamado de "autorização dinâmica".
Para solicitar autorização dinamicamente com o FedCM, o IdP pode:
- Chame
navigator.credentials.get()
com os parâmetros obrigatórios que o IdP possa entender, comoscope
. - O endpoint de
declaração de ID
confirma que o usuário já está conectado e responde com um URL
continue_on
. - O navegador abre uma janela pop-up com a página de permissões do IdP solicitando outra permissão que corresponda aos escopos solicitados.
- Depois de autorizado por
IdentityProvider.resolve()
pelo IdP, a janela é fechada e a chamadanavigator.credentials.get()
original da RP recebe um token relevante ou um código de autorização para que a RP possa trocá-lo por um token de acesso adequado.
API Fields
A API Fields permite que a RP declare atributos de conta a serem solicitados ao IdP para que o navegador possa renderizar uma interface de divulgação adequada na caixa de diálogo do FedCM. É responsabilidade do IdP incluir os campos solicitados no token retornado. Considere isso solicitando um "perfil básico" no OpenID Connect em vez de "escopos" no OAuth.
![Mensagem de divulgação no modo de widget.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-126-with-disclosure-widget.jpg?authuser=6&hl=pt)
![Mensagem de divulgação no modo de botão.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-126-with-disclosure-button.jpg?authuser=6&hl=pt)
Para usar a API Fields, adicione parâmetros à propriedade fields
como uma matriz na chamada navigator.credentials.get()
. Os campos podem conter 'name'
, 'email'
e 'picture'
por enquanto, mas podem ser expandidos para incluir mais valores no futuro.
Uma solicitação com fields
ficaria assim:
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',
});
A solicitação HTTP para o endpoint de declaração de
ID
inclui o parâmetro fields
especificado pela RP, com o parâmetro disclosure_text_shown
definido como true
se esse não for um usuário recorrente, e os campos que o
navegador divulgou ao usuário em um 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
Se a RP precisar acessar outros dados do IdP, como acesso a uma
agenda, isso precisará ser processado com um parâmetro personalizado, conforme mencionado acima. O IdP retorna um URL continue_on
para solicitar a permissão.
Se fields
for uma matriz vazia, a solicitação será assim:
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',
});
Se fields
for uma matriz vazia, o user agent vai pular a interface de divulgação.
![A mensagem de divulgação não é exibida no modo de widget. No fluxo do botão, a interface de divulgação é totalmente ignorada.](https://developers.google.cn/static/privacy-sandbox/assets/images/blog/fedcm-126-without-disclosure-widget.jpg?authuser=6&hl=pt)
Isso ocorre mesmo que a resposta do endpoint
das contas
não contenha um ID do cliente que corresponda à RP em approved_clients
.
Nesse caso, o disclosure_text_shown
enviado ao endpoint de declaração de
ID é
falso no corpo do 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
Vários configURLs
Vários configURLs permitem que os IdPs
acomodem vários arquivos de configuração para um IdP, especificando
accounts_endpoint
e login_url
no arquivo
conhecido da mesma forma
que nos arquivos de configuração.
Se accounts_endpoint
e login_url
forem adicionados ao arquivo conhecido, os
provider_urls
serão ignorados para que o IdP seja compatível com vários arquivos de configuração.
Se não forem, provider_urls
vão continuar em vigor para oferecer compatibilidade
com versões anteriores.
O arquivo mais conhecido compatível com vários configURLs pode ter esta aparência:
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Com isso, podemos:
- Manter a compatibilidade com versões anteriores e posteriores com arquivos conhecidos existentes e com a versão anterior de navegadores que já estão implantados.
- Ter um número arbitrário de arquivos de configuração, desde que todos apontem para os
mesmos
accounts_endpoint
elogin_url
. - Não há oportunidade de a entropia ser adicionada à solicitação de busca
credenciada feita ao
accounts_endpoint
, já que ela precisa ser especificada no nível "conhecido".
A compatibilidade com vários configURLs é opcional, e as implementações do FedCM podem permanecer as mesmas.
Rótulos de conta personalizados
Os rótulos de conta personalizados permitem que os IdPs do FedCM anotem contas para que os RPs possam filtrá-las especificando o rótulo em um arquivo de configuração. É possível aplicar filtros semelhantes na API
Domain Hint e na API
Login Hint especificando-os
na chamada navigator.credentials.get()
, mas os rótulos de conta personalizados
podem filtrar usuários especificando o arquivo de configuração, o que é especialmente útil quando
vários configURLs são usados. Os rótulos de conta personalizados também
são diferentes porque são fornecidos pelo servidor do IdP, e não pela
RP, como dicas de login ou domínio.
Exemplo
Um IdP é compatível com dois configURLs para consumidor e empresarial, respectivamente. O
arquivo de configuração do consumidor tem um rótulo 'consumer'
e o arquivo de configuração empresarial
tem um rótulo 'enterprise'
.
Com essa configuração, o arquivo conhecido inclui accounts_endpoint
e
login_url
para permitir vários configURLs.
{
"provider_urls": [ "https://idp.example/fedcm.json" ],
"accounts_endpoint": "https://idp.example/accounts",
"login_url": "https://idp.example/login"
}
Quando o accounts_endpoint
é fornecido no arquivo conhecido, os
provider_urls
são ignorados. A RP pode apontar diretamente para os respectivos arquivos
de configuração na chamada navigator.credentials.get()
.
O arquivo de configuração do consumidor está em https://idp.example/fedcm.json
, que inclui a propriedade accounts
que especifica 'consumer'
usando o 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"
}
}
O arquivo de configuração da empresa está em https://idp.example/enterprise/fedcm.json
,
que inclui a propriedade accounts
que especifica 'enterprise'
usando o
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"
}
}
O endpoint de contas
do IdP (neste exemplo, https://idp.example/accounts
)
retorna uma lista de contas que
inclui uma propriedade de rótulos com labels
atribuído em uma matriz para cada conta.
Veja a seguir um exemplo de resposta para um usuário que tem duas contas. Uma é para
consumidores e a outra é 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"]
}]
}
Quando uma parte restrita quer permitir que usuários de 'enterprise'
façam login, ele pode especificar o
configURL 'enterprise'
'https://idp.example/enterprise/fedcm.json'
na
chamada navigator.credentials.get()
:
let { token } = await navigator.credentials.get({
identity: {
providers: [{
clientId: '1234',
nonce: '234234',
configURL: 'https://idp.example/enterprise/fedcm.json',
},
}
});
Como resultado, apenas o ID da conta de '4567'
está disponível para o usuário
fazer login. O ID da conta de '123'
é ocultado silenciosamente pelo navegador para que o usuário
não receba uma conta sem suporte do IdP neste site.
Teste de origem: FedCM como um sinal de confiança para a API Storage Access
O Chrome 126 está iniciando um teste de origem do FedCM como um sinal de confiança para a API Storage Access. Com essa mudança, uma concessão de permissão anterior via FedCM se torna um motivo válido para aprovar automaticamente uma solicitação de acesso ao armazenamento pelas APIs Storage Access.
Isso é útil quando um iframe incorporado quer acessar recursos personalizados: por exemplo, se idp.example estiver incorporado em rp.example e precisar mostrar um recurso personalizado. Se o navegador restringir o acesso a cookies de terceiros, mesmo que o usuário faça login em rp.example usando idp.example com o FedCM, o iframe incorporado idp.example não poderá solicitar recursos personalizados porque as solicitações não incluirão cookies de terceiros.
Para isso, idp.example precisa de uma permissão de acesso ao armazenamento pelo iframe incorporado no site, e isso só pode ser conseguido com um solicitação de permissão.
Com o FedCM como um sinal de confiança para a API Storage Access, as verificações de permissão dessa API não apenas aceitam a concessão de permissão concedida por uma solicitação de acesso ao armazenamento, mas também a permissão concedida por uma solicitação do 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();
Depois que o usuário fizer login com o FedCM, a permissão será concedida automaticamente, desde que a autenticação do FedCM esteja ativa. Isso significa que, quando o usuário estiver desconectado, uma solicitação de permissão será exibida.
Participar do teste de origem
Você pode testar o pacote da API FedCM Continuation localmente ativando uma sinalização
do Chrome
chrome://flags#fedcm-authz
no Chrome 126 ou mais recente. Você também pode testar o FedCM
como um sinal de confiança para a API Storage Access localmente ativando
#fedcm-with-storage-access-api
no Chrome 126 ou mais recente.
Esses recursos também estão disponíveis como testes de origem. Os testes de origem permitem que você teste novos recursos e dê feedback sobre usabilidade, praticidade e eficácia. Para mais informações, confira Introdução aos testes de origem.
Para testar o teste de origem do pacote da API FedCM Continuation, crie dois tokens de teste de origem:
- Inscreva-se no teste. Incorpore o token à origem do IdP.
- Inscreva-se no teste de origem com a caixa de seleção de terceiros correspondente marcada. Siga as instruções em Registrar um teste de origem de terceiros para a RP para incorporar o token da RP.
Se você tiver interesse em ativar a API de continuação com o fluxo de botões, ative também o teste de origem da API de modo botão (link em inglês):
- Inscreva-se no teste de origem como um terceiro. Siga as instruções em Registrar um teste de origem de terceiros para a RP para incorporar o token à RP.
Para testar o FedCM como um sinal de confiança para o teste de origem da API Storage Access:
- Inscreva-se no teste de origem. Incorpore o token à origem do IdP.
O teste de origem do pacote da API de continuação e o FedCM como sinal de confiança para o teste de origem da API Storage Access estão disponíveis no Chrome 126.
Registrar um teste de origem de terceiros para a parte restrita
- Acesse a página de registro do teste de origem.
- Clique no botão Registrar e preencha o formulário para solicitar um token.
- Digite a origem do IdP como Web Origin.
- Verificar a correspondência de terceiros para injetar o token com JavaScript em outras origens.
- Clique em Enviar.
- Incorporar o token emitido em um site de terceiros.
Para incorporar o token em um site de terceiros, adicione o código a seguir à biblioteca JavaScript do IdP ou ao SDK disponibilizado pela origem do IdP.
const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);
Substitua TOKEN_GOES_HERE
pelo seu próprio token.