發布日期:2026 年 10 月 23 日
在 Chrome 155 以上版本中,Digital Credentials API 發行功能預設為啟用,因此您不再需要來源試用權杖或旗標,即可使用這項功能。Digital Credentials API 是傳輸層,可讓網站連結至使用者行動裝置上安裝的錢包應用程式。發卡機構可透過發卡功能,直接將新的憑證 (例如數位身分證件) 新增至使用者的錢包應用程式。
背景
數位身分生態系統有三個參與方:核發者、驗證者 (也稱為依賴方) 和持有者 (錢包應用程式)。使用者通常會透過推送佈建,將數位身分證件新增至錢包應用程式,也就是從發卡機構的網站或應用程式開始核發程序。舉例來說,學生可以在大學網站 (發卡機構) 將數位學生證儲存至偏好的錢包應用程式 (持有者)。
如要成功採用這個模式,核發機構必須能以安全可靠的方式叫用錢包應用程式,核發身分證件。在這個 API 推出前,各發卡機構必須自行建構開啟合作錢包應用程式的方法,通常是使用自訂 URI 配置。發卡機構必須為每個錢包應用程式維護獨立機制,使用者也無法以一致的方式選擇錢包應用程式。
數位憑證核發作業的運作方式
為簡化這項程序,Chrome 支援使用 W3C Digital Credentials API 發行憑證。這項功能可強化 Chrome 141 推出的展示功能 (與驗證者共用數位憑證中要求的特定資料)。當發卡機構網站呼叫 navigator.credentials.create(),且 digital 成員包含核發要求時,Chrome 會將要求傳遞至作業系統 (在 Android 上為 Credential Manager)。接著,作業系統會顯示自己的介面,讓使用者選擇錢包應用程式。這個 API 支援業界標準通訊協定,例如 OpenID for Verifiable Credential Issuance (OpenID4VCI)。核發作業支援兩種流程:Android 上的同裝置流程,以及從電腦開始並在 Android 裝置上完成的跨裝置流程。
Android 上的相同裝置流程
在 Android 裝置上,Chrome 會將核發要求傳送至 Android Credential Manager,後者會顯示裝置上相容的錢包應用程式清單。使用者選取錢包,並同意新增憑證。接著,錢包應用程式會使用核發通訊協定 (例如 OpenID4VCI),從核發機構取得憑證。
電腦上的跨裝置流程
在電腦上,Chrome 會顯示 QR code。使用者使用 Android 裝置掃描代碼,並在該裝置上完成流程,如上一節所述。裝置會使用藍牙確認彼此距離不遠,因此如果藍牙功能關閉,Chrome 會要求使用者開啟。Chrome 會使用相同的跨裝置機制,呈現 Digital Credentials API。
使用 API 實作核發功能
如要啟動核發流程,請呼叫 navigator.credentials.create(),並在 digital 成員中傳遞核發要求。請從點擊處理常式或其他使用者手勢處理常式發出這項呼叫,因為呼叫需要暫時啟用使用者。以下範例使用 OpenID4VCI 憑證,並搭配預先授權碼流程:
// 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);
});
在這個範例中,showAlternativeIssuanceFlow() 和 showIssuanceStatus() 代表您自己的應用程式邏輯。
如要從跨源 iframe 呼叫 create(),嵌入頁面必須允許 digital-credentials-create 權限政策功能。否則,呼叫會遭到拒絕,並傳回 NotAllowedError:
<iframe src="https://issuer.example" allow="digital-credentials-create">
</iframe>
來源試用後的異動
API 方法和參數自來源試用以來並未變更。不過,Chrome 143 到 Chrome 155 之間推出了下列異動,其中部分可能需要您更新程式碼。下表摘要說明這些異動,後續章節則會逐一說明。
| 區 | 來源試用 (Chrome 143) | Chrome 155 |
|---|---|---|
| 可用性 | 來源試用權杖或 chrome://flags/#web-identity-digital-credentials-creation 旗標 |
預設為啟用 |
| 使用者啟用 | 必要,但未消耗 | 每個 create() 呼叫都需要並會消耗這個權限 (Chrome 146) |
| 取消錯誤 | NetworkError |
NotAllowedError (Chrome 148) |
| 通訊協定 ID | Chrome 會將所有 ID 傳遞至作業系統 | 無法辨識的 ID 會觸發淘汰警告 (Chrome 151) |
| 不透明來源 | 已允許 | 已使用 NotAllowedError 封鎖 (Chrome 151) |
| 自動化測試 | 不提供內建支援 | Chrome 開發人員工具通訊協定中的虛擬錢包 (Chrome 152) |
使用者啟用
自 Chrome 146 起,根據規格要求,含有 digital 成員的 create() 呼叫會消耗暫時性使用者啟用。在來源試用期間,Chrome 會檢查使用者啟用狀態,但不會耗用。
因此,每次呼叫 create() 都需要使用者手勢,例如點選按鈕。如果使用者未啟用,Promise 會拒絕並傳回 NotAllowedError。呼叫後,window.open() 和其他需要使用者啟用的 API 無法使用相同手勢。
取消遭拒,原因:NotAllowedError
從 Chrome 148 開始,當使用者取消流程時 (例如在 Android 上關閉錢包選取器,或在電腦上關閉 QR code 對話方塊),create() 傳回的承諾會拒絕並顯示 NotAllowedError。如果沒有錢包應用程式可以處理要求,Promise 也會拒絕並傳回 NotAllowedError。在來源試用期間,系統會拒絕這些情況,並傳回 NetworkError。
如果程式碼會檢查 NetworkError 來偵測取消,請改為檢查 NotAllowedError。
無法辨識的通訊協定 ID 會觸發警告
這項規格定義了 OpenID4VCI 1.0 的單一核發通訊協定 ID openid4vci-v1。Chrome 155 可辨識 openid4vci-v1 和 openid4vci。由於 openid4vci 不是規格的一部分,建議您使用 openid4vci-v1。
Chrome 會將含有任何通訊協定 ID 的要求傳遞至平台。不過,自 Chrome 151 起,如果網頁使用無法辨識的通訊協定 ID 呼叫 create(),開發人員工具會顯示淘汰警告。Chrome 打算封鎖含有無法辨識通訊協定 ID 的要求。如要瞭解狀態,請參閱「Digital Credential API 採用更明確的通訊協定篩選機制」一節。
如要測試這項行為,請啟用 chrome://flags/#enable-experimental-web-platform-features。啟用這個旗標後,create() 會忽略含有無法辨識通訊協定 ID 的要求,如果沒有剩餘要求,則會拒絕並傳回 TypeError。此外,DigitalCredential.userAgentAllowsProtocol() 只會針對可辨識的通訊協定傳回 true。如未設定這個旗標,系統只會檢查 ID 格式是否正確。因此,請勿僅依賴 userAgentAllowsProtocol() 進行功能偵測。如範例所示,處理 NotSupportedError。
不透明來源遭到封鎖
自 Chrome 151 起,如果具有不透明來源的文件呼叫 create(),例如沒有 allow-same-origin 權杖的沙箱 iframe,則會遭到 NotAllowedError 拒絕。在來源試用期間,Chrome 不會封鎖這類呼叫。
使用虛擬錢包測試
自 Chrome 152 起,您不必使用 Android 裝置或錢包應用程式,即可測試核發流程。Chrome 開發人員工具通訊協定 (CDP) 中的實驗性 DigitalCredentials.setVirtualWalletBehavior 指令,會實作規格為自動化測試定義的虛擬錢包。虛擬錢包可以回應您提供的資料、拒絕要求 (就像使用者取消流程一樣),或讓要求處於待處理狀態,以便測試逾時和中止。
下列 Puppeteer 測試會將虛擬錢包設為回應 openid4vci-v1 要求,然後點選啟動核發作業的按鈕:
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');
業界導入案例
我們發現 Digital Credentials API 核發功能已獲採用。舉例來說,德國金融機構 Sparkasse 使用 Digital Credentials API,讓帳戶持有人將經過驗證的年齡憑證儲存到 Google 錢包。帳戶持有人可以使用這些憑證,在線上和實體環境驗證年齡。
試試看
測試 Digital Credentials API 核發功能前,請確認您已備妥下列項目:
- 請更新至 Chrome 155 以上版本。
- 在 Android 裝置上安裝支援的錢包應用程式,例如試用版 CMWallet。
- 兩部裝置都已開啟藍牙 (僅限跨裝置流程)。
如要測試跨裝置流程,請按照下列步驟操作:
- 在電腦上開啟發卡機構示範網站。
- 按一下「新增」按鈕。
- 使用 Android 裝置掃描 QR code,並按照畫面上的指示操作。
如要測試相同裝置流程,請在 Android 裝置上使用 Chrome 開啟發卡機構示範網站。
開發人員資源
如要開始將 Digital Credentials API 核發功能整合至網站,請使用下列資源:
- 請參閱 W3C Web Identity & Credentials Adoption Community Group 的開發人員指南。
- 請參閱 W3C 數位憑證規格。
- 請參閱 OpenID for Verifiable Credential Issuance 1.0 規格。
- 探索 CMWallet 試用版的原始碼,這是一款 Android 開放原始碼試用版錢包應用程式。
- 瞭解 Android 錢包應用程式如何處理 Credential Manager 的核發要求。
- 在 Android 裝置上安裝 CMWallet 試用版,並試用發卡機構試用網站。
- 探索數位憑證要求建構函式示範,瞭解要求酬載的樣貌。
提供意見
如要回報錯誤或提出功能要求,請在 Chromium Issue Tracker 中提交問題。