Implementar uma solução de identidade com o FedCM no provedor de identidade

A implementação da FedCM inclui várias etapas principais para o provedor de identidade (IdP) e a parte confiável (RP). Consulte a documentação para saber como implementar o FedCM no lado do RP.

Os IdPs precisam concluir as etapas a seguir para implementar a FedCM:

Criar um arquivo conhecido

Para evitar que rastreadores abusem da API, um arquivo conhecido precisa ser veiculado de /.well-known/web-identity do eTLD+1 do IdP.

O arquivo conhecido pode incluir as seguintes propriedades:

Propriedade Obrigatório Descrição
provider_urls obrigatório Matriz de caminhos de arquivos de configuração do IdP. Ignorado (mas ainda obrigatório) se accounts_endpoint e login_url forem especificados.
accounts_endpoint recomendado, requer login_url
URL do endpoint de contas. Isso permite o suporte a várias configurações, desde que cada arquivo de configuração use o mesmo URL login_url e accounts_endpoint.

Observação: o parâmetro é compatível com o Chrome 132 e versões mais recentes.
login_url recomendado, requer accounts_endpoint O URL da página de login para o usuário fazer login no IdP. Isso permite o suporte a várias configurações, desde que cada arquivo de configuração use o mesmo login_url e accounts_endpoint.

Observação: o parâmetro é compatível com o Chrome 132 e versões mais recentes.

Por exemplo, se os endpoints do IdP forem veiculados em https://accounts.idp.example/, eles também precisarão veicular um arquivo conhecido em https://idp.example/.well-known/web-identity, além de um arquivo de configuração do IdP. Confira um exemplo de conteúdo de arquivo conhecido:

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

Os IdPs podem acomodar vários arquivos de configuração para um IdP especificando accounts_endpoint e login_url no arquivo conhecido. Esse recurso pode ser útil nos seguintes casos:

  • Um IdP precisa oferecer suporte a várias configurações de teste e produção diferentes.
  • Um IdP precisa oferecer suporte a diferentes configurações por região (por exemplo, eu-idp.example e us-idp.example).

Para oferecer suporte a várias configurações (por exemplo, para diferenciar entre ambientes de teste e de produção), o IdP precisa especificar accounts_endpoint e 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"
  }

Criar um arquivo de configuração e endpoints do IdP

O arquivo de configuração do IdP fornece uma lista de endpoints necessários para o navegador. Os IdPs precisam hospedar um ou vários arquivos de configuração, além dos endpoints e URLs necessários. Todas as respostas JSON precisam ser veiculadas com o tipo de conteúdo application/json.

O URL do arquivo de configuração é determinado pelos valores fornecidos à chamada navigator.credentials.get() executada em um RP. O RP vai transmitir o URL do arquivo de configuração para cada provedor de identidade:

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

O navegador vai buscar o arquivo de configuração com uma solicitação GET sem o cabeçalho Origin ou Referer. A solicitação não tem cookies e não segue redirecionamentos. Isso impede que o IdP saiba quem fez a solicitação e qual RP está tentando se conectar. Exemplo:

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

O IdP precisa implementar um endpoint de configuração que responda com um JSON. O JSON inclui as seguintes propriedades:

Propriedade Descrição
accounts_endpoint (obrigatório) URL do endpoint de contas.
account_label (opcional) String de rótulo da conta personalizada, determinando quais contas serão retornadas quando este arquivo de configuração for usado. Por exemplo: "account_label": "developer".
Um IdP pode implementar a rotulagem personalizada de contas da seguinte maneira:

Por exemplo, um IdP implementa um arquivo de configuração "https://idp.example/developer-config.json" com "account_label": "developer" especificado. O IdP também marca algumas contas com o rótulo "developer" usando o parâmetro label_hints no endpoint "accounts". Quando um RP chama navigator.credentials.get() com o arquivo de configuração "https://idp.example/developer-config.json" especificado, somente as contas com o rótulo "developer" são retornadas.

Observação: os rótulos personalizados da conta são compatíveis com o Chrome 132 e versões mais recentes.
supports_use_other_account (opcional) Booleano que especifica se o usuário pode fazer login com uma conta diferente daquela com que está conectado no momento (se o IdP aceitar várias contas). Isso se aplica apenas ao modo ativo.
client_metadata_endpoint (opcional) URL do endpoint de metadados do cliente.
id_assertion_endpoint (obrigatório) URL do endpoint de declaração de ID.
disconnect (opcional) URL do endpoint de desconexão.
login_url (obrigatório) O URL da página de login para o usuário fazer login no IdP.
branding (opcional) Objeto que contém várias opções de branding.
branding.background_color (opcional) Opção de branding que define a cor de plano de fundo do botão "Continuar como...". Use a sintaxe CSS relevante, ou seja, hex-color, hsl(), rgb() ou named-color.
branding.color (opcional) Opção de branding que define a cor do texto do botão "Continuar como...". Use a sintaxe CSS relevante, ou seja, hex-color, hsl(), rgb() ou named-color.
branding.icons (opcional) Matriz de objetos de ícone. Esses ícones são exibidos na caixa de diálogo de login. O objeto de ícone tem dois parâmetros:
  • url (obrigatório): URL da imagem do ícone. Isso não é compatível com imagens SVG.
  • size (opcional): dimensões do ícone, que o aplicativo considera como quadradas e de resolução única. Esse número precisa ser maior ou igual a 25 px no modo passivo e maior ou igual a 40 px no modo ativo.

Confira um exemplo de corpo de resposta do 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
      }]
    }
  }

Depois que o navegador busca o arquivo de configuração, ele envia solicitações subsequentes para os endpoints do IdP:

Endpoints do IdP
Endpoints do IdP

Usar outra conta

Os usuários podem mudar para uma conta diferente daquela em que estão conectados se o IdP aceitar várias contas ou a substituição da conta atual.

Para permitir que o usuário escolha outras contas, o IdP precisa especificar esse recurso no arquivo de configuração:

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

Endpoint "Accounts"

O endpoint de contas do IdP retorna uma lista de contas em que o usuário está conectado no IdP. Se o IdP aceitar várias contas, esse endpoint vai retornar todas as contas conectadas.

O navegador envia uma solicitação GET com cookies com SameSite=None, mas sem um parâmetro client_id, o cabeçalho Origin ou o cabeçalho Referer. Isso impede que o IdP saiba a RP em que o usuário está tentando fazer login. Exemplo:

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

Ao receber a solicitação, o servidor precisa:

  1. Verifique se a solicitação contém um cabeçalho HTTP Sec-Fetch-Dest: webidentity.
  2. Corresponda os cookies de sessão aos IDs das contas já conectadas.
  3. Responda com a lista de contas.

O navegador espera uma resposta JSON que inclua uma propriedade accounts com uma matriz de informações da conta com as seguintes propriedades:

Propriedade Descrição
id (obrigatório) ID exclusivo do usuário.
name Nome completo do usuário de acordo com a localidade e as preferências.

Observação: a partir do Chrome 141, pelo menos um dos parâmetros name, email, username ou tel é obrigatório. Em versões anteriores do Chrome, name e email são obrigatórios.
username Um nome de usuário escolhido pelo usuário.

Observação: a partir do Chrome 141, pelo menos um dos parâmetros name, email, username ou tel é obrigatório.
email Endereço de e-mail do usuário.

Observação: a partir do Chrome 141, pelo menos um dos parâmetros name, email, username ou tel é obrigatório. Em versões anteriores do Chrome, name e email são obrigatórios.
tel Número de telefone do usuário.

Observação: a partir do Chrome 141, pelo menos um dos parâmetros name, email, username ou tel é obrigatório.
picture (opcional) URL da imagem do avatar do usuário.
given_name (opcional) Nome do usuário.
approved_clients (opcional) Uma matriz de IDs de cliente do RP com que o usuário se registrou.
login_hints (opcional) Uma matriz de todos os tipos de filtro possíveis que o IdP aceita para especificar uma conta. O RP pode invocar navigator.credentials.get() com a propriedade loginHint para mostrar seletivamente a conta especificada.
domain_hints (opcional) Uma matriz com todos os domínios associados à conta. O RP pode chamar navigator.credentials.get() com uma propriedade domainHint para filtrar as contas.
label_hints (opcional) Matriz de strings de rótulos personalizados da conta a que uma conta está associada.
Um IdP pode implementar a rotulagem personalizada de contas da seguinte maneira:
  • Especifique os rótulos da conta no endpoint "accounts" (usando este parâmetro label_hints).
  • Crie um arquivo de configuração para cada rótulo específico.

Por exemplo, um IdP implementa um arquivo de configuração https://idp.example/developer-config.json com "account_label": "developer" especificado. O IdP também marca algumas contas com o rótulo "developer" usando o parâmetro label_hints no endpoint de contas . Quando um RP chama navigator.credentials.get() com um arquivo de configuração https://idp.example/developer-config.json especificado, somente as contas com o rótulo "developer" são retornadas.

Os rótulos personalizados da conta são diferentes da dica de login e da dica de domínio porque são totalmente mantidos pelo servidor do IdP, e o RP especifica apenas o arquivo de configuração a ser usado.

Observação: os rótulos personalizados da conta são compatíveis com o Chrome 132 e versões mais recentes.

Exemplo de corpo da resposta:

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

Se o usuário não estiver conectado, responda com HTTP 401 (Não autorizado).

A lista de contas retornadas é consumida pelo navegador e não fica disponível para o RP.

Endpoint de declaração de ID

O endpoint de declaração de ID do IdP retorna uma declaração para o usuário conectado. Quando o usuário faz login em um site de RP usando a chamada navigator.credentials.get(), o navegador envia uma solicitação POST com cookies com SameSite=None e um tipo de conteúdo de application/x-www-form-urlencoded para esse endpoint com as seguintes informações:

Propriedade Descrição
client_id (obrigatório) O identificador do cliente do RP.
account_id (obrigatório) O ID exclusivo do usuário que está fazendo login.
disclosure_text_shown Resulta em uma string de "true" ou "false" (em vez de um booleano). O resultado é "false" nestes casos:
  • Se o texto de divulgação não foi mostrado porque o ID do cliente do RP foi incluído na lista de propriedades approved_clients da resposta do endpoint de contas.
  • Se o texto da declaração não foi mostrado porque o navegador observou um momento de inscrição no passado sem approved_clients.
  • Se o parâmetro fields não incluir todos os três campos ("name", "email" e "picture"), por exemplo, fields=[ ] ou fields=['name', 'picture']. Isso é necessário para compatibilidade com versões anteriores de implementações mais antigas.

    Observação: a partir do Chrome 141, o texto de divulgação pode ser mostrado mesmo que o valor disclosure_text_shown seja "false". Para verificar se o texto da declaração foi exibido, confira o valor disclosure_shown_for.
disclosure_shown_for Lista os campos que o navegador mostrou ao usuário no texto de divulgação para informar quais dados o RP está solicitando do IdP.
is_auto_selected Se a reautenticação automática for realizada no RP, is_auto_selected indicará "true". Caso contrário, "false". Isso é útil para oferecer suporte a mais recursos relacionados à segurança. Por exemplo, alguns usuários podem preferir um nível de segurança mais alto que exija mediação explícita do usuário na autenticação. Se um IdP receber uma solicitação de token sem essa mediação, ele poderá processar a solicitação de maneira diferente. Por exemplo, retorne um código de erro para que o RP possa chamar a API FedCM novamente com mediation: required.
fields (opcional) Matriz de strings que especifica as informações do usuário que o RP solicitou ao IdP para compartilhar. Os seguintes campos podem ser especificados opcionalmente:
  • "name"
  • "username"
  • "email"
  • "tel"
  • "picture"
O navegador vai enviar fields, disclosure_text_shown e disclosure_shown_for listando os campos especificados na solicitação POST, como no exemplo a seguir.

Observação: a API Fields é compatível com o Chrome 132 e versões mais recentes. Os campos"username" e"tel" são compatíveis com o Chrome 141.
params (opcional) Qualquer objeto JSON válido que permita especificar outros parâmetros personalizados de chave-valor, por exemplo:
  • scope: um valor de string que contém outras permissões que o RP precisa solicitar, por exemplo, "drive.readonly calendar.readonly"
  • nonce: uma string aleatória fornecida pelo RP para garantir que a resposta seja emitida para essa solicitação específica. Evita ataques de repetição.
  • Outros parâmetros personalizados de chave-valor.
Quando o navegador envia uma solicitação POST, o valor params é serializado em JSON e depois codificado em porcentagem.

Observação: a API Parameters é compatível com o Chrome 132 e versões mais recentes.

Exemplo de cabeçalho 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

Ao receber a solicitação, o servidor precisa:

  1. Responda à solicitação com CORS (compartilhamento de recursos entre origens).
  2. Verifique se a solicitação contém um cabeçalho HTTP Sec-Fetch-Dest: webidentity.
  3. Faça a correspondência do cabeçalho Origin com a origem do RP determinada pelo client_id. Rejeite se não corresponderem.
  4. Compare account_id com o ID da conta já conectada. Rejeite se não corresponderem.
  5. Responda com um token. Se a solicitação for rejeitada, responda com uma resposta de erro.

O IdP pode decidir como emitir o token. Em geral, ele é assinado com informações como ID da conta, ID do cliente, origem do emissor e nonce, para que a RP possa verificar se o token é genuíno.

O navegador espera uma resposta JSON que inclua a seguinte propriedade:

Propriedade Descrição
token Um token é uma string que contém declarações sobre a autenticação.
continue_on URL de redirecionamento que permite um fluxo de login de várias etapas.

O token retornado é transmitido ao RP pelo navegador para que ele possa validar a autenticação.

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

Continuar no recurso

O IdP pode fornecer um URL de redirecionamento na resposta do endpoint de declaração de ID para ativar um fluxo de login de várias etapas. Isso é útil quando o IdP precisa solicitar mais informações ou permissões, por exemplo:

  • Permissão para acessar os recursos do lado do servidor do usuário.
  • Verificação de que os dados de contato estão atualizados.
  • Controles da família.

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 popup window:
    "continue_on": "https://idp.example/continue_on_url"
  }

Se a resposta contiver o parâmetro continue_on, uma nova janela pop-up será aberta e vai navegar o usuário até o caminho especificado. Depois da interação do usuário com a página continue_on, o IdP precisa chamar IdentityProvider.resolve() com o token transmitido como um argumento para que a promessa da chamada navigator.credentials.get() original possa ser resolvida:

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

Em seguida, o navegador fecha automaticamente o pop-up e retorna o token para o autor da chamada da API. Uma chamada IdentityProvider.resolve() única é a única maneira de a janela principal (RP) e a janela pop-up (IdP) se comunicarem.
Se o usuário rejeitar a solicitação, o IdP poderá fechar a janela chamando IdentityProvider.close().

  IdentityProvider.close();

A API Continuation exige interação explícita do usuário (cliques) para funcionar. Confira como a API Continuation funciona com diferentes modos de mediação:

  • No modo passive:
    • mediation: 'optional' (padrão): a API Continuation só funciona com um gesto do usuário, como clicar em um botão na página ou na interface da FedCM. Quando a nova autenticação automática é acionada sem um gesto do usuário, nenhuma janela pop-up é aberta, e a promessa é rejeitada.
    • mediation: 'required': sempre pede que o usuário interaja, então a API Continuation sempre funciona.
  • No modo ativo:
    • A ativação do usuário é sempre necessária. A API Continuation é sempre compatível.

Se, por algum motivo, o usuário tiver mudado de conta no pop-up (por exemplo, o IdP oferece uma função "usar outra conta" ou em casos de delegação), a chamada de resolução vai usar um segundo argumento opcional, permitindo algo como:

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

Retornar uma resposta de erro

O id_assertion_endpoint também pode retornar uma resposta de "erro" com dois campos opcionais:

  • code: o IdP pode escolher um dos erros conhecidos na lista de erros especificados do OAuth 2.0 (invalid_request, unauthorized_client, access_denied, server_error e temporarily_unavailable) ou usar qualquer string arbitrária. Se for o último caso, o Chrome vai renderizar a interface de erro com uma mensagem genérica e transmitir o código ao RP.
  • url: identifica uma página da Web legível com informações sobre o erro para fornecer mais detalhes aos usuários. Esse campo é útil para os usuários porque os navegadores não podem fornecer mensagens de erro avançadas em uma interface integrada. Por exemplo: links para as próximas etapas ou informações de contato do atendimento ao cliente. Se um usuário quiser saber mais sobre os detalhes do erro e como corrigir o problema, ele pode acessar a página fornecida na interface do navegador para mais detalhes. O URL precisa ser do mesmo site que o IdP configURL.
  // id_assertion_endpoint response
  {
    "error" : {
      "code": "access_denied",
      "url" : "https://idp.example/error?type=access_denied"
    }
  }

Rótulos personalizados da conta

Com os rótulos personalizados da conta, o IdP pode anotar contas de usuário com rótulos, e o RP pode optar por buscar apenas contas com rótulos específicos especificando o configURL para esse rótulo específico. Isso pode ser útil quando um RP precisa filtrar contas por critérios específicos, por exemplo, para mostrar apenas contas específicas de função, como "developer" ou "hr".

É possível fazer uma filtragem semelhante usando os recursos Dica de domínio e Dica de login, especificando-os na chamada navigator.credentials.get(). No entanto, os rótulos personalizados da conta podem filtrar usuários especificando o arquivo de configuração, o que é especialmente útil quando vários configURLs são usados. Os rótulos personalizados de conta também são diferentes porque são fornecidos pelo servidor do IdP, e não pelo RP, como dicas de login ou de domínio.

Considere um IdP que quer diferenciar entre contas "developer" e "hr". Para isso, o IdP precisa oferecer suporte a dois configURLs para "developer" e "hr", respectivamente:

  • O arquivo de configuração do desenvolvedor https://idp.example/developer/fedcm.json tem um rótulo "developer", e o arquivo de configuração empresarial https://idp.example/hr/fedcm.json tem um rótulo "hr", conforme mostrado abaixo:
  // 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"
  }
  • Com essa configuração, o arquivo well-known precisa incluir 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"
  }
  • O endpoint de contas comum do IdP (neste exemplo, https://idp.example/accounts) retorna uma lista de contas que inclui uma propriedade label_hints com rótulos atribuídos em uma matriz para cada conta:
  {
  "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"]
    }]
  }

Quando um RP quer permitir que usuários do "hr" façam login, ele pode especificar o configURL https://idp.example/hr/fedcm.json na chamada navigator.credentials.get():

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

Como resultado, apenas o ID da conta 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 que não é compatível com o IdP neste site.

Outras considerações:

  • Os rótulos são strings. Se a matriz label_hints ou o campo account_label usar um valor que não seja uma string, ele será ignorado.
  • Se nenhum rótulo for especificado no configURL, todas as contas serão mostradas no seletor de contas da FedCM.
  • Se nenhum rótulo for especificado para uma conta, ela só vai aparecer no seletor de contas se o configURL também não especificar um rótulo.
  • Se nenhuma conta corresponder ao rótulo solicitado no modo passivo (semelhante ao recurso de dica de domínio), a caixa de diálogo do FedCM vai mostrar uma solicitação de login, permitindo que o usuário faça login em uma conta do IdP. No modo ativo, a janela pop-up de login é aberta diretamente.

Desconectar endpoint

Ao invocar IdentityCredential.disconnect(), o navegador envia uma solicitação POST de origem cruzada com cookies com SameSite=None e um tipo de conteúdo application/x-www-form-urlencoded para esse endpoint de desconexão com as seguintes informações:

Propriedade Descrição
account_hint Uma dica para a conta do IdP.
client_id O identificador do cliente do 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

Ao receber a solicitação, o servidor precisa:

  1. Responda à solicitação com CORS (compartilhamento de recursos entre origens).
  2. Verifique se a solicitação contém um cabeçalho HTTP Sec-Fetch-Dest: webidentity.
  3. Faça a correspondência do cabeçalho Origin com a origem do RP determinada pelo client_id. Rejeite se não corresponderem.
  4. Compare account_hint com os IDs das contas já conectadas.
  5. Desconecte a conta de usuário do RP.
  6. Responda ao navegador com as informações da conta de usuário identificada em formato JSON.

Um exemplo de payload JSON de resposta é assim:

  {
    "account_id": "account456"
  }

Em vez disso, se o IdP quiser que o navegador desconecte todas as contas associadas ao RP, transmita uma string que não corresponda a nenhum ID de conta, por exemplo "*".

Endpoint de metadados do cliente

O endpoint de metadados do cliente do IdP retorna os metadados da parte confiante, como a política de privacidade, os Termos de Serviço e os ícones de logotipo da RP. Os RPs precisam fornecer links para a Política de Privacidade e os Termos de Serviço ao IdP com antecedência. Esses links são mostrados na caixa de diálogo de login quando o usuário ainda não se registrou no RP com o IdP.

O navegador envia uma solicitação GET usando o client_id navigator.credentials.get sem cookies. Exemplo:

  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

Ao receber a solicitação, o servidor precisa:

  1. Determine o RP para o client_id.
  2. Responda com os metadados do cliente.

As propriedades do endpoint de metadados do cliente incluem:

Propriedade Descrição
privacy_policy_url (opcional) URL da Política de Privacidade do RP.
terms_of_service_url (opcional) URL dos Termos de Serviço do RP.
icons (opcional) Matriz de objetos, como [{ "url": "https://rp.example/rp-icon.ico", "size": 40}]

O navegador espera uma resposta JSON do endpoint:

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

Os metadados do cliente retornados são consumidos pelo navegador e não ficam disponíveis para o RP.

URL de login

Esse endpoint é usado para permitir que o usuário faça login no IdP.

Com a API Login Status, o IdP precisa informar o status de login do usuário ao navegador. No entanto, o status pode estar dessincronizado, como quando a sessão expira. Nesse cenário, o navegador pode permitir dinamicamente que o usuário faça login no IdP usando o URL da página de login especificado com o login_url do arquivo de configuração do IdP.

A caixa de diálogo da FedCM mostra uma mensagem sugerindo um login, conforme mostrado na imagem a seguir.

Uma caixa de diálogo do FedCM sugerindo fazer login no IdP.
Uma caixa de diálogo da FedCM sugerindo fazer login no IdP.

Quando o usuário clica no botão Continuar, o navegador abre uma janela pop-up para a página de login do IdP.

Exemplo de caixa de diálogo do FedCM.
Exemplo de caixa de diálogo mostrada depois de clicar no botão de login no IdP.

A caixa de diálogo é uma janela normal do navegador com cookies primários. O que acontece na caixa de diálogo depende do IdP, e nenhum identificador de janela está disponível para fazer uma solicitação de comunicação entre origens à página do RP. Depois que o usuário fizer login, o IdP deverá:

  • Envie o cabeçalho Set-Login: logged-in ou chame a API navigator.login.setStatus("logged-in") para informar ao navegador que o usuário fez login.
  • Chame IdentityProvider.close() para fechar a caixa de diálogo.
Um usuário faz login em um RP depois de fazer login no IdP usando a FedCM.

Informar o navegador sobre o status de login do usuário

A API Login Status é um mecanismo em que um site, especialmente um IdP, informa ao navegador o status de login do usuário no IdP. Com essa API, o navegador pode reduzir solicitações desnecessárias ao IdP e mitigar possíveis ataques de tempo.

Os IdPs podem sinalizar o status de login do usuário para o navegador enviando um cabeçalho HTTP ou chamando uma API JavaScript quando o usuário faz login no IdP ou quando o usuário faz logout de todas as contas do IdP. Para cada IdP (identificado pelo URL de configuração), o navegador mantém uma variável de três estados que representa o estado de login com os seguintes valores possíveis:

  • logged-in
  • logged-out
  • unknown (padrão)
Estado do login Descrição
logged-in Quando o status de login do usuário é definido como logged-in, o RP que chama o FedCM faz solicitações para o endpoint de contas do IdP e mostra as contas disponíveis para o usuário na caixa de diálogo do FedCM.
logged-out Quando o status de login do usuário é logged-out, a chamada da FedCM falha silenciosamente sem fazer uma solicitação ao endpoint de contas do IdP.
unknown (padrão) O status unknown é definido antes de o IdP enviar um sinal usando a API Login Status. Quando o status é unknown, o navegador faz uma solicitação ao endpoint de contas do IdP e atualiza o status com base na resposta desse endpoint.

Para indicar que o usuário fez login, envie um cabeçalho HTTP Set-Login: logged-in em uma navegação de nível superior ou uma solicitação de subrecurso do mesmo site na origem do IdP:

  Set-Login: logged-in

Como alternativa, chame o método JavaScript navigator.login.setStatus('logged-in') da origem do IdP em uma navegação de nível superior:

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

O status de login do usuário será definido como logged-in.

Para indicar que o usuário saiu de todas as contas, envie um cabeçalho HTTP Set-Login: logged-out em uma navegação de nível superior ou uma solicitação de subrecurso do mesmo site na origem do IdP:

  Set-Login: logged-out

Ou chame a API JavaScript navigator.login.setStatus('logged-out') da origem do IdP em uma navegação de nível superior:

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

O status de login do usuário será definido como logged-out.

O status unknown é definido antes de o IdP enviar um indicador usando a API Login Status. O navegador faz uma solicitação ao endpoint de contas do IdP e atualiza o status com base na resposta do endpoint de contas:

  • Se o endpoint retornar uma lista de contas ativas, atualize o status para logged-in e abra a caixa de diálogo do FedCM para mostrar essas contas.
  • Se o endpoint não retornar nenhuma conta, atualize o status para logged-out e faça com que a chamada da FedCM falhe.

Permitir que o usuário faça login por um fluxo dinâmico

Mesmo que o IdP continue informando o status de login do usuário ao navegador, ele pode ficar dessincronizado, como quando a sessão expira. O navegador tenta enviar uma solicitação com credenciais ao endpoint de contas quando o status de login é logged-in, mas o servidor não retorna nenhuma conta porque a sessão não está mais disponível. Nesse cenário, o navegador pode permitir dinamicamente que o usuário faça login no IdP em uma janela pop-up.

Próximas etapas

Implemente o FedCM para seus RPs e distribua o SDK do JavaScript. Mantenha os RPs atualizados eliminando a necessidade de autoimplementação.
Aprenda a configurar o ambiente e depurar a implementação.