صدور Digital Credentials API در Chrome 155 ارائه می‌شود

تاریخ انتشار: ۲۳ اکتبر ۲۰۲۶

در Chrome نسخه ۱۵۵ و نسخه‌های جدیدتر، صدور Digital Credentials API به‌طور پیش‌فرض فعال است، بنابراین دیگر برای استفاده از آن به پرچم یا کد آزمایش معرفی ویژگی جدید نیاز ندارید. ‫Digital Credentials API یک لایه انتقال است که به وب‌سایت‌ها اجازه می‌دهد به برنامه‌های کیف پول نصب‌شده در دستگاه همراه کاربر متصل شوند. با صدور، صادرکنندگان می‌توانند اعتبارنامه‌های جدید (مانند شناسه‌های دیجیتال) را مستقیماً به برنامه کیف پول کاربر اضافه کنند.

پس‌زمینه

بوم‌سازگان هویت دیجیتال سه طرف دارد: صادرکنندگان، درستی‌سنج‌ها (که طرف‌های متکی نیز نامیده می‌شوند)، و دارندگان (برنامه‌های کیف پول). کاربران اغلب شناسه دیجیتال را ازطریق فراهم‌سازی فوری به برنامه کیف پول خود اضافه می‌کنند، جایی که کاربر صدور را از وب‌سایت یا برنامه صادرکننده شروع می‌کند. برای مثال، یک دانشجو در وب‌سایت دانشگاه خود (صادرکننده) می‌تواند شناسه دانشجویی دیجیتال خود را در برنامه کیف پول ترجیحی خود (دارنده) ذخیره کند.

برای اینکه این مدل موفقیت‌آمیز باشد، صادرکننده به روشی امن و مطمئن برای فراخوانی برنامه کیف پول جهت صدور مدرک شناسایی نیاز دارد. قبل‌از این API، هر صادرکننده باید روش خودش را برای باز کردن برنامه‌های کیف پولی که با آن‌ها شریک بود می‌ساخت، معمولاً با طرح‌واره‌های URI سفارشی. صادرکنندگان باید سازوکار جداگانه‌ای برای هر برنامه کیف پول حفظ می‌کردند و کاربران روش ثابتی برای انتخاب برنامه کیف پول نداشتند.

نحوه عملکرد صدور اعتبارنامه دیجیتال

برای ساده‌سازی این فرایند، Chrome از صدور با W3C Digital Credentials API پشتیبانی می‌کند. این به قابلیت‌های ارائه (هم‌رسانی داده‌های درخواستی و انتخابی از اطلاعات کاربری دیجیتال با تأییدکننده) که در Chrome 141 عرضه شد اضافه می‌شود. وقتی وب‌سایت صادرکننده navigator.credentials.create() را با عضو digital که حاوی درخواست صدور است فراخوانی می‌کند، Chrome درخواست را به سیستم‌عامل (در Android، «مدیر اطلاعات کاربری») ارسال می‌کند. سپس سیستم‌عامل میانای خودش را نشان می‌دهد که در آن کاربر برنامه کیف پولی را انتخاب می‌کند. این میانای برنامه‌سازی کاربردی با پروتکل‌های استاندارد صنعتی مثل OpenID برای صدور اطلاعات کاربری قابل‌تأیید (OpenID4VCI) کار می‌کند. صدور از دو جریان پشتیبانی می‌کند: جریان یک‌دستگاهی در Android، و جریان بین‌دستگاهی که در رایانه شروع می‌شود و در دستگاه Android به‌پایان می‌رسد.

جریان همان دستگاه در Android

در Android، ‏Chrome درخواست صدور را به Credential Manager Android ارسال می‌کند، که فهرستی از برنامه‌های کیف پول سازگار را در دستگاه نشان می‌دهد. کاربر کیف پولی را انتخاب می‌کند و با افزودن اعتبارنامه موافقت می‌کند. سپس برنامه کیف پول بااستفاده از پروتکل صدور، مانند OpenID4VCI، اعتبارنامه را از صادرکننده دریافت می‌کند.

جریان بین‌دستگاهی در رایانه

در رایانه، Chrome رمزینه پاسخ‌سریع را نمایش می‌دهد. کاربر کد را با دستگاه Android خود اسکن می‌کند و جریان را در آن دستگاه تکمیل می‌کند، همان‌طور که در بخش قبلی توضیح داده شد. دستگاه‌ها از بلوتوث برای تأیید اینکه نزدیک یکدیگر هستند استفاده می‌کنند، بنابراین Chrome از کاربر می‌خواهد که بلوتوث را درصورت خاموش بودن روشن کند. Chrome از همان سازوکار بین‌دستگاهی برای ارائه Digital Credentials 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() جایگزین منطق برنامه خودتان می‌شوند.

برای فراخوانی create() از iframe میان‌مبدئی، صفحه جاسازی باید ویژگی خط‌مشی اجازه‌های digital-credentials-create را مجاز کند. درغیراین‌صورت، تماس با NotAllowedError رد می‌شود:

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

تغییرات از زمان آزمایش معرفی ویژگی جدید

روش‌ها و پارامترهای میانای برنامه‌سازی کاربردی از زمان آزمایش معرفی ویژگی جدید تغییر نکرده‌اند. بااین‌حال، تغییرات زیر بین Chrome 143 و Chrome 155 عرضه شده‌اند و برخی‌از آن‌ها ممکن است نیاز به به‌روزرسانی کد شما داشته باشند. جدول زیر خلاصه‌ای از تغییرات را نشان می‌دهد و بخش‌های بعداز آن هرکدام را توضیح می‌دهد.

منطقه آزمایش معرفی ویژگی جدید (Chrome 143) Chrome 155
دردسترس بودن کد آزمایش معرفی ویژگی جدید یا پرچم chrome://flags/#web-identity-digital-credentials-creation به‌طور پیش‌فرض فعال است
فعال‌سازی کاربر الزامی است، اما مصرف نشده است موردنیاز و مصرف‌شده توسط هر تماس create() (Chrome 146)
خطاهای لغو NetworkError NotAllowedError (Chrome 148)
شناسه‌های پروتکل ‫Chrome هیچ شناسه‌ای را به سیستم‌عامل منتقل نمی‌کند شناسه‌های ناشناخته هشدار منسوخ شدن را فعال می‌کنند (Chrome 151)
مبدأهای مبهم اجازه داشتن مسدودشده با NotAllowedError (Chrome 151)
آزمایش خودکارسازی‌شده پشتیبانی داخلی ندارد کیف پول مجازی در پروتکل Chrome DevTools (نسخه ۱۵۲ Chrome)

فعال‌سازی کاربر مصرف شده است

از Chrome 146، تماس create() با عضو digital، فعال‌سازی گذرا توسط کاربر را مصرف می‌کند، همان‌طور که مشخصات ایجاب می‌کند. درطول آزمایش معرفی ویژگی جدید، Chrome فعال‌سازی کاربر را بررسی کرد اما آن را مصرف نکرد.

درنتیجه، هر فراخوانی create() به اشاره کاربر خودش نیاز دارد، برای مثال، کلیک روی دکمه. بدون فعال‌سازی کاربر، وعده با NotAllowedError رد می‌شود. پس‌از تماس، window.open() و دیگر میاناهای برنامه‌سازی کاربردی که به فعال‌سازی کاربر نیاز دارند نمی‌توانند از همان اشاره استفاده کنند.

لغو کردن با NotAllowedError رد می‌شود

از Chrome 148، وعده‌ای که create() برمی‌گرداند، وقتی کاربر جریان را لغو می‌کند، مثلاً با رد کردن انتخابگر کیف پول در Android یا بستن کادر گفتگوی رمزینه پاسخ‌سریع در رایانه، با NotAllowedError رد می‌شود. اگر هیچ برنامه کیف پولی نتواند درخواست را انجام دهد، این وعده با NotAllowedError رد می‌شود. درطول آزمایش معرفی ویژگی جدید، این موارد با NetworkError رد شدند.

اگر کد شما NetworkError را برای تشخیص لغو بررسی می‌کند، آن را به‌روز کنید تا به‌جای آن NotAllowedError را بررسی کند.

شناسه‌های پروتکل ناشناخته باعث فعال شدن هشدار می‌شود

این مشخصات یک شناسه پروتکل صدور واحد، openid4vci-v1، برای OpenID4VCI 1.0 تعریف می‌کند. ‫Chrome 155 ‏openid4vci-v1 و همچنین openid4vci را تشخیص می‌دهد. چون openid4vci بخشی از مشخصات نیست، توصیه می‌کنیم از openid4vci-v1 استفاده کنید.

‫Chrome درخواست‌ها را با هر شناسه پروتکلی به پلاتفرم ارسال می‌کند. بااین‌حال، از Chrome 151 به بعد، DevTools وقتی صفحه‌ای create() را با شناسه پروتکل ناشناخته‌ای فراخوانی می‌کند، هشدار منسوخ شدن نشان می‌دهد. ‫Chrome قصد دارد درخواست‌های دارای شناسه‌های پروتکل ناشناخته را مسدود کند. برای اطلاع از وضعیت، ورودی فیلتر کردن پروتکل خاص‌تر در Digital Credential API را ببینید.

برای آزمایش این رفتار، chrome://flags/#enable-experimental-web-platform-features را فعال کنید. با فعال بودن این پرچم، create() درخواست‌های دارای شناسه‌های پروتکل ناشناخته را نادیده می‌گیرد و اگر درخواستی باقی نمانده باشد، با TypeError رد می‌کند. همچنین، DigitalCredential.userAgentAllowsProtocol() فقط برای پروتکل‌های شناسایی‌شده true را برمی‌گرداند. بدون پرچم، فقط بررسی می‌کند که شناسه به‌درستی قالب‌بندی شده باشد. بنابراین، برای تشخیص ویژگی فقط به userAgentAllowsProtocol() تکیه نکنید. نام کاربری NotSupportedError همان‌طور که در مثال نشان داده شده است.

مبدأهای مبهم مسدود شده‌اند

از Chrome 151 به‌بعد، create() با NotAllowedError رد می‌شود وقتی که سندی با مبدأ مات آن را فراخوانی کند، مثل iframe جعبه امن بدون کد allow-same-origin. درطول آزمایش معرفی ویژگی جدید، Chrome این فراخوانی‌ها را مسدود نکرد.

آزمایش با کیف پول مجازی

از Chrome 152 به بعد، می‌توانید جریان صدور را بدون دستگاه Android یا برنامه کیف پول آزمایش کنید. فرمان آزمایشی DigitalCredentials.setVirtualWalletBehavior در پروتکل Chrome DevTools (CDP) کیف پول مجازی را که مشخصات برای آزمایش خودکار تعریف می‌کند پیاده‌سازی می‌کند. کیف پول مجازی می‌تواند با داده‌هایی که ارائه می‌دهید پاسخ دهد، درخواست‌ها را رد کند (مثل اینکه کاربر جریان را لغو کرده باشد)، یا درخواست‌ها را در حالت معلق بگذارد تا زمان‌های اتمام و لغو را آزمایش کند.

آزمایش 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 نسخه ۱۵۵ یا بالاتر به‌روزرسانی کنید.
  • برنامه کیف پول پشتیبانی‌شده‌ای را در دستگاه Android خود نصب کنید، برای مثال، نسخه نمایشی CMWallet.
  • بلوتوث در هر دو دستگاه روشن باشد (فقط جریان بین‌دستگاهی).

برای آزمایش کردن جریان بین‌دستگاهی:

  1. در رایانه، سایت صادرکننده نسخه نمایشی را باز کنید.
  2. روی دکمه افزودن کلیک کنید.
  3. رمزینه پاسخ‌سریع را با دستگاه Android خود اسکن کنید و دستورالعمل‌های روی صفحه را دنبال کنید.

برای آزمایش کردن جریان یک‌دستگاهی، سایت صادرکننده نمایشی را در Chrome در دستگاه Android خود باز کنید.

منابع برای برنامه‌نویسان

برای شروع ادغام کردن صدور Digital Credentials API در وب‌سایتتان، از منابع زیر استفاده کنید:

هم‌رسانی بازخورد

برای گزارش کردن اشکال یا درخواست ویژگی، مشکلی را در ردیاب اشکال Chromium ثبت کنید.