L'emissione dell'API Digital Credentials è disponibile in Chrome 155

Data di pubblicazione: 23 ottobre 2026

In Chrome 155 e versioni successive, l'emissione dell'API Digital Credentials è abilitata per impostazione predefinita, quindi non hai più bisogno di un token di origin trial o di un flag per utilizzarla. L'API Digital Credentials è un livello di trasporto che consente ai siti web di connettersi alle app wallet installate sul dispositivo mobile dell'utente. Con l'emissione, gli emittenti possono aggiungere nuove credenziali (come i documenti di identità digitali) direttamente nell'app Wallet di un utente.

Sfondo

L'ecosistema dell'identità digitale è composto da tre parti: emittenti, verificatori (chiamati anche parti fidate) e titolari (app wallet). Gli utenti spesso aggiungono un documento di identità digitale alla loro app wallet tramite il provisioning push, in cui l'utente avvia l'emissione dal sito web o dall'app dell'emittente. Ad esempio, uno studente sul sito web della sua università (emittente) può salvare il suo documento di identità digitale dello studente nell'app wallet preferita (titolare).

Affinché questo modello funzioni, l'emittente deve avere un modo sicuro e affidabile per richiamare l'app Wallet per emettere il documento di identità. Prima di questa API, ogni emittente doveva creare il proprio modo per aprire le app wallet con cui collaborava, di solito con schemi URI personalizzati. Gli emittenti dovevano mantenere un meccanismo separato per ogni app wallet e gli utenti non avevano un modo coerente per scegliere un'app wallet.

Come funziona l'emissione di credenziali digitali

Per semplificare questa procedura, Chrome supporta l'emissione con l'API Digital Credentials del W3C. Questo si aggiunge alle funzionalità di presentazione (condivisione di dati richiesti e selettivi da una credenziale digitale con un verificatore), disponibili in Chrome 141. Quando un sito web dell'emittente chiama navigator.credentials.create() con un membro digital che contiene una richiesta di emissione, Chrome la trasmette al sistema operativo (su Android, Gestore delle credenziali). Il sistema operativo mostra quindi la propria interfaccia in cui l'utente sceglie un'app wallet. L'API funziona con protocolli standard di settore come OpenID for Verifiable Credential Issuance (OpenID4VCI). L'emissione supporta due flussi: un flusso sullo stesso dispositivo su Android e un flusso cross-device che inizia su computer e termina su un dispositivo Android.

Flusso sullo stesso dispositivo su Android

Su Android, Chrome trasmette la richiesta di emissione al Gestore delle credenziali di Android, che mostra un elenco di app wallet compatibili sul dispositivo. L'utente seleziona un wallet e acconsente all'aggiunta della credenziale. L'app wallet riceve quindi la credenziale dall'emittente utilizzando il protocollo di emissione, ad esempio OpenID4VCI.

Flusso cross-device su computer

Su computer, Chrome mostra un codice QR. L'utente scansiona il codice con il proprio dispositivo Android e completa il flusso su quel dispositivo, come descritto nella sezione precedente. I dispositivi utilizzano il Bluetooth per confermare che sono vicini tra loro, quindi Chrome chiede all'utente di attivare il Bluetooth se è disattivato. Chrome utilizza lo stesso meccanismo cross-device per la presentazione dell'API Digital Credentials.

Implementa l'emissione utilizzando l'API

Per avviare il flusso di emissione, chiama navigator.credentials.create() e passa le tue richieste di emissione all'interno di un membro digital. Effettua questa chiamata da un gestore di clic o da un altro gestore di attivazioni dall'utente, perché la chiamata richiede l'attivazione temporanea dell'utente. L'esempio seguente utilizza un'offerta di credenziali OpenID4VCI con il flusso del codice pre-autorizzato:

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

In questo esempio, showAlternativeIssuanceFlow() e showIssuanceStatus() rappresentano la logica della tua app.

Per chiamare create() da un iframe multiorigine, la pagina di incorporamento deve consentire la funzionalità della policy relativa alle autorizzazioni digital-credentials-create. In caso contrario, la chiamata viene rifiutata con un NotAllowedError:

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

Modifiche rispetto all'origin trial

I metodi e i parametri dell'API non sono cambiati rispetto all'origin trial. Tuttavia, le seguenti modifiche sono state introdotte tra Chrome 143 e Chrome 155 e alcune di queste potrebbero richiedere l'aggiornamento del codice. La tabella seguente riassume le modifiche, che vengono spiegate nelle sezioni successive.

Area Origin trial (Chrome 143) Chrome 155
Disponibilità Token di origin trial o il flag chrome://flags/#web-identity-digital-credentials-creation Abilitato per impostazione predefinita
Attivazione utente Richiesto, ma non utilizzato Obbligatorio e utilizzato da ogni chiamata create() (Chrome 146)
Errori di annullamento NetworkError NotAllowedError (Chrome 148)
Identificatori di protocollo Chrome trasmette un identificatore al sistema operativo Gli identificatori non riconosciuti attivano un avviso di ritiro (Chrome 151)
Origini opache Consentito Bloccato con NotAllowedError (Chrome 151)
Test automatici Nessuna assistenza integrata Portafoglio virtuale in Chrome DevTools Protocol (Chrome 152)

L'attivazione utente viene consumata

A partire da Chrome 146, una chiamata create() con un membro digital consuma l'attivazione utente temporanea, come richiesto dalla specifica. Durante l'origin trial, Chrome ha verificato l'attivazione dell'utente, ma non l'ha utilizzata.

Di conseguenza, ogni chiamata create() richiede un'attivazione dall'utente, ad esempio un clic su un pulsante. Senza l'attivazione utente, la promise viene rifiutata con un errore NotAllowedError. Dopo la chiamata, window.open() e altre API che richiedono l'attivazione dell'utente non possono utilizzare lo stesso gesto.

Rifiuti di annullamento con NotAllowedError

A partire da Chrome 148, la promise restituita da create() viene rifiutata con un NotAllowedError quando l'utente annulla il flusso, ad esempio ignorando il selettore del wallet su Android o chiudendo la finestra di dialogo del codice QR su computer. La promessa viene rifiutata anche con un NotAllowedError quando nessuna app wallet può gestire la richiesta. Durante l'origin trial, questi casi sono stati rifiutati con un errore NetworkError.

Se il tuo codice controlla un NetworkError per rilevare l'annullamento, aggiornalo in modo che controlli invece un NotAllowedError.

Gli identificatori di protocollo non riconosciuti attivano un avviso

La specifica definisce un singolo identificatore del protocollo di emissione, openid4vci-v1, per OpenID4VCI 1.0. Chrome 155 riconosce openid4vci-v1 e anche openid4vci. Poiché openid4vci non fa parte della specifica, ti consigliamo di utilizzare openid4vci-v1.

Chrome trasmette alla piattaforma le richieste con qualsiasi identificatore di protocollo. Tuttavia, a partire da Chrome 151, DevTools mostra un avviso di ritiro quando una pagina chiama create() con un identificatore di protocollo non riconosciuto. Chrome intende bloccare le richieste con identificatori di protocollo non riconosciuti. Per lo stato, consulta la voce Filtro dei protocolli più specifico nell'API Digital Credential.

Per testare questo comportamento, attiva chrome://flags/#enable-experimental-web-platform-features. Con questo flag attivato, create() ignora le richieste con identificatori di protocollo non riconosciuti e le rifiuta con un TypeError se non rimangono richieste. Inoltre, DigitalCredential.userAgentAllowsProtocol() restituisce true solo per i protocolli riconosciuti. Senza il flag, verifica solo che l'identificatore sia nel formato corretto. Pertanto, non fare affidamento solo su userAgentAllowsProtocol() per il rilevamento delle funzionalità. Gestisci NotSupportedError come mostrato nell'esempio.

Le origini opache sono bloccate

A partire da Chrome 151, create() rifiuta con un NotAllowedError quando un documento con un'origine opaca lo chiama, ad esempio un iframe con sandbox senza il token allow-same-origin. Durante l'origin trial, Chrome non ha bloccato queste chiamate.

Esegui il test con un wallet virtuale

A partire da Chrome 152, puoi testare il flusso di emissione senza un dispositivo Android o un'app wallet. Il comando sperimentale DigitalCredentials.setVirtualWalletBehavior nel Chrome DevTools Protocol (CDP) implementa il wallet virtuale definito dalla specifica per i test automatici. Il wallet virtuale può rispondere con i dati che fornisci, rifiutare le richieste come se l'utente avesse annullato il flusso o lasciare le richieste in attesa per testare timeout e interruzioni.

Il seguente test Puppeteer imposta il wallet virtuale in modo che risponda alle richieste openid4vci-v1, quindi fa clic sul pulsante che avvia l'emissione:

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

Adozione nel settore

Abbiamo notato l'adozione dell'emissione dell'API Digital Credentials. Ad esempio, l'istituto finanziario tedesco Sparkasse utilizza l'API Digital Credentials per consentire ai proprietari di account di salvare le credenziali di età verificate su Google Wallet. I proprietari degli account possono quindi utilizzare queste credenziali per verificare la loro età online e di persona.

Prova

Prima di testare l'emissione dell'API Digital Credentials, assicurati di disporre di quanto segue:

  • Esegui l'aggiornamento a Chrome 155 o versioni successive.
  • Installa un'app wallet supportata sul tuo dispositivo Android, ad esempio la demo CMWallet.
  • Bluetooth attivato su entrambi i dispositivi (solo flusso cross-device).

Per testare il flusso cross-device:

  1. Sul computer, apri il sito demo dell'emittente.
  2. Fai clic sul pulsante Aggiungi.
  3. Scansiona il codice QR con il tuo dispositivo Android e segui le istruzioni sullo schermo.

Per testare il flusso sullo stesso dispositivo, apri il sito dell'emittente demo in Chrome sul tuo dispositivo Android.

Risorse per gli sviluppatori

Per iniziare a integrare l'emissione dell'API Digital Credentials nel tuo sito web, utilizza le seguenti risorse:

Condividi il tuo feedback

Per segnalare un bug o richiedere una funzionalità, segnala un problema nel tracker dei bug di Chromium.