A emissão da API Digital Credentials é lançada no Chrome 155

Publicado em: 23 de outubro de 2026

No Chrome 155 e versões mais recentes, a emissão da API Digital Credentials é ativada por padrão, então você não precisa mais de um token de teste de origem ou de uma flag para usá-la. A API Digital Credentials é uma camada de transporte que permite que sites se conectem a apps de carteira instalados no dispositivo móvel do usuário. Com a emissão, os emissores podem adicionar novas credenciais (como documentos de identificação digitais) diretamente no app de carteira do usuário.

Contexto

O ecossistema de identidade digital tem três partes: emissores, verificadores (também chamados de partes confiáveis) e titulares (apps de carteira). Os usuários costumam adicionar um documento de identificação digital ao app de carteira por provisionamento por push, em que o usuário inicia a emissão no site ou app do emissor. Por exemplo, um estudante no site da universidade (emissor) pode salvar o documento de identificação digital de estudante no app de carteira preferido (titular).

Para que esse modelo seja bem-sucedido, o emissor precisa de uma maneira segura e confiável de invocar o app de carteira para emitir o documento. Antes dessa API, cada emissor precisava criar uma maneira própria de abrir os apps de carteira com que tinha parceria, geralmente com esquemas de URI personalizados. Os emissores precisavam manter um mecanismo separado para cada app de carteira, e os usuários não tinham uma maneira consistente de escolher um app de carteira.

Como funciona a emissão de credenciais digitais

Para simplificar esse processo, o Chrome oferece suporte à emissão com a API Digital Credentials do W3C. Isso complementa os recursos de apresentação (compartilhamento de dados seletivos solicitados de uma credencial digital com um verificador), que foram lançados no Chrome 141. Quando um site de emissor chama navigator.credentials.create() com um membro digital que contém uma solicitação de emissão, o Chrome transmite a solicitação para o sistema operacional (no Android, o Gerenciador de credenciais). Em seguida, o sistema operacional mostra a própria interface, em que o usuário escolhe um app de carteira. A API funciona com protocolos padrão do setor, como OpenID para emissão de credenciais verificáveis (OpenID4VCI). A emissão é compatível com dois fluxos: um no mesmo dispositivo Android e outro entre dispositivos, que começa no computador e termina em um dispositivo Android.

Fluxo no mesmo dispositivo no Android

No Android, o Chrome transmite o pedido de emissão ao Gerenciador de credenciais do Android, que mostra uma lista de apps de carteira compatíveis no dispositivo. O usuário seleciona uma carteira e autoriza a adição da credencial. Em seguida, o app de carteira recebe a credencial do emissor usando o protocolo de emissão, como o OpenID4VCI.

Fluxo entre dispositivos no computador

No computador, o Chrome mostra um QR code. O usuário lê o código com o dispositivo Android e conclui o fluxo nesse dispositivo, conforme descrito na seção anterior. Os dispositivos usam o Bluetooth para confirmar que estão próximos um do outro. Por isso, o Chrome pede que o usuário ative o Bluetooth, se estiver desativado. O Chrome usa o mesmo mecanismo entre dispositivos para a apresentação da API Digital Credentials.

Implementar a emissão usando a API

Para iniciar o fluxo de emissão, chame navigator.credentials.create() e transmita as solicitações de emissão em um membro digital. Faça essa chamada de um gerenciador de cliques ou de outro gerenciador de interação do usuário, porque a chamada requer ativação temporária do usuário. O exemplo a seguir usa uma oferta de credencial OpenID4VCI com o fluxo de código pré-autorizado:

// Call this function from a user gesture handler, for example, a button's
// click handler. The pre-authorized code is a short-lived, single-use code
// that your server generates for the signed-in user.
async function issueDigitalCredential(preAuthorizedCode) {
  // Check for Digital Credentials API and protocol support.
  if (!window.DigitalCredential ||
      !DigitalCredential.userAgentAllowsProtocol('openid4vci-v1')) {
    // Provide an alternative issuance method.
    showAlternativeIssuanceFlow();
    return;
  }

  // Construct a credential offer according to the OpenID4VCI
  // specification. This example uses the format that the
  // demo CMWallet supports.
  const credentialOffer = {
    credential_issuer: 'https://issuer.example',
    credential_configuration_ids: ['org.iso.18013.5.1.mDL'],
    grants: {
      'urn:ietf:params:oauth:grant-type:pre-authorized_code': {
        'pre-authorized_code': preAuthorizedCode
      }
    },
    // Metadata that the wallet uses to request and display the credential.
    credential_issuer_metadata: {
      credential_issuer: 'https://issuer.example',
      credential_endpoint: 'https://issuer.example/openid4vci/credential',
      nonce_endpoint: 'https://issuer.example/openid4vci/nonce',
      credential_configurations_supported: {
        'org.iso.18013.5.1.mDL': {
          format: 'mso_mdoc',
          doctype: 'org.iso.18013.5.1.mDL',
          // Bind the credential to a key that the wallet generates.
          cryptographic_binding_methods_supported: ['cose_key'],
          proof_types_supported: {
            jwt: { proof_signing_alg_values_supported: ['ES256'] }
          },
          credential_metadata: {
            display: [{ name: 'Mobile driving license', locale: 'en-US' }],
            // The claims that this credential contains. For a full list of
            // standard mDL claims, see the ISO/IEC 18013-5 specification.
            claims: [{
              path: ['org.iso.18013.5.1', 'family_name'],
              display: [{ name: 'Family name', locale: 'en-US' }]
            }
            // ... Add any other claims for your credential here.
            ]
          }
        }
      }
    },
    // Metadata of the authorization server that issues access tokens.
    authorization_server_metadata: {
      issuer: 'https://issuer.example',
      token_endpoint: 'https://issuer.example/openid4vci/token'
    }
  };

  try {
    const credential = await navigator.credentials.create({
      digital: {
        requests: [{
          // The protocol identifier for OpenID4VCI 1.0.
          protocol: 'openid4vci-v1',
          // Pass the offer as an object, not as a JSON string.
          data: credentialOffer
        }]
      }
    });

    // The wallet handled the request. credential.data is an object that
    // contains the wallet's protocol-specific response. It is not the issued
    // credential, and it does not necessarily mean that issuance is complete.
    // Your server knows when the wallet retrieves the credential from your
    // credential endpoint.
    // Implement your custom logic here as needed.
    showIssuanceStatus(credential);
  } catch (error) {
    switch (error.name) {
      case 'NotAllowedError':
        // The user canceled the flow, no wallet can handle the request, or
        // the call does not have transient user activation.
        break;
      case 'NotSupportedError':
        // The browser does not support Digital Credentials API issuance.
        // Fall back to your custom alternative flow logic.
        showAlternativeIssuanceFlow();
        break;
      case 'TypeError':
        // The request is malformed, for example, data is not an object.
        console.error('Invalid issuance request:', error);
        break;
      default:
        // For example, AbortError or NetworkError.
        console.error('Credential issuance failed:', error);
    }
  }
}

const addButton = document.querySelector('#add-to-wallet');
addButton.addEventListener('click', () => {
  // Your server adds a pre-authorized code for the signed-in user
  // to the button's data-pre-authorized-code attribute.
  issueDigitalCredential(addButton.dataset.preAuthorizedCode);
});

Neste exemplo, showAlternativeIssuanceFlow() e showIssuanceStatus() representam sua própria lógica de app.

Para chamar create() de um iframe entre origens, a página de incorporação precisa permitir o recurso de política de permissões digital-credentials-create. Caso contrário, a chamada será rejeitada com um NotAllowedError:

<iframe src="https://issuer.example" allow="digital-credentials-create">
</iframe>

Mudanças desde o teste de origem

Os métodos e parâmetros da API não mudaram desde o teste de origem. No entanto, as mudanças a seguir foram lançadas entre o Chrome 143 e o Chrome 155, e algumas delas podem exigir que você atualize seu código. A tabela a seguir resume as mudanças, e as seções seguintes explicam cada uma delas.

Área Teste de origem (Chrome 143) Chrome 155
Disponibilidade Token de teste de origem ou a flag chrome://flags/#web-identity-digital-credentials-creation Ativado por padrão
Ativação do usuário Obrigatório, mas não consumido Obrigatório e consumido por cada chamada create() (Chrome 146)
Erros de cancelamento NetworkError NotAllowedError (Chrome 148)
Identificadores de protocolo O Chrome transmite qualquer identificador para o sistema operacional Identificadores não reconhecidos acionam um aviso de descontinuação (Chrome 151)
Origens opacas Permitido Bloqueado com NotAllowedError (Chrome 151)
Testes automatizados Sem suporte integrado Carteira virtual no Chrome DevTools Protocol (Chrome 152)

A ativação do usuário é consumida

A partir do Chrome 146, uma chamada create() com um membro digital consome a ativação temporária do usuário, conforme exigido pela especificação. Durante o teste de origem, o Chrome verificou a ativação do usuário, mas não a consumiu.

Como resultado, cada chamada create() precisa da própria interação inicial, por exemplo, um clique em um botão. Sem a ativação do usuário, a promessa é rejeitada com um NotAllowedError. Após a chamada, window.open() e outras APIs que exigem ativação do usuário não podem usar o mesmo gesto.

O cancelamento rejeita com NotAllowedError

A partir do Chrome 148, a promessa que create() retorna rejeita com um NotAllowedError quando o usuário cancela o fluxo, por exemplo, ao dispensar o seletor de carteira no Android ou fechar a caixa de diálogo do QR code no computador. A promessa também rejeita com um NotAllowedError quando nenhum app de carteira pode processar a solicitação. Durante o teste de origem, esses casos foram rejeitados com um NetworkError.

Se o código verificar um NetworkError para detectar o cancelamento, atualize-o para verificar um NotAllowedError.

Identificadores de protocolo não reconhecidos acionam um aviso

A especificação define um único identificador de protocolo de emissão, openid4vci-v1, para o OpenID4VCI 1.0. O Chrome 155 reconhece openid4vci-v1 e também openid4vci. Como openid4vci não faz parte da especificação, recomendamos que você use openid4vci-v1.

O Chrome transmite solicitações com qualquer identificador de protocolo para a plataforma. No entanto, a partir do Chrome 151, o DevTools mostra um aviso de descontinuação quando uma página chama create() com um identificador de protocolo não reconhecido. O Chrome pretende bloquear solicitações com identificadores de protocolo não reconhecidos. Para saber o status, consulte a entrada "Filtragem de protocolo mais específica na API Digital Credential".

Para testar esse comportamento, ative chrome://flags/#enable-experimental-web-platform-features. Com essa flag ativada, o create() ignora solicitações com identificadores de protocolo não reconhecidos e rejeita com um TypeError se não houver mais solicitações. Além disso, DigitalCredential.userAgentAllowsProtocol() retorna true apenas para protocolos reconhecidos. Sem a flag, ele só verifica se o identificador está bem formado. Portanto, não use apenas userAgentAllowsProtocol() para detectar recursos. Processe NotSupportedError como mostrado no exemplo.

Origens opacas são bloqueadas

A partir do Chrome 151, create() rejeita com um NotAllowedError quando um documento com uma origem opaca o chama, como um iframe em sandbox sem o token allow-same-origin. Durante o teste de origem, o Chrome não bloqueou essas chamadas.

Testar com uma carteira virtual

A partir do Chrome 152, é possível testar seu fluxo de emissão sem um dispositivo Android ou um app de carteira. O comando experimental DigitalCredentials.setVirtualWalletBehavior no Chrome DevTools Protocol (CDP) implementa a carteira virtual que a especificação define para testes automatizados. A carteira virtual pode responder com os dados que você fornecer, recusar solicitações como se o usuário tivesse cancelado o fluxo ou deixar solicitações pendentes para testar tempos limite e cancelamentos.

O teste do Puppeteer a seguir define a carteira virtual para responder às solicitações openid4vci-v1 e, em seguida, clica no botão que inicia a emissão:

const client = await page.createCDPSession();
await client.send('DigitalCredentials.setVirtualWalletBehavior', {
  action: 'respond',
  protocol: 'openid4vci-v1',
  response: {}
});

// Clicking the button provides the user activation that create() requires.
await page.click('#add-to-wallet');

Adoção pelo setor

Vemos a adoção da emissão da API Digital Credentials. Por exemplo, a instituição financeira alemã Sparkasse usa a API Digital Credentials para permitir que os titulares de contas salvem credenciais de idade verificadas na Carteira do Google. Os proprietários das contas podem usar essas credenciais para confirmar a idade on-line e pessoalmente.

Faça um teste

Antes de testar a emissão da API Digital Credentials, verifique se você tem o seguinte:

  • Atualize para o Chrome 155 ou mais recente.
  • Instale um app de carteira compatível no seu dispositivo Android, por exemplo, a demonstração da CMWallet.
  • O Bluetooth ativado nos dois dispositivos (somente para o fluxo multidispositivo).

Para testar o fluxo multidispositivo:

  1. No computador, abra o site de demonstração do emissor.
  2. Clique no botão Adicionar.
  3. Leia o QR code com o dispositivo Android e siga as instruções na tela.

Para testar o fluxo no mesmo dispositivo, abra o site do emissor de demonstração no Chrome no seu dispositivo Android.

Recursos para desenvolvedores

Para começar a integrar a emissão da API Digital Credentials ao seu site, use os seguintes recursos:

Envie feedback

Para informar um bug ou solicitar um recurso, registre um problema no rastreador de bugs do Chromium.