보안 결제 확인

W3C 후보 권고안 초안,

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/CRD-secure-payment-confirmation-20261013/
최신 발행 버전:
https://www.w3.org/TR/secure-payment-confirmation/
편집자 초안:
https://w3c.github.io/secure-payment-confirmation/
이전 버전:
변경 이력:
https://www.w3.org/standards/history/secure-payment-confirmation/
구현 보고서:
https://wpt.fyi/results/secure-payment-confirmation
의견:
GitHub
명세 내 인라인
편집자:
(Google)
전 편집자:
(Google)
기여자:
Ian Jacobs (W3C)
Nick Burris (Google)
Darwin Yang (Google)
테스트 스위트:
https://wpt.fyi/results/secure-payment-confirmation/

초록

보안 결제 확인(SPC)은 결제 거래 중 간소화된 인증을 지원하는 Web API입니다. 이 API는 여러 판매자에 걸쳐 인증을 확장하고, 다양한 인증 프로토콜에서 사용되며, 사용자가 거래 세부 정보를 확인했음을 입증하는 암호학적 증거를 생성하도록 설계되었습니다.

이 문서의 상태

이 절에서는 문서가 발행될 당시의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인하실 수 있습니다.

이 문서는 웹 결제 워킹 그룹이 권고안 절차에 따라 후보 권고안 초안으로 발행했습니다.

이전 후보 권고안 확정본 이후의 변경 사항은 GitHub 변경 이력을 참조하시기 바랍니다.

후보 권고안으로 발행되었다고 해서 W3C와 그 회원사가 이를 승인했다는 의미는 아닙니다. 후보 권고안 초안에는 워킹 그룹이 후속 후보 권고안 확정본에 포함하려는 이전 후보 권고안 이후의 변경 사항이 통합되어 있습니다.

이 문서는 초안이며 언제든지 다른 문서로 갱신되거나 대체되거나 폐기될 수 있습니다. 따라서 진행 중인 작업이라는 점을 명시하지 않고 이 문서를 인용하는 것은 적절하지 않습니다.

이 명세가 제안 권고안 단계로 진행되려면 사용자 에이전트에서 독립적이고 상호 운용 가능한 두 가지 구현을 입증해야 합니다. 관련 구현 보고서를 참조하시기 바랍니다.

이 후보 권고안은 2023년 8월 1일 이전에 제안 권고안으로 진행될 것으로 예상되지 않습니다.

웹 결제 워킹 그룹은 이슈 목록을 관리합니다.

후보 권고안으로 발행되었다고 해서 W3C와 그 회원사가 이를 승인했다는 의미는 아닙니다. 후보 권고안 초안에는 워킹 그룹이 후속 후보 권고안 확정본에 포함하려는 이전 후보 권고안 이후의 변경 사항이 통합되어 있습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했습니다. W3C는 이 그룹의 산출물과 관련하여 제출된 특허 공개 목록을 공개적으로 관리하며, 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 자신이 실제로 알고 있는 특허에 필수 청구항이 포함되어 있다고 판단하는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.

이 문서에는 2025년 8월 18일 W3C 절차 문서가 적용됩니다.

1. 소개

이 절과 그 하위 절은 비규범적입니다.

이 명세는 웹상의 결제 과정에서 강력한 인증 방법을 사용할 수 있도록 하는 API를 정의합니다. 이 API는 [webauthn-3]와 동일한 인증 이점과 사용자 개인정보 보호에 대한 중점을 유지하면서 결제 처리의 요구 사항을 충족하기 위한 개선 사항을 제공하는 것을 목표로 합니다.

[webauthn-3]와 마찬가지로, 이 명세는 사용자와 관련된 두 가지 프로세스를 정의합니다. 첫 번째는 § 3 등록(이전에는 "등록 절차(enrollment)"라고 불렸습니다)로, 사용자와 신뢰 당사자 사이의 관계가 형성됩니다. 두 번째는 § 4 인증 - 보안 결제 확인 결제 수단으로, 사용자가 신뢰 당사자의 챌린지에 (중개 결제 서비스 제공업체를 통해서일 수도 있습니다) 응답하여 특정 결제에 동의하는 과정입니다.

이 명세의 목표 중 하나는 결제 과정에서 인증에 따른 불편을 줄이는 것이며, 이를 위한 한 가지 방법은 한 번의 등록으로 사용자가 수행할 수 있는 인증 횟수를 최대화하는 것입니다. 즉, 신뢰 당사자의 동의가 있다면, 이상적으로 사용자는 "한 번만 등록"하고 모든 판매자 출처에서(결제 서비스 제공업체를 통해서도) 인증할 수 있어야 하며, 최초 등록한 판매자 출처에만 국한되지 않아야 합니다.

이를 위해 보안 결제 확인의 중요한 기능 중 하나는 판매자(또는 다른 주체)가 신뢰 당사자를 대신하여 인증 절차를 시작할 수 있다는 것입니다. 신뢰 당사자는 자격 증명을 생성할 때 이러한 동작을 허용하도록 명시적으로 동의해야 합니다.

기능적으로 이 명세는 결제 수단을 PaymentRequest API에 새롭게 정의하고, WebAuthn 확장을 추가하여 [webauthn-3]에 결제 전용 데이터 구조와 기기 바인딩을 추가하고, 결제 환경에서 API를 호출할 수 있도록 기존 가정을 완화합니다.

1.1. 사용 사례

[webauthn-3]는 웹을 위한 일반적인 인증 기능을 제공하지만, 다음 사용 사례는 이 명세에서 정의하는 결제 전용 확장의 가치를 보여줍니다.

온라인 거래에서 암호화 기술을 기반으로 한 인증의 일반적인 사용 사례는 이미 널리 확립되어 있다고 가정합니다.

1.1.1. 거래 확인에 대한 암호학적 증거

많은 온라인 결제 시스템에서는 결제 수단을 발급하는 주체(예: 은행)가 인증을 통해 사기를 줄이려는 것이 일반적입니다. [webauthn-3]와 이 명세를 사용하면 인증기를 통해 판매자의 출처, 거래 금액 및 통화와 같은 중요한 결제 전용 정보에 암호학적으로 서명할 수 있습니다. 그러면 은행은 신뢰 당사자로서 서명된 결제 전용 정보를 검증하고 이를 결제 승인 여부를 결정하는 데 활용할 수 있습니다.

은행이 일반적인 [webauthn-3]를 사용한다면, 검증해야 할 결제 전용 정보는 WebAuthn의 challenge에 저장해야 합니다. 이로 인해 다음과 같은 문제가 발생합니다.

  1. 이는 재전송 공격을 방지하기 위한 challenge 필드를 본래 목적과 다르게 사용하는 것입니다.

  2. 이에 대한 명세가 없으므로 각 은행은 결제 전용 정보를 챌린지에 어떤 형식으로 구성하고 인코딩할지 자체적으로 정의해야 할 가능성이 높으며, 이로 인해 배포가 복잡해지고 파편화가 심화됩니다.

  3. 규제에 따라 사용자에게 결제 전용 정보가 표시되었고 사용자가 이에 동의했다는 증거가 요구될 수 있습니다. 일반적인 [webauthn-3]는 이러한 정보 표시를 지원하지 않습니다. challenge 필드에 저장된 정보와 관련된 사용자 경험이 정의되어 있지 않기 때문입니다.

이러한 제약으로 인해 보안 결제 확인에는 다음과 같은 동작이 도입되었습니다.

  1. challenge 필드는 일반적인 [webauthn-3]와 마찬가지로 재전송 공격을 방지하는 용도로만 사용됩니다.

  2. SPC는 결제 전용 정보의 형식을 정의합니다. 이를 통해 범용 검증 코드와 테스트 스위트를 개발할 수 있습니다.

  3. SPC는 악의적인 웹사이트(또는 신뢰할 수 있는 웹사이트에 악의적으로 삽입된 JavaScript 코드)가 우회할 수 없는 방식으로 사용자 에이전트가 결제 전용 정보를 사용자에게 표시했음을 보장합니다.

    • 결제 전용 정보는 CollectedClientData 사전에 포함되며, 이 사전은 JavaScript를 통해 변조할 수 없습니다.

    참고: 은행과 결제 생태계의 다른 이해관계자들은 현재 TLS, iframe 및 기타 웹 기능을 사용한 브라우저 기반 결제를 충분히 신뢰하고 있습니다. 현재 명세는 웹 결제의 보안성과 사용성을 향상하도록 설계되었습니다.

1.1.2. 판매자의 인증 제어

판매자는 결제 과정에서 사용자가 이탈하는 것을 방지하려 하며, 특히 인증에 따른 불편을 줄이고자 합니다. 사용자 인증에 [webauthn-3]를 사용하려는 신뢰 당사자 (예: 은행)는 일반적으로 iframe에서 인증을 수행합니다. 그러나 판매자는 신뢰 당사자가 인증 결과를 검증할 수 있도록 하면서도 사용자 인증 경험을 직접 관리하기를 선호합니다.

이러한 제약으로 인해 보안 결제 확인에는 다음과 같은 동작이 도입되었습니다.

이 기능은 신뢰 당사자가 더 이상 인증을 위한 자체 프런트엔드 사용자 경험을 구축할 필요가 없다는 추가적인 이점도 제공합니다. 대신 결제 서비스 제공업체가 판매자를 대신하여 이를 구축할 가능성이 높습니다.

참고: 인증 사용자 경험을 직접 제공하려는 신뢰 당사자는 여전히 iframe에서 SPC를 사용하여 이를 제공할 수 있습니다.

1.1.3. 기기 바인딩에 대한 암호학적 증거

결제 업계에서는 기기 소유를 나타내는 신호가 두 번째 인증 요소로서 중요한 역할을 합니다. WebAuthn은 하나의 자격 증명을 여러 기기에서 사용할 수 있는 동기화된 패스키를 지원합니다(웹 인증 § 1.2.1 다중 기기 자격 증명을 사용하는 소비자). 동기화는 로그인 사용 사례에서 사용자 경험을 개선하지만, 일부 규제 환경에서는 동기화된 패스키만으로 기기 소유 요구 사항을 충족하지 못한다는 우려가 제기되었습니다.

이러한 우려에 따라 사용자 에이전트가 생성하는 보조 공개 키와 비공개 키 쌍을 포함하게 되었습니다. 이 키 쌍의 비공개 키는 오직 하나의 기기에만 저장되고 해당 기기에서만 사용됩니다. 이러한 키와 SPC에서의 사용을 브라우저 바인딩 키라고 합니다.

1.2. API 사용 시나리오 예시

이 절에서는 보안 결제 확인의 몇 가지 시나리오와 이 API를 사용하는 데 필요한 해당 예제 코드를 살펴봅니다. 이러한 시나리오는 예시 흐름일 뿐이며 API 사용 범위를 제한하지 않습니다.

1.2.1. 결제 과정 중 등록

이는 사용자가 특정 판매자에서 결제하는 동안 발급 은행이 새로운 자격 증명을 생성하고 저장하는 최초 등록 흐름입니다.

  1. 사용자가 merchant.example에 방문하여 구매할 상품을 선택한 다음 결제 과정으로 진행합니다. 사용자는 결제 수단의 세부 정보를 입력하고 결제 의사를 표시합니다(예: "결제" 버튼을 누릅니다).

  2. 판매자는 결제 수단을 발급한 은행과 대역 외 방식(예: 다른 프로토콜 사용)으로 통신합니다. 발급 은행은 사용자 확인을 요청하고 판매자가 iframe에서 열 수 있도록 은행이 관리하는 URL을 제공합니다.

  3. 판매자는 bank.example을 가리키는 iframe을 열고 allow 속성을 "publickey-credentials-create"로 설정합니다.

  4. iframe에서 발급 은행은 기존 인증 수단(예: SMS 일회용 비밀번호)을 통해 사용자의 신원을 확인합니다. 확인 후 은행은 사용자에게 향후 결제를 위한 SPC 인증 등록을 안내합니다.

  5. 사용자가 동의하면(예: 은행의 사용자 인터페이스에서 "등록" 버튼 클릭) 은행은 iframe에서 코드를 실행합니다(아래 예제 참조).

  6. 사용자는 WebAuthn 등록 과정을 거칩니다. 새로운 자격 증명이 생성되어 발급 은행으로 반환되며, 은행은 이를 사용자 및 결제 수단과 연결된 서버 측 데이터베이스에 저장합니다.

  7. 확인이 완료되면 은행 iframe이 닫히고 판매자는 사용자의 결제 과정을 마무리합니다.

이러한 방식으로 사용자를 등록하는 예제 코드는 다음과 같습니다. 이 예제 코드는 Promise를 더 쉽게 읽고 처리할 수 있도록 async/await를 사용할 수 있다고 가정합니다.

if (!window.PublicKeyCredential) { /* 클라이언트가 지원하지 않습니다. 오류를 처리합니다. */ }

const publicKey = {
  // 챌린지는 은행 서버에서 생성하여 iframe으로 전송해야 합니다.
  challenge: new Uint8Array([21,31,105 /* 서버에서 생성한 29개의 추가 무작위 바이트 */]),

  // 신뢰 당사자:
  rp: {
    name: "Fancy Bank",
  },

  // 사용자:
  user: {
    // WebAuthn의 일부입니다. 이 정보는 SPC에서 필수는 아니지만
    // 은행 서버가 향후 거래에서 이 사용자를
    // 식별하는 데 사용할 수 있습니다. 동일한 사용자에게 서로 다른 값을
    // 사용하면 해당 사용자에 대해 여러 자격 증명이 생성될 수 있으며
    // 자격 증명 선택으로 인한 사용자 경험의 불편이 발생할 수 있습니다.
    id: Uint8Array.from(window.atob("MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII="), c=>c.charCodeAt(0)),
    name: "jane.doe@email.example",
    displayName: "Jane Doe",
  },

  // 이 예제에서 신뢰 당사자는 ES256 또는 RS256
  // 자격 증명을 허용하지만 ES256 자격 증명을 선호합니다.
  pubKeyCredParams: [
    {
      type: "public-key",
      alg: -7 // "ES256"
    },
    {
      type: "public-key",
      alg: -257 // "RS256"
    }
  ],

  authenticatorSelection: {
    userVerification: "required",
    residentKey: "required",
    authenticatorAttachment: "platform",
  },

  timeout: 360000,  // 6분

  // 이것이 SPC 자격 증명임을 나타냅니다. 현재 이 설정은
  // 브라우저가 이 자격 증명이 SPC와 관련되어 있음을 인식하는 데 필요합니다. 또한
  // 이 예제에 필요한 교차 출처 iframe에서의 자격 증명
  // 생성을 허용합니다.
  //
  // 향후 명세 버전에서는 이 확장이 필요하지 않을 수 있습니다.
  extensions: {
    "payment": {
      isPayment: true,
      // 허용되는 알고리즘의 선택적 목록입니다. 이 목록이 없거나 비어 있으면
      // pubKeyCredParams가 사용되며 기본값은 ES256과 RS256입니다. 이
      // 예제에서는 ES256과 RS256이 허용되고 RS256이 선호됩니다.
      browserBoundPubKeyCredParams: [
        {
          type: "public-key",
          alg: -257 // "RS256"
        },
        {
          type: "public-key",
          alg: -7 // "ES256"
        }
      ]
    }
  }
};

// 참고: 다음 호출은 인증기에 사용자 인터페이스를 표시하게 합니다.
try {
  const newCredentialInfo = await navigator.credentials.create({ publicKey });
  // 검증 및 등록을 위해 새로운 자격 증명 정보를 서버로 전송합니다.
} catch(err) {
  // 허용 가능한 인증기가 없거나 사용자가 동의를 거부했습니다. 적절히 처리합니다.
}

1.2.2. 판매자 사이트에서의 인증

이는 이미 등록된 자격 증명을 보유한 사용자가 거래를 수행할 때 발급 은행과 판매자가 보안 결제 확인을 사용하려는 경우의 흐름입니다.

  1. 사용자가 merchant.example에 방문하여 구매할 상품을 선택한 다음 결제 과정으로 진행합니다. 사용자는 결제 수단의 세부 정보를 입력하고 결제 의사를 표시합니다(예: "결제" 버튼을 누릅니다).

  2. 판매자는 결제 수단의 발급 은행과 대역 외 방식으로 통신합니다(예: 다른 프로토콜 사용). 발급 은행은 사용자 확인을 요청하는 동시에 API 사용에 필요한 정보를 제공하여 SPC를 허용한다는 사실을 판매자에게 알립니다. 이 정보에는 챌린지와 해당 사용자 및 결제 수단에 연결된 모든 자격 증명 ID가 포함됩니다.

  3. 판매자는 아래에 표시된 예제 코드를 실행합니다.

  4. 사용자는 SPC 사용자 인터페이스에 표시된 결제 전용 정보에 동의하고 이후 WebAuthn 인증 절차를 수행합니다. 서명된 암호문은 판매자에게 반환됩니다(브라우저 바인딩 키 출력도 AuthenticationExtensionsPaymentOutputs에 포함됩니다).

  5. 판매자는 서명된 암호문을 발급 은행에 대역 외 방식으로 전달합니다. 발급 은행은 암호문을 검증하여 사용자가 유효한지, 어떤 결제 전용 정보가 표시되었는지, 사용자가 거래에 동의했는지를 확인합니다. 발급 은행은 거래를 승인하고 판매자는 사용자의 결제 과정을 완료합니다. 발급 은행은 브라우저 바인딩 키의 공개 키인 browserBoundPublicKey를 저장합니다.

사용자를 인증하는 예제 코드는 다음과 같습니다. 이 예제 코드는 Promise를 더 쉽게 읽고 처리할 수 있도록 async/await를 사용할 수 있다고 가정합니다.

/* securePaymentConfirmationAvailability는 브라우저가 */
/* SPC를 지원하는지 나타냅니다. 사용자가 이 기기에서 사용할 수 있는 */
/* 자격 증명을 가지고 있는지는 나타내지 않습니다. */
const spcAvailable =
  (await window.PaymentRequest?.securePaymentConfirmationAvailability?.()) === 'available';
if (!spcAvailable) {
  /* 브라우저가 SPC를 지원하지 않으므로 판매자는 기존 흐름으로 대체해야 합니다. */
}

const request = new PaymentRequest([{
  supportedMethods: "secure-payment-confirmation",
  data: {
    // 은행에서 받은 자격 증명 ID 목록입니다.
    credentialIds,

    rpId: "fancybank.example",

    // 챌린지도 은행에서 받습니다.
    challenge: new Uint8Array([21,31,105 /* 은행에서 생성한 29개의 추가 무작위 바이트 */]),

    instrument: {
      displayName: "FancyBank 플래티넘 카드",
      details: "****1234 | 01/29",
      icon: "https://fancybank.example/card-art.png",
    },

    payeeName: "판매자 상점",
    payeeOrigin: "https://merchant.example",

    paymentEntitiesLogos: [
      {
        url: "https://fancybank.example/logo.png",
        label: "Fancy Bank",
      },
      {
        url: "https://securenetwork.example/logo.png",
        label: "Secure Network",
      },
    ],

    // 유효성 검사를 위해 호출자가 선호하는 로케일
    locale: ["en"],

    timeout: 360000,  // 6분

    // 허용되는 알고리즘의 선택적 목록이며 기본값은 ES256과 RS256입니다.
    // 이 예제에서는 ES256과 RS256을 허용하고 ES256을 선호합니다.
    // 브라우저 바인딩 키가 이미 존재하면 새로 생성하지 않으므로 이
    // 목록은 브라우저 바인딩 키를 새로 생성해야 하는 경우에만
    // 사용됩니다.
    browserBoundPubKeyCredParams: [
      {
        type: "public-key",
        alg: -7 // "ES256"
      },
      {
        type: "public-key",
        alg: -257 // "RS256"
      }
    ]
  }], {
    total: {
      label: "합계",
      amount: {
        currency: "USD",
        value: "5.00",
      },
    },
  });

try {
  const response = await request.show();
  await response.complete('success');

  // response.data는 발급 은행이 검증할 거래 데이터가 포함된
  // clientDataJSON을 가진 PublicKeyCredential입니다.

  /* 검증을 위해 response.data를 발급 은행에 전송합니다. */
} catch (err) {
  /* SPC를 사용할 수 없으므로 판매자는 기존 흐름으로 대체해야 합니다. */
}

2. 용어

SPC 자격 증명

이 명세에서 정의한 동작에 사용할 수 있는 WebAuthn 자격 증명입니다.

이 명세는 신뢰 당사자가 다른 인증 흐름(예: 로그인)에서 SPC 자격 증명을 사용할 수 있는지 또는 사용할 수 없는지를 제한하려는 의도가 없습니다.

참고: 이 명세의 현재 버전에서는 자격 증명을 자사 또는 제3자 컨텍스트에서 사용하려면 신뢰 당사자가 명시적으로 동의해야 합니다. 장기적으로는 모든 WebAuthn 자격 증명을 자사 컨텍스트(예: 신뢰 당사자의 도메인)에서 SPC에 사용할 수 있도록 하고, 제3자가 자격 증명을 사용하도록 허용할 때만 명시적 동의를 요구하려는 것입니다.

제3자 사용이 허용된 SPC 자격 증명

SPC 자격 증명 중 신뢰 당사자가 자격 증명 생성 시 자신 이외의 주체가 보안 결제 확인 인증에 해당 자격 증명을 사용할 수 있도록 명시적으로 동의한 신뢰 당사자의 자격 증명입니다.

SPC 자격 증명의 제3자 사용 허용 여부를 사용자에게 알리지 않고 확인하는 단계

사용자 에이전트가 신뢰 당사자 식별자와 자격 증명 ID를 받아, 해당 ID가 나타내는 자격 증명이 제3자 사용이 허용된 SPC 자격 증명인지 사용자와 상호 작용하지 않고 확인하는 아직 정의되지 않은 프로세스입니다.

참고: WebAuthn 이슈 1667을 참조하시기 바랍니다.

현재 기기에서 자격 증명을 사용할 수 있는지 사용자에게 알리지 않고 확인하는 단계

사용자 에이전트가 신뢰 당사자 식별자와 자격 증명 ID를 받아, 해당 자격 증명 ID가 나타내는 자격 증명을 현재 기기에서 사용할 수 있는지(즉, WebAuthn Get 호출의 일부로 성공적으로 사용할 수 있는지) 사용자와 상호 작용하지 않고 확인하는 아직 정의되지 않은 프로세스입니다.

이를 통해 사용자 에이전트는 사용자가 거래를 성공적으로 완료할 가능성이 있을 때만 거래 사용자 인터페이스를 조건부로 표시할 수 있습니다.

참고: 이 속성을 지원하려면 SPC 자격 증명이 검색 가능해야 할 가능성이 높으며, 따라서 이 명세에서는 현재 이를 요구 사항으로 규정합니다.

참고: 이 속성은 WebAuthn 조건부 UI 제안에 필요한 속성과 매우 유사합니다. 두 기능 모두 동일한 기반 API로 지원할 수 있을 것으로 보입니다.

브라우저 바인딩 키

WebAuthn 자격 증명과 함께 거래 세부 정보에 서명하며 사용자 에이전트에 의해 단일 기기에 바인딩되는 공개 키와 비공개 키 키 쌍입니다. 참고: 이 기능의 초기 구현이 브라우저용으로 만들어졌기 때문에 이러한 이름이 선택되었지만, 이 개념은 모든 사용자 에이전트에 적용할 수 있습니다.

키 쌍

키 쌍은 공개 키와 비공개 키로 구성된 구조체이며, 두 키의 유형은 구현 정의에 따릅니다.

참고: 공개 키와 비공개 키는 IANA COSE 알고리즘 등록부 [IANA-COSE-ALGS-REG]에 명시된 암호화 알고리즘의 알고리즘별 매개변수입니다.

참고: 공개 키 부분은 등록 시 CollectedClientAdditionalPaymentRegistrationData.browserBoundPublicKey에서 반환되고, 결제 어서션 시에는 CollectedClientAdditionalPaymentData.browserBoundPublicKey에서 반환됩니다.

참고: 비공개 키는 BrowserBoundSignature.signature에 포함되는 암호학적 서명을 생성하는 데 사용됩니다. 사용자 에이전트는 비공개 키를 내보내지 않으며 기기의 보안 요소에 비공개 키를 저장할 수 있습니다.

3. 등록

보안 결제 확인에 사용자를 등록하려면 신뢰 당사자는 navigator.credentials.create()를 호출할 때 payment WebAuthn 확장을 지정해야 합니다.

테스트

참고: 이 명세에서는 조건부 UI가 없는 경우에도 브라우저가 SPC 자격 증명 ID를 캐시할 수 있도록 확장을 정의합니다. 향후 WebAuthn 버전에서 이 기능을 사용할 수 있게 되면 SPC에서 해당 확장에 대한 요구 사항을 제거할 수 있습니다. 확장을 포함한 SPC 자격 증명도 그 밖의 측면에서는 완전한 WebAuthn 자격 증명입니다.

참고: 등록 시 웹 인증에서는 name과 displayName이 모두 필요하지만, user 멤버의 정의에 따르면 구현에서 이후 인증 절차 중 어느 값도 표시할 의무는 없습니다. 2023년 10월 기준으로 두 값 중 name이 더 일관되게 표시됩니다. 개발자는 계속해서 구현 현황을 살펴보아야 합니다.

4. 인증 - 보안 결제 확인 결제 수단

보안 결제 확인을 통해 결제를 인증하기 위해 이 명세는 다음을 정의합니다.

  1. 주어진 결제의 인증 요청을 처리하는 결제 처리기인 보안 결제 확인 결제 처리기입니다.

  2. 이 결제 처리기에 대한 표준화된 결제 수단 식별자인 "secure-payment-confirmation"입니다.

보안 결제 확인 결제 처리기는 사용자에게 거래를 확인받은 후 인증 절차를 수행하여 사용자를 인증하고 인증 절차를 나타내는 서명된 데이터 블롭을 생성합니다.

개략적으로 보안 결제 확인의 인증은 [webauthn-3]와 유사하지만 한 가지 중요한 개념적 차이가 있습니다. 보안 결제 확인은 제3자(예: 판매자)가 신뢰 당사자를 대신하여 인증 절차를 시작하고, 명시되지 않은 다른 채널을 통해 신뢰 당사자로부터 받은 자격 증명을 전달할 수 있도록 합니다. § 1.1.2 판매자의 인증 제어를 참조하시기 바랍니다.

4.1. [payment-method-id]에 등록

[payment-method-id]의 표준화된 결제 수단 등록부에 다음을 추가합니다.

"secure-payment-confirmation"

보안 결제 확인 명세입니다.

4.2. Payment Request 생성자 수정

PaymentRequest 객체의 생성자에 대한 단계에서 4.3단계 뒤에 새 단계를 추가합니다.

  1. 결제 수단 처리: [하위 단계 1~3 생략]

    1. seenPMIs에 "secure-payment-confirmation"이 포함되어 있고 seenPMIs의 크기가 1보다 크면 RangeError를 발생시킵니다.

4.3. 사용자 활성화 요구 사항 수정

PaymentRequest.show() 메서드의 단계에서 2단계와 3단계를 수정합니다.

  1. request의 관련 전역 객체에 일시적 활성화가 없으면 사용자 에이전트는 다음을 수행할 수 있습니다(MAY).

    1. "SecurityError" DOMException으로 거부된 Promise를 반환합니다.

  2. 그렇지 않으면 관련 전역 객체의 사용자 활성화를 소비합니다.

참고: 이를 통해 사용자 에이전트는 사용자 활성화를 요구하지 않을 수 있습니다. 예를 들어 리디렉션 시 사용자 활성화가 존재하지 않을 수 있는 리디렉션 인증 흐름을 지원할 수 있습니다. 보안 고려 사항은 § 11.4 사용자 활성화 요구 사항의 부재를 참조하시기 바랍니다.

4.4. SecurePaymentConfirmationRequest 사전

dictionary SecurePaymentConfirmationRequest {
    required BufferSource challenge;
    required USVString rpId;
    required sequence<BufferSource> credentialIds;
    required PaymentCredentialInstrument instrument;
    unsigned long timeout;
    USVString payeeName;
    USVString payeeOrigin;
    sequence<> paymentEntitiesLogos;
    AuthenticationExtensionsClientInputs extensions;
    sequence<PublicKeyCredentialParameters> browserBoundPubKeyCredParams;
    sequence<USVString> locale;
    boolean showOptOut;
};

SecurePaymentConfirmationRequest 사전에는 다음 멤버가 포함됩니다.

challenge

재전송 공격을 방지하기 위해 신뢰 당사자가 서버 측에서 생성하는 무작위 챌린지입니다.

rpId

자격 증명의 신뢰 당사자 식별자입니다.

credentialIds

주어진 결제 수단에 대한 자격 증명 식별자 목록입니다.

instrument

등록 중 표시되고 거래 세부 정보와 함께 서명될 결제 수단의 이름과 아이콘에 대한 설명입니다.

timeout

거래 세부 정보에 서명하는 요청이 시간 초과되기까지의 밀리초 수입니다. 최대 1시간입니다. 기본값과 허용되는 값의 범위는 사용자 에이전트가 정의합니다. 웹 인증에서는 시간 초과에 대한 추가 지침을 제공합니다.

payeeName

이 SPC 호출의 대상인 수취인(예: 판매자)의 표시 이름입니다. 선택 사항이며 payeeOrigin과 함께 또는 이를 대신하여 제공할 수 있습니다.

payeeOrigin

이 SPC 호출의 대상인 수취인(예: 판매자)의 출처입니다. 선택 사항이며 payeeName과 함께 또는 이를 대신하여 제공할 수 있습니다.

paymentEntitiesLogos

이 SPC 호출의 대상인 결제를 지원하는 주체를 나타내는 로고의 선택적 목록이며, 표시 우선순위가 높은 순서대로 나열됩니다. 사용자 에이전트는 일부 또는 모든 로고를 표시할 의무가 없습니다. § 4.9 결제 가능 여부 확인 단계를 참조하시기 바랍니다.

참고: 이 명세에서 로고의 정확한 렌더링 방식을 지정하지 않은 것은 의도적입니다. 이는 렌더링에 대한 사용자 에이전트의 제어권을 유지하고, 여러 고려 사항과 제약에 따라 정보를 최적으로 표시할 수 있도록 하기 위한 것입니다. 하지만 목록 내 로고의 순서는 중요하므로 개발자는 특정 순서가 원하는 결과를 제공하는지 실험할 수 있습니다.

extensions

전달된 자격 증명에 사용해야 하는 모든 WebAuthn 확장입니다. 호출자는 결제 확장을 지정할 필요가 없으며 자동으로 추가됩니다.

참고: 제3자 SPC 호출에서는 이 사전이 비어 있지 않으면 예외가 발생합니다. 이는 비공개 데이터를 저장할 수 있는 신뢰 당사자의 확장에 대한 공격을 방지하기 위한 것입니다. § 11.1.3 신뢰 당사자에게만 허용되는 WebAuthn 확장을 참조하시기 바랍니다.

browserBoundPubKeyCredParams

브라우저 바인딩 키에 사용되는 암호화 알고리즘의 유형을 제한하는 허용된 자격 증명 유형 목록입니다.

참고: 이 멤버는 브라우저 바인딩 키를 새로 생성해야 하는 경우에만 사용됩니다.

locale

호출자의 로케일 기본 설정을 나타내는 언어 태그의 선택적 목록입니다([BCP47] 참조). 이 값에 하나 이상의 언어 태그가 설정되면 사용자 에이전트는 목록의 태그 중 보안 결제 확인 대화 상자에서 사용될 언어와 일치하는 태그가 있는지 확인합니다. 제공된 언어 태그 중 일치하는 것이 없으면 사용자 에이전트는 PaymentRequest.canMakePayment()가 반환하는 Promise를 "NotSupportedError" DOMException으로 거부합니다.

showOptOut

거래 확인 사용자 경험 중 사용자에게 거부를 선택할 기회를 제공할지 여부입니다. 선택 사항이며 기본값은 false입니다.

4.5. 결제 수단 추가 데이터 유형

이 결제 수단의 결제 수단 추가 데이터 유형은 SecurePaymentConfirmationRequest입니다.

4.6. 보안 결제 확인의 사용 가능 여부 확인

개발자가 보안 결제 확인의 사용 가능 여부를 간단하게 확인할 수 있도록 PaymentRequest에 정적 API를 추가합니다. 이 메서드인 securePaymentConfirmationAvailability()는 보안 결제 확인을 사용할 수 있는지, 사용할 수 없다면 그 근본적인 이유를 어느 정도 나타내는 열거형 멤버를 반환합니다. 열거형 출력을 사용하는 목적은 개발자가 사용자의 인증 옵션을 안내하고 설명하는 데 도움을 주기 위한 것입니다.

enum SecurePaymentConfirmationAvailability {
  "available",
  "unavailable-unknown-reason",
  "unavailable-feature-not-enabled",
  "unavailable-no-permission-policy",
  "unavailable-no-user-verifying-platform-authenticator",
};

partial interface PaymentRequest {
    static Promise<SecurePaymentConfirmationAvailability> securePaymentConfirmationAvailability();
};

SecurePaymentConfirmationAvailability 열거형에는 다음 멤버가 포함됩니다.

available

사용자 에이전트가 호출 프레임에서 보안 결제 확인 API를 사용할 수 있다고 판단함을 나타냅니다.

참고: 이 결과는 특정 SPC 자격 증명을 사용할 수 있는지 또는 향후 사용할 수 있게 되는지를 나타내지 않습니다.

unavailable-unknown-reason

알 수 없는 이유로 호출 프레임에서 보안 결제 확인 API를 사용할 수 없음을 나타냅니다. 사용자 에이전트는 사용자 개인정보를 보호하기 위해 더 구체적인 이유 대신 항상 이 결과를 반환하도록 선택할 수 있습니다(MAY).

unavailable-feature-not-enabled

기능이 활성화되지 않아 호출 프레임에서 보안 결제 확인 API를 사용할 수 없음을 나타냅니다.

unavailable-no-permission-policy

프레임에 "payment" 권한 정책이 없어서 호출 프레임에서 보안 결제 확인 API를 사용할 수 없음을 나타냅니다.

unavailable-no-user-verifying-platform-authenticator

사용할 수 있는 사용자 검증 플랫폼 인증기가 없기 때문에 호출 프레임에서 보안 결제 확인 API를 사용할 수 없음을 나타냅니다.

참고: 이 정보는 isUserVerifyingPlatformAuthenticatorAvailable를 호출하여 얻을 수도 있지만, 개발자의 편의를 위해 이 API에도 포함되었습니다.

주어진 Document document에서 securePaymentConfirmationAvailability()를 호출하면 사용자 에이전트는 아래 단계를 수행해야 합니다. 사용자 에이전트는 사용자의 개인정보를 보호해야 하거나 사용자 에이전트 고유의 이유로 단계를 완료할 수 없는 경우 언제든지 "unavailable-unknown-reason"을 반환하도록 선택할 수 있습니다.

  1. 사용자 에이전트가 보안 결제 확인을 지원하지 않거나, 지원하지만 사용자 에이전트 고유의 메커니즘을 통해 기능이 비활성화된 경우 "unavailable-feature-not-enabled"을 반환합니다.

  2. "payment" 권한 정책이 document에 대해 활성화되지 않은 경우 "unavailable-no-permission-policy"을 반환합니다.

  3. 사용할 수 있는 사용자 검증 플랫폼 인증기가 없으면 "unavailable-no-user-verifying-platform-authenticator"을 반환합니다.

  4. document에서 보안 결제 확인 기능을 호출했을 때 작동하지 않는 다른 이유가 있다면 "unavailable-unknown-reason"을 반환합니다.

  5. "available"을 반환합니다.

이 API를 사용하면 개발자는 SPC 흐름을 시작할지 결정할 때 다음과 같이 확인할 수 있습니다.

const spcAvailable =
    PaymentRequest &&
    PaymentRequest.securePaymentConfirmationAvailability &&
    await PaymentRequest.securePaymentConfirmationAvailability() === 'available';

참고: SPC 기능 감지에는 이미 생성된 PaymentRequest 객체에서 canMakePayment를 호출하는 대신 정적 securePaymentConfirmationAvailability 메서드를 사용하는 것이 권장됩니다.

참고: 이 API의 개인정보 보호 고려 사항은 § 12.5 securePaymentConfirmationAvailability를 통한 핑거프린팅을 참조하시기 바랍니다.

4.7. 보안 결제 확인 기능의 사용 가능 여부

개발자가 보안 결제 확인의 기능을 사용할 수 있는지 확인할 수 있도록 PaymentRequest에 정적 API를 추가합니다. 이 메서드인 getSecurePaymentConfirmationCapabilities()는 기능 키를 불리언 값에 매핑하는 레코드를 반환합니다.

partial interface PaymentRequest {
    static Promise<SecurePaymentConfirmationCapabilities> getSecurePaymentConfirmationCapabilities();
};

typedef record<DOMString, boolean> SecurePaymentConfirmationCapabilities;

SecurePaymentConfirmationCapabilities의 키는 사전식 오름차순으로 정렬되어야 합니다(MUST). 키 집합에는 SecurePaymentConfirmationCapability의 열거형 값 집합이 포함되는 것이 좋지만(SHOULD), 사용자 에이전트는 필요하다고 판단하는 경우 키를 생략할 수 있습니다(MAY). § 12.6 getSecurePaymentConfirmationCapabilities를 통한 핑거프린팅을 참조하시기 바랍니다.

특정 기능의 값이 true이면 해당 기능이 현재 이 사용자 에이전트의 보안 결제 확인 구현에서 지원되는 것으로 알려져 있습니다.

특정 기능의 값이 false이면 해당 기능이 현재 이 사용자 에이전트의 보안 결제 확인 구현에서 지원되지 않는 것으로 알려져 있습니다.

어떤 기능이 키로 존재하지 않으면 이 사용자 에이전트의 보안 결제 확인 구현에서 해당 기능의 지원 여부를 알 수 없습니다.

이 API를 사용하면 개발자는 보안 결제 확인 흐름을 시작할지 결정할 때 다음과 같이 특정 기능의 지원 여부를 확인할 수 있습니다.

if (PaymentRequest && PaymentRequest.getSecurePaymentConfirmationCapabilities) {
    const capabilities = await PaymentRequest.getSecurePaymentConfirmationCapabilities();
    if (capabilities.browserBoundKeyHardware) {
        // SPC API 사용 시 하드웨어 기반 BBK를 사용할 수 있습니다.
    }
}

참고: 이 API의 개인정보 보호 고려 사항은 § 12.6 getSecurePaymentConfirmationCapabilities를 통한 핑거프린팅을 참조하시기 바랍니다.

4.7.1. SecurePaymentConfirmationCapability 열거형

enum SecurePaymentConfirmationCapability {
  "browserBoundKeyHardware",
};

이 열거형은 개발자가 사용자에게 특정 작업 흐름과 경험을 제공하기 위해 평가할 수 있는 제한된 보안 결제 확인 기능 집합을 정의합니다.

browserBoundKeyHardware

보안 결제 확인 API가 기기의 하드웨어 보안 요소에 저장된 브라우저 바인딩 키를 사용할 수 있음을 나타냅니다.

자세한 내용은 § 6 브라우저 바인딩 키 저장소를 참조하시기 바랍니다.

4.8. 결제 수단 데이터 유효성 검사 단계

이 결제 수단의 결제 수단 데이터 유효성 검사 단계는 입력 PaymentRequest request와 SecurePaymentConfirmationRequest data에 대해 다음과 같습니다.

테스트
  1. data["credentialIds"]가 비어 있으면 RangeError를 발생시킵니다.

  2. data["credentialIds"]의 각 id에 대해:

    1. id가 비어 있으면 RangeError를 발생시킵니다.

  3. data["challenge"]가 null이거나 비어 있으면 TypeError를 발생시킵니다.

  4. data["instrument"]["displayName"]가 비어 있으면 TypeError를 발생시킵니다.

  5. data["instrument"]["icon"]이 비어 있으면 TypeError를 발생시킵니다.

  6. data["instrument"] ["icon"]에 대해 URL 파서를 실행합니다. 결과가 실패이면 TypeError를 발생시킵니다.

  7. data["instrument"]["details"]가 존재하지만 비어 있으면 TypeError를 발생시킵니다.

  8. data["rpId"]가 유효한 도메인이 아니면 TypeError를 발생시킵니다.

  9. data["payeeName"]과 data["payeeOrigin"]이 모두 생략되었으면 TypeError를 발생시킵니다.

  10. data["payeeName"]이나 data["payeeOrigin"] 중 하나가 존재하지만 비어 있으면 TypeError를 발생시킵니다.

  11. data["payeeOrigin"]이 존재하면:

    1. parsedURL을 data["payeeOrigin"]에 대해 URL 파서를 실행한 결과로 설정합니다.

    2. parsedURL이 실패이면 TypeError를 발생시킵니다.

    3. parsedURL의 스킴이 "https"가 아니면 TypeError를 발생시킵니다.

  12. data["paymentEntitiesLogos"]가 존재하고 비어 있지 않으면:

    1. data["paymentEntitiesLogos"]의 각 logo에 대해:

      1. logo["url"]이 비어 있으면 TypeError를 발생시킵니다.

      2. logo["url"]에 대해 URL 파서를 실행합니다. 결과가 실패이면 TypeError를 발생시킵니다.

      3. logo["label"]이 비어 있으면 TypeError를 발생시킵니다.

  13. data["extensions"]가 존재하고 비어 있지 않으며, data["rpId"]가 request의 관련 설정 객체의 출처가 아니면 TypeError를 발생시킵니다.

  14. data["locale"]이 존재하고 비어 있지 않으면:

    1. dialogLanguageTag를 보안 결제 확인 대화 상자에서 사용하는 언어 태그로 설정합니다.

    2. matched를 false로 설정합니다.

    3. data["locale"]의 각 tag에 대해:

      1. tag가 올바른 형식의 [BCP47] 언어 태그가 아니면 TypeError를 발생시킵니다.

      2. tag와 dialogLanguageTag가 모두 둘 이상의 언어 하위 태그를 포함하고, tag와 dialogLanguageTag가 ASCII 대소문자를 구분하지 않는 방식으로 일치하면 matched를 true로 설정하고 반복을 종료합니다.

      3. tag 또는 dialogLanguageTag 중 적어도 하나가 기본 언어 하위 태그로만 구성되고([BCP47] 참조), 두 기본 언어 하위 태그가 ASCII 대소문자를 구분하지 않는 방식으로 일치하면 matched를 true로 설정하고 반복을 종료합니다.

    4. matched가 false이면 "NotSupportedError" DOMException을 발생시킵니다.

    참고: 일치하는 항목이 없을 때 NotSupportedError를 반환하면 호출자는 대화 상자의 로케일이 요청된 로케일 기본 설정 중 어느 것과도 일치하지 않음을 알 수 있습니다.

    참고: 여기에서는 일반적인 언어 협상을 적용하지 않습니다. 협상 결과의 언어나 로케일을 보안 결제 확인 대화 상자에 사용하지 않기 때문입니다.

    참고: locale은 특정 입력 멤버와 연결된 언어 또는 방향 메타데이터와 다릅니다. 특정 문자열 값에 대한 단언이 아니라 호출자가 요청한 현지화된 경험을 나타내기 때문입니다. 자세한 내용은 § 14 국제화 고려 사항을 참조하시기 바랍니다.

4.9. 결제 가능 여부 확인 단계

이 결제 수단의 결제 가능 여부 확인 단계는 입력 SecurePaymentConfirmationRequest data에 대해 다음과 같습니다.

테스트
  1. data["payeeOrigin"]이 존재하면:

    1. parsedURL을 data["payeeOrigin"]에 대해 URL 파서를 실행한 결과로 설정합니다.

    2. parsedURL이 실패가 아님을 단언합니다.

    3. parsedURL의 스킴이 "https"임을 단언합니다.

    참고: 이러한 사전 조건은 앞서 결제 수단 데이터의 유효성을 검사하는 단계에서 확인되었습니다.

    1. data["payeeOrigin"]을 parsedURL의 직렬화된 값으로 설정합니다. 출처의 직렬화된 값입니다.

  2. 아이콘의 이미지 리소스를 가져옵니다. 이때 «["src" → data["instrument"]["icon"]]» 를 image로 전달합니다. 실패하면:

    1. data["instrument"]["iconMustBeShown"]이 true이면 false를 반환합니다.

    2. 그렇지 않으면 data["instrument"]["icon"]을 빈 문자열로 설정합니다.

      참고: 이를 통해 RP는 지정된 아이콘이 표시되지 않았음을 알 수 있습니다. 출력 instrument에 빈 아이콘 문자열이 포함되기 때문입니다.

    참고: 일치하는 자격 증명이 있는지 여부와 관계없이 이미지 리소스를 가져와야 합니다. 이는 자격 증명의 존재 여부를 탐색하려는 시도를 방지하기 위한 것입니다.

  3. 선택적으로 사용자 에이전트는 data["paymentEntitiesLogos"]에서 목록의 끝부터 시작 방향으로 항목을 제거할 수 있습니다.

    참고: 이를 통해 사용자 에이전트는 표시할 로고의 수를 제어하면서 로고가 호출자에게 표시 우선순위의 내림차순으로 지정되었다는 의미를 유지할 수 있습니다.

  4. data["paymentEntitiesLogos"]의 각 logo에 대해:

    1. logo의 이미지 리소스를 가져옵니다. 이때 logo에 대해 «["src" → logo["url"]]» 를 image로 전달하고 결과를 디코딩합니다.

    2. 가져오기 또는 디코딩이 실패하면 logo["url"]을 빈 문자열로 설정합니다.

      참고: 이를 통해 RP는 지정된 로고가 표시되지 않았음을 알 수 있습니다. 출력 paymentEntitiesLogos 시퀀스에서 해당 로고의 URL 문자열이 비어 있기 때문입니다.

    참고: 일치하는 자격 증명이 있는지 여부와 관계없이 로고 리소스를 가져와야 합니다. 이는 자격 증명의 존재 여부를 탐색하려는 시도를 방지하기 위한 것입니다.

  5. data["credentialIds"]의 각 id에 대해:

    1. 현재 기기에서 자격 증명을 사용자에게 알리지 않고 사용할 수 있는지 확인하는 단계를 실행합니다. 이때 data["rpId"]와 id를 전달합니다. 결과가 false이면 data["credentialIds"]에서 id를 제거합니다.

    2. data["rpId"]가 request의 관련 설정 객체의 출처가 아니라면 SPC 자격 증명의 제3자 사용 허용 여부를 사용자에게 알리지 않고 확인하는 단계를 실행합니다. 이때 data["rpId"]와 id를 전달합니다. 결과가 false이면 data["credentialIds"]에서 id를 제거합니다.

  6. true를 반환합니다.

4.10. 거래 확인 사용자 경험 표시

PaymentRequest.show()가 호출되고 보안 결제 확인 결제 처리기가 선택되면(해당 알고리즘의 19~24단계), 사용자 에이전트는 사용자가 진행 여부와 진행 방법을 선택할 수 있는 사용자 인터페이스를 반드시 제공해야 합니다.

4.10.1. 사용자에게 표시되는 정보

사용자 에이전트 구현의 선택을 제한하지 않기 위해 이 명세에서는 특정 사용자 인터페이스를 표시하도록 요구하지 않습니다. 그러나 신뢰 당사자가 CollectedClientPaymentData에 포함된 정보를 신뢰할 수 있도록, 사용자 에이전트는 다음 정보가 사용자에게 전달되고 인증에 대한 사용자의 동의가 수집되도록 반드시 보장해야 합니다.

showOptOut이 true이면 사용자 에이전트는 사용자가 주어진 신뢰 당사자에 대한 절차에서 탈퇴할 의사를 표시할 기회를 반드시 제공해야 합니다.

테스트

4.10.2. 거래 확인 사용자 경험의 결과

사용자 에이전트는 사용자가 진행 여부와 진행 방법에 대해 다음 옵션 중 하나를 선택할 수 있도록 반드시 허용해야 합니다.

사용자가 SPC 자격 증명을 사용하여 인증하고 결제를 진행하려는 경우,

사용자가 상호 작용하고 있는 PaymentRequest에 대해 사용자가 결제 요청을 수락하는 알고리즘을 실행합니다.

사용자가 결제를 진행하려고 하지만 data["credentialIds"]가 비어 있어 사용할 수 없거나 SPC 자격 증명을 사용하고 싶지 않은 경우,

다음 단계를 실행합니다.

  1. data["credentialIds"]를 빈 목록으로 설정합니다.

    참고: 이로 인해 PaymentRequest.show()의 Promise가 "NotAllowedError" DOMException으로 거부됩니다. § 4.11 결제 요청에 응답하는 단계를 참조하시기 바랍니다.

  2. 사용자가 상호 작용하고 있는 PaymentRequest에 대해 사용자가 결제 요청을 수락하는 알고리즘을 실행합니다.

테스트
사용자가 결제를 진행하고 싶지 않은 경우,

사용자가 상호 작용하고 있는 PaymentRequest에 대해 사용자가 결제 요청을 중단하는 알고리즘을 실행합니다.

참고: 이로 인해 PaymentRequest.show()의 Promise가 "AbortError" DOMException으로 거부됩니다.

사용자가 주어진 신뢰 당사자에 대한 절차에서 탈퇴하려는 경우,

PaymentRequest.show()를 "OptOutError" DOMException으로 거부합니다. § 12.7 사용자 탈퇴를 참조하시기 바랍니다.

참고: 이 옵션은 showOptOut이 true로 설정된 경우에만 사용자에게 제공해야 합니다.

4.10.3. 테스트 자동화 지원

현재 거래 자동화 모드가 "none"이 아니면 사용자 에이전트는 먼저 자동화 컨텍스트에 있는지 확인하는 것이 좋습니다( WebDriver의 보안 고려 사항 참조). 그런 다음 사용자 에이전트는 앞서 설명한 정보 전달과 사용자 동의 수집을 건너뛰고, 대신 현재 거래 자동화 모드의 값에 따라 다음을 수행하는 것이 좋습니다.

"autoAccept"

사용자가 거래 세부 정보를 확인하고 수락한 것처럼 동작합니다.

"autoChooseToAuthAnotherWay"

사용자가 거래 세부 정보를 확인하고 수락했지만 인증에 SPC 자격 증명을 사용하고 싶지 않다고 표시한 것처럼 동작합니다. data["credentialIds"]가 비어 있으면 "autoAccept"와 동일합니다.

"autoReject"

사용자가 거래 세부 정보를 확인하고 거부한 것처럼 (즉, 거래를 계속하고 싶지 않은 것처럼) 동작합니다.

"autoOptOut"

사용자가 거래 세부 정보를 확인하고 탈퇴 의사를 표시한 것처럼 동작합니다.

4.11. 결제 요청에 응답하는 단계

이 결제 수단의 결제 요청에 응답하는 단계는 주어진 PaymentRequest request와 SecurePaymentConfirmationRequest data에 대해 다음과 같습니다.

참고: 이 단계는 사용자가 거래 확인 사용자 경험을 수락한 경우에만 실행됩니다. 사용자가 결제 요청을 수락하는 알고리즘에서 호출됩니다.

  1. data["credentialIds"]가 비어 있으면 "NotAllowedError" DOMException을 발생시킵니다. 이는 사용자가 SPC를 사용하여 인증할 수 없거나 사용하고 싶지 않은 경우에도 인증 절차의 개인정보 보호를 유지하기 위한 것입니다.

    참고: 여기서 예외를 발생시키면 PaymentRequest.show()의 Promise가 "NotAllowedError" DOMException으로 거부됩니다.

  2. topOrigin을 request의 관련 설정 객체의 최상위 출처로 설정합니다.

  3. payment를 새 AuthenticationExtensionsPaymentInputs 사전으로 설정하며, 해당 필드는 다음과 같습니다.

    isPayment

    불리언 값 true입니다.

    rpId

    data["rpId"]

    topOrigin

    topOrigin

    payeeName

    data["payeeName"]이 존재하면 해당 값을 사용하고, 그렇지 않으면 생략합니다.

    payeeOrigin

    data["payeeOrigin"]이 존재하면 해당 값을 사용하고, 그렇지 않으면 생략합니다.

    paymentEntitiesLogos

    data["paymentEntitiesLogos"]이 존재하고 비어 있지 않으면 해당 값을 사용하고, 그렇지 않으면 생략합니다.

    이 명세의 현재 버전은 각 PaymentEntityLogo에 대해 하나의 URL만 지원하므로 데이터 구조를 그대로 복사하고 서명하는 것만으로 사용자에게 표시된 내용을 나타내기에 충분합니다. 향후 이 명세의 버전에서는 다크 모드를 기본적으로 지원하는 등의 목적으로 각 PaymentEntityLogo에 여러 URL을 추가할 수 있습니다. 그렇게 되면 명세는 특정 PaymentEntityLogo에 대해 어떤 URL이 표시되었는지 신뢰 당사자에게 알려야 합니다.

    total

    request.[[details]]["total"]

    instrument

    data["instrument"]

    browserBoundPubKeyCredParams

    data["browserBoundPubKeyCredParams"]

  4. extensions를 새 AuthenticationExtensionsClientInputs 사전으로 설정합니다. 해당 payment 멤버는 payment로 설정하고, 다른 멤버는 data["extensions"]에서 설정합니다.

  5. publicKeyOpts를 새 PublicKeyCredentialRequestOptions 사전으로 설정하며, 필드는 다음과 같습니다.

    challenge

    data["challenge"]

    timeout

    data["timeout"]

    rpId

    data["rpId"]

    userVerification

    required

    extensions

    extensions

    참고: 이 알고리즘은 userVerification의 값을 "required"로 고정합니다. 이는 Chrome의 초기 구현에서 지원하는 값이기 때문입니다. 현재의 제한 사항은 변경될 수 있습니다. 워킹 그룹은 구현자가 다른 값(예: "preferred" 또는 "discouraged")의 지원으로 이점을 얻을 수 있는 사용 사례를 공유하기를 요청합니다.

  6. data["credentialIds"]의 각 id에 대해:

    1. descriptor를 새 PublicKeyCredentialDescriptor 사전으로 설정하며, 필드는 다음과 같습니다.

      type

      public-key

      id

      id

      transports

      유일한 멤버가 internal인 길이 1의 시퀀스입니다.

    2. descriptor를 publicKeyOpts["allowCredentials"]에 추가합니다.

  7. outputCredential을 «["publicKey" → publicKeyOpts]»를 전달하여 자격 증명 요청 알고리즘을 실행한 결과로 설정합니다.

    참고: Chrome의 초기 구현은 전체 data.credentialIds 목록을 자격 증명 요청에 전달하지 않습니다. 대신 목록에서 현재 기기와 일치하는 자격 증명 하나를 선택하여 그것만 전달합니다.

    참고: 이는 [webauthn-3]의 Get 동작을 트리거합니다.

  8. outputCredential을 반환합니다.

5. WebAuthn 확장 - "payment"

이 클라이언트 등록 확장과 인증 확장은 각각 자격 증명이 보안 결제 확인을 위해 생성되거나 사용되고 있음을 나타냅니다.

등록 시 이 확장을 통해 브라우저는 보안 결제 확인 자격 증명 ID를 식별하고 캐시할 수 있습니다. 인증 시 이 확장을 통해 제3자가 신뢰 당사자를 대신하여 인증 절차를 수행할 수 있으며, 서명된 암호문에 거래 정보도 추가됩니다.

특히 웹사이트는 이 확장을 사용하여 navigator.credentials.get()를 직접 호출해서는 안 됩니다. 인증 시 이 확장에는 "secure-payment-confirmation" 결제 수단을 지정한 PaymentRequest를 통해서만 접근할 수 있습니다.

참고: 이전에는 payment 확장이 교차 출처 iframe에서 자격 증명을 생성할 수 있도록 허용했습니다. 하지만 WebAuthn PR #1801 이후 WebAuthn에서는 이 동작을 기본적으로 허용합니다.

테스트

이 테스트는 명세의 특정 행에 직접 대응하지 않고, 대신 교차 출처 iframe 내부에서 인증을 시작할 수 있는지 확인합니다. 이 동작은 이를 금지하는 규정이 없다는 사실로 명시됩니다.


확장 식별자

payment

적용 가능한 작업

등록 및 인증

클라이언트 확장 입력
partial dictionary AuthenticationExtensionsClientInputs {
  AuthenticationExtensionsPaymentInputs payment;
};

dictionary AuthenticationExtensionsPaymentInputs {
  boolean isPayment;
  sequence<PublicKeyCredentialParameters> browserBoundPubKeyCredParams;

  // 인증에만 사용됩니다.
  USVString rpId;
  USVString topOrigin;
  USVString payeeName;
  USVString payeeOrigin;
  sequence<PaymentEntityLogo> paymentEntitiesLogos;
  PaymentCurrencyAmount total;
  PaymentCredentialInstrument instrument;
};
isPayment

확장이 활성화되어 있음을 나타냅니다.

rpId

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

topOrigin

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

payeeName

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

payeeOrigin

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

paymentEntitiesLogos

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

total

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

instrument

등록 시가 아닌 인증 시에만 사용되며, 웹 개발자가 직접 설정해서는 안 됩니다.

browserBoundPubKeyCredParams

브라우저 바인딩 키에 사용되는 암호화 알고리즘의 유형을 제한하는 허용된 자격 증명 유형 목록입니다. 인증 시 웹 개발자는 대신 SecurePaymentConfirmationRequest.browserBoundPubKeyCredParams를 설정해야 합니다.

참고: 이 멤버가 없으면 기본값으로 PublicKeyCredentialCreationOptions.pubKeyCredParams가 사용됩니다.

클라이언트 확장 처리(등록)

새 자격 증명을 생성할 때:

  1. 3단계 뒤에 다음 단계를 삽입합니다.

  2. 13단계 이전(CollectedClientData 생성 전)입니다.

    테스트
    1. bbk_allowed_algorithms를 browserBoundPubKeyCredParams로 설정합니다.

    2. browserBoundPubKeyCredParams가 비어 있으면 bbk_allowed_algorithms를 PublicKeyCredentialCreationOptions.pubKeyCredParams로 설정합니다.

    3. bbk_and_algorithm, bbk_id를 bbk_allowed_algorithms를 사용하여 키 쌍을 생성한 결과로 설정합니다.

    4. (bbk_and_algorithm, bbk_id)가 null이면 아래에서 bbk_and_algorithm과 bbk_public_key에 관련된 단계를 건너뜁니다.

    5. bbk_public_key를 bbk_and_algorithm을 사용하여 브라우저 바인딩 공개 키를 가져온 결과로 설정합니다.

  3. 13단계에서 CollectedClientData를 생성하는 대신 CollectedClientPaymentData를 생성하며, 필드는 다음과 같습니다.

    payment

    다음 필드로 초기화된 CollectedClientAdditionalPaymentRegistrationData입니다.

    browserBoundPublicKey

    bbk_public_key - COSE_Key로 인코딩된 공개 키입니다.

    기타 필드

    다른 모든 필드는 원래 13단계에 따라 설정합니다.

  4. 22단계의 "인증기 중 하나라도 성공을 나타내는 경우"에서, 3단계의 pubKeyCred를 반환하기 직전에:

    1. bbk_id와 pubKeyCred.[[identifier]]를 사용하여 키 쌍을 바인딩합니다. 결과가 실패이면 UnknownError를 반환합니다.

    2. payment_outputs를 AuthenticationExtensionsPaymentOutputs로 설정하며, 다음을 포함합니다.

      browserBoundSignature

      다음 필드로 초기화된 BrowserBoundSignature입니다.

      signature

      bbk_and_algorithm과 자격 증명 생성 14단계의 clientDataJson을 사용하여 브라우저 바인딩 서명을 생성한 결과입니다.

    3. [[clientExtensionsResults]]["payment"]를 payment_outputs로 설정합니다.

클라이언트 확장 처리(인증)

AuthenticationExtensionsPaymentInputs extension_inputs를 사용하여 어서션을 생성할 때:

  1. "secure-payment-confirmation" 결제 처리기 내에 있지 않으면 "NotAllowedError" DOMException을 반환합니다.

    테스트

    참고: 이는 웹사이트가 거래 사용자 경험을 거치지 않고 SPC의 확장된 기능에 접근하려는 시도를 방지합니다.

  2. [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 중:

    1. options.rpId와 effectiveDomain을 비교하는 6.1단계를 건너뜁니다.

    테스트

    참고: 이를 통해 교차 도메인 인증 절차를 수행할 수 있습니다. § 1.1.2 판매자의 인증 제어를 참조하시기 바랍니다.

    1. 10단계 이전, CollectedClientData를 생성하기 전입니다.

      1. allowed_algorithms를 SecurePaymentConfirmationRequest.browserBoundPubKeyCredParams로 설정합니다.

      2. bbk_and_algorithm을 credential_id와 allowed_algorithms를 사용하여 브라우저 바인딩 키를 가져오거나 생성한 결과로 설정합니다.

    2. 10단계에서 CollectedClientData를 생성하는 대신 CollectedClientPaymentData를 다음과 같이 생성합니다.

      1. type을 "payment.get"으로 설정합니다.

      2. payment를 새 CollectedClientAdditionalPaymentData로 설정하며, 필드는 다음과 같습니다.

        rpId

        extension_inputs["rpId"]

        topOrigin

        extension_inputs["topOrigin"]

        payeeName

        extension_inputs["payeeName"]가 존재하면 해당 값을 사용하고, 그렇지 않으면 생략합니다.

        payeeOrigin

        extension_inputs["payeeOrigin"]가 존재하면 해당 값을 사용하고, 그렇지 않으면 생략합니다.

        paymentEntitiesLogos

        extension_inputs["paymentEntitiesLogos"]가 존재하면 해당 값을 사용하고, 그렇지 않으면 생략합니다.

        total

        extension_inputs["total"]

        instrument

        extension_inputs["instrument"]

        browserBoundPublicKey

        bbk_and_algorithm이 null이 아니면 bbk_and_algorithm을 사용하여 브라우저 바인딩 공개 키를 가져온 결과입니다. bbk_and_algorithm이 null이면 이 키를 설정하지 않습니다.

      3. 다른 모든 필드는 원래 10단계에 따라 설정합니다.

      테스트
    3. "인증기 중 하나라도 성공을 나타내는 경우"에서 [[clientExtensionsResults]]를 설정하는 2단계 중:

      1. payment_outputs를 AuthenticationExtensionsPaymentOutputs로 설정하며, 필드는 다음과 같습니다.

        browserBoundSignature

        bbk_and_algorithm이 null이 아니면 다음 필드를 가진 BrowserBoundSignature입니다.

        signature

        bbk_and_algorithm과 clientDataJson을 사용하여 브라우저 바인딩 서명을 생성한 결과입니다. 자격 증명 생성 14단계의 결과입니다.

      2. [[clientExtensionsResults]]["payment"]를 payment_outputs로 설정합니다.

      테스트
클라이언트 확장 출력
partial dictionary AuthenticationExtensionsClientOutputs {
  AuthenticationExtensionsPaymentOutputs payment;
};

dictionary AuthenticationExtensionsPaymentOutputs {
  BrowserBoundSignature browserBoundSignature;
};

dictionary BrowserBoundSignature {
  required ArrayBuffer signature;
};
browserBoundSignature

브라우저 바인딩 서명 절차의 출력입니다.

signature

브라우저 바인딩 서명 프로세스의 출력입니다.

인증기 확장 처리

없음

5.1. CollectedClientPaymentData 사전

dictionary CollectedClientPaymentData : CollectedClientData {
    required (CollectedClientAdditionalPaymentData or CollectedClientAdditionalPaymentRegistrationData) payment;
};

CollectedClientPaymentData 사전은 CollectedClientData를 상속합니다. 다음과 같은 추가 필드를 포함합니다.

payment

서명할 추가 결제 정보입니다.

5.2. CollectedClientAdditionalPaymentData 사전

dictionary CollectedClientAdditionalPaymentData {
    required USVString rpId;
    required USVString topOrigin;
    USVString payeeName;
    USVString payeeOrigin;
    sequence<PaymentEntityLogo> paymentEntitiesLogos;
    required PaymentCurrencyAmount total;
    required PaymentCredentialInstrument instrument;
    USVString browserBoundPublicKey;
};

CollectedClientAdditionalPaymentData 사전에는 다음과 같은 필드가 포함됩니다.

rpId

자격 증명을 생성한 신뢰 당사자의 ID입니다.

참고: 역사적인 이유로 일부 구현에서는 이 매개변수를 rp라는 이름으로 추가로 포함할 수 있습니다. rp와 rpId가 모두 존재하면 값이 같아야 합니다.

topOrigin

거래 세부 정보에 서명을 요청한 최상위 컨텍스트의 출처입니다.

payeeName

존재하는 경우 사용자에게 표시된 수취인의 이름입니다.

payeeOrigin

존재하는 경우 사용자에게 표시된 수취인의 출처입니다.

paymentEntitiesLogos

거래 대화 상자에서 사용자에게 표시된 로고가 있는 경우 해당 로고입니다. 이러한 로고는 거래를 지원하는 주체를 나타내기 위한 것입니다.

total

[payment-request]의 total 필드에 해당하는 PaymentCurrencyAmount입니다.

instrument

사용자에게 표시된 결제 수단 정보입니다.

browserBoundPublicKey

브라우저 바인딩 키 공개 키의 base64url 인코딩입니다. WebAuthn의 Base64url 인코딩을 참조하시기 바랍니다.

CollectedClientAdditionalPaymentData에는 paymentRequestOrigin 필드가 없습니다. 호출하는 프레임의 출처가 이미 [webauthn-3]의 CollectedClientData에 포함되어 있기 때문입니다.

5.3. CollectedClientAdditionalPaymentRegistrationData 사전

dictionary CollectedClientAdditionalPaymentRegistrationData {
    USVString browserBoundPublicKey;
};

CollectedClientAdditionalPaymentRegistrationData 사전에는 다음과 같은 필드가 포함됩니다.

browserBoundPublicKey

브라우저 바인딩 키 공개 키의 base64url 인코딩입니다. WebAuthn의 Base64url 인코딩을 참조하시기 바랍니다.

6. 브라우저 바인딩 키 저장소

이는 사용자 에이전트가 소유하는 내부 구성 요소로, SPC 자격 증명(즉, 패스키)과의 연결을 포함하여 플랫폼별 암호화 키 쌍을 관리합니다. 각 브라우저 바인딩 키 저장소는 하나의 사용자 에이전트가 소유하며, 이를 기기와 브라우저 모두에 바인딩합니다. 각 사용자 에이전트는 여러 브라우저 바인딩 키 저장소를 보유할 수 있습니다. 예를 들어 사용자 에이전트에 여러 프로필이 있는 경우입니다. 이 절에서는 브라우저 바인딩 키 저장소와 브라우저 바인딩 키 쌍을 생성, 바인딩, 가져오기 및 서명에 사용하는 절차를 설명합니다.

참고: 브라우저 바인딩 키 저장소는 키 쌍 생성, 키 쌍 가져오기, 공개 키 내보내기 및 서명 생성을 수행해야 합니다. 많은 운영 체제는 이러한 작업을 구현하는 API를 제공하며, 가능한 경우 기기의 보안 요소에 비공개 키를 저장하는 기능도 제공합니다. 예를 들어 Android KeyStore, Apple CryptoKit 또는 Windows 암호화 API: 차세대 기술이 있습니다.

참고: 브라우저 바인딩 키의 요구 사항과 설계 고려 사항은 BBK 요구 사항 문서에 설명되어 있습니다. 브라우저 바인딩 키 저장소와 그 절차의 설계는 이러한 요구 사항과 고려 사항을 기반으로 합니다. 요구 사항 문서에서는 브라우저 구현을 염두에 두고 작성되었기 때문에 사용자 에이전트를 가리키는 용어로 "설치된 브라우저 프로그램"을 사용합니다. 그러나 요구 사항과 설계 고려 사항은 모든 사용자 에이전트 구현에 적용할 수 있습니다.

브라우저 바인딩 키 저장소에는 다음이 포함됩니다.

browser_bound_map

자격 증명 ID를 키 쌍 식별자에 매핑하는 맵입니다.

참고: 각 키 쌍 식별자는 최대 하나의 자격 증명 ID에 연결될 수 있습니다.

keypair_map

키 쌍 식별자인 바이트 배열을 공개 키와 비공개 키 키 쌍 및 알고리즘 식별자인 COSEAlgorithmIdentifier의 튜플에 매핑하는 맵입니다.

참고: 사용자 에이전트는 keypair_map에 상응하는 기능을 제공하는 암호화 API를 사용할 수 있으며, 이 경우 사용자 에이전트는 해당 부분을 암호화 API에 위임합니다.

6.1. 키 쌍 생성

PublicKeyCredentialParameters allowed_algorithms가 주어졌을 때 키 쌍을 생성하고, 키 쌍과 해당 COSEAlgorithmIdentifier의 튜플, 그리고 키 쌍 식별자의 바이트 배열을 반환하려면 다음 단계를 실행합니다.

참고: 허용된 알고리즘 또는 기본 허용 알고리즘에서 키 쌍을 생성합니다.

  1. allowed_algorithms가 비어 있으면, 이 목록을 다음 항목을 순서대로 포함하는 기본 목록으로 설정합니다.

  2. allowed_algorithms에서 PublicKeyCredential 유형이 아닌 모든 항목을 제거합니다.

  3. allowed_algorithms에서 사용자 에이전트가 지원하지 않는 모든 항목을 제거합니다.

    참고: 사용자 에이전트는 기기 플랫폼에 따라 서로 다른 암호화 알고리즘 집합을 지원할 수 있습니다.

  4. allowed_algorithms의 크기가 0이면 null을 반환합니다.

    참고: 이 경우 사용자 에이전트는 브라우저 바인딩 출력을 추가하지 않습니다.

  5. allowed_algorithms의 크기가 0보다 크면:

    1. chosen_algorithm을 allowed_algorithms[0]으로 설정합니다.

    2. bbk를 chosen_algorithm에 해당하는 확립된 절차를 사용하여 공개 키와 비공개 키 키 쌍을 생성한 결과로 설정합니다. 확립된 키 생성 알고리즘은 IANA COSE 알고리즘 등록부 [IANA-COSE-ALGS-REG]를 참조하시기 바랍니다. 결과가 실패이면 null을 반환합니다.

    3. bbk_and_algorithm을 튜플 (bbk, chosen_algorithm)로 설정합니다.

    4. bbk_id를 다음 중 하나로 설정합니다.

      1. 다음과 같이 초기화된 바이트 배열입니다.

        1. bbk_id를 길이가 32인 배열로 설정합니다.

        2. getRandomValues(bbk_id)를 호출합니다.

      2. 구현 정의 키 생성 절차에서 키 쌍 핸들을 직렬화한 바이트 배열 결과입니다. 이 바이트 배열은 나중에 브라우저 바인딩 키를 가져오거나 생성할 때 키를 식별할 수 있어야 합니다.

      참고: 많은 암호화 API는 비공개 키 대신 식별자, 핸들 또는 래핑된 키를 공개 키와 함께 반환할 수 있습니다. 예를 들어 비공개 키가 보안 요소에 저장되어 있으면 사용자 에이전트가 비공개 키에 직접 접근할 수 없으며, 이를 사용하려면 식별자/핸들/래핑된 키를 암호화 API의 다른 함수에 전달해야 합니다.

    5. keypair_map[bbk_id]을 bbk_and_algorithm으로 설정합니다.

    6. (bbk_and_algorithm, bbk_id)를 반환합니다.

이 명세에서는 먼저 하드웨어 저장소의 알고리즘을 (지정된 순서대로) 선호하고, 그다음 소프트웨어의 알고리즘을 (동일한 지정 순서대로) 선호하도록 규정할 수 있습니다. 현재로서는 Chrome이 플랫폼당 하드웨어에서 하나의 알고리즘만 지원할 계획이므로 이 논의가 불필요할 수 있습니다. 허용해야 하는 저장소 유형과 신뢰 당사자에게 저장소 유형을 공개하는 문제를 포함하여 BBK의 저장소 유형을 논의하는 보안 결제 확인 이슈 #288을 참조하시기 바랍니다.

6.2. 키 쌍 바인딩

키 쌍 식별자를 포함하는 바이트 배열 bbk_id와 바이트 배열 credential_id가 주어졌을 때 키 쌍을 바인딩하려면, 실패를 반환할 수 있는 다음 단계를 수행합니다.

참고: 자격 증명 ID(즉, 패스키 식별자)에 대한 브라우저 바인딩 키 식별자를 browser_bound_map에 저장합니다.

  1. browser_bound_map[credential_id]을 bbk_id로 설정합니다. InvalidStateError, TypeError 및 QuotaExceededError 오류를 포착한 다음 실패를 반환합니다.

    참고: write(buffer, options)와 같은 기본 파일 시스템 작업에서 오류가 발생할 수 있습니다. 여기서는 false를 반환하여 사용자 에이전트가 거래에 브라우저 바인딩 키를 포함하지 않도록 하며, 이 경우 신뢰 당사자는 해당 거래에서 브라우저 바인딩 키를 받지 못합니다. 이후 결제 어서션에서는 새로운 키 쌍 생성을 시도합니다.

6.3. 키 쌍 가져오기

바이트 배열 credential_id와 PublicKeyCredentialParameters의 목록인 allowed_algorithms가 주어졌을 때 브라우저 바인딩 키를 가져오거나 생성하고, 키 쌍과 해당 COSEAlgorithmIdentifier의 튜플을 반환하려면:

참고: 자격 증명 ID에 연결된 기존 키 쌍을 찾거나 새 연결 키 쌍을 생성하고 해당 키 쌍과 알고리즘을 반환합니다.

  1. browser_bound_map[credential_id]이 존재하면:

    1. bbk_id를 browser_bound_map[credential_id]으로 설정합니다.

    2. bbk_and_algorithm을 keypair_map[bbk_id]으로 설정합니다.

  2. browser_bound_map[credential_id]이 존재하지 않으면:

    1. (new_bbk_and_algorithm, bbk_id)를 allowed_algorithms를 사용하여 키 쌍을 생성한 결과로 설정합니다.

    2. binding_result를 bbk_id와 credential_id를 사용하여 키 쌍을 바인딩한 결과로 설정합니다. 결과가 실패이면 bbk_and_algorithm을 null로 설정합니다.

    3. binding_result가 실패가 아니면 bbk_and_algorithm을 new_bbk_and_algorithm으로 설정합니다.

  3. bbk_and_algorithm을 반환합니다.

6.4. 브라우저 바인딩 공개 키 가져오기

키 쌍과 COSEAlgorithmIdentifier의 튜플인 bbk_and_algorithm이 주어졌을 때 브라우저 바인딩 공개 키를 가져오고 바이트 배열을 반환하려면:

참고: 브라우저 바인딩 키의 인코딩된 공개 키를 가져옵니다.

  1. bbk를 bbk_and_algorithm[0]으로 설정합니다.

  2. algorithm을 bbk_and_algorithm[1]로 설정합니다.

  3. public_key를 algorithm에 대해 확립된 절차에 따라 bbk에서 가져온 공개 키로 설정합니다.

  4. encoded_public_key를 public_key의 COSE_Key 인코딩으로 설정합니다. WebAuthn의 credentialPublicKey를 참조하시기 바랍니다. 웹 인증 § 6.5.1 증명된 자격 증명 데이터에 설명되어 있습니다.

  5. encoded_public_key를 반환합니다.

6.5. 클라이언트 데이터 서명

키 쌍과 COSEAlgorithmIdentifier의 튜플인 bbk_and_algorithm과 바이트 배열 client_data_json이 주어졌을 때 브라우저 바인딩 서명을 생성하고 바이트 배열을 반환하려면:

참고: 브라우저 바인딩 키의 비공개 키를 사용하여 CollectedClientData에 서명합니다( CollectedClientAdditionalPaymentData 또는 CollectedClientAdditionalPaymentRegistrationData 포함).

  1. bbk를 bbk_and_algorithm[0]으로 설정합니다.

  2. algorithm을 bbk_and_algorithm[1]로 설정합니다.

  3. signature를 bbk의 비공개 키로 client_data_json에 대해 algorithm을 수행한 결과로 설정합니다. IANA COSE 알고리즘 등록부 [IANA-COSE-ALGS-REG]를 참조하시기 바랍니다.

    참고: 결과는 bbk의 비공개 키를 사용하여 client_data_json에 생성한 암호학적 서명입니다.

  4. signature를 반환합니다.

7. 공통 데이터 구조

다음 데이터 구조는 등록과 인증에서 공통으로 사용됩니다.

7.1. PaymentCredentialInstrument 사전

dictionary PaymentCredentialInstrument {
    required USVString displayName;
    required USVString icon;
    boolean iconMustBeShown = true;
    USVString details;
};

PaymentCredentialInstrument 사전에는 거래 세부 정보와 함께 서명되고 사용자에게 표시되는 정보가 포함됩니다. 다음과 같은 멤버가 포함됩니다.

displayName

사용자에게 표시할 결제 수단의 이름입니다.

참고: displayName의 국제화에 관한 논의는 § 14 국제화 고려 사항을 참조하시기 바랍니다.

icon

결제 수단 아이콘의 URL입니다.

참고: icon URL은 인터넷에서 접근할 수 있는 서버의 이미지(예: https://bank.example/card.png)를 가리키거나, 데이터 URL [RFC2397]을 통해 아이콘 데이터를 직접 인코딩할 수 있습니다. 두 URL 유형 중 데이터 URL은 신뢰 당사자에게 여러 이점을 제공합니다. 신뢰성을 높일 수 있습니다(예: 아이콘 호스팅 서버를 사용할 수 없는 경우). 또한 신뢰 당사자가 브라우저에서 사용자에게 표시한 내용에 대한 암호학적 증거를 확보하므로 검증도 강화할 수 있습니다. 아이콘 URL은 CollectedClientAdditionalPaymentData 구조의 일부로 서명됩니다.

참고: 관련 접근성 고려 사항을 참조하시기 바랍니다.

iconMustBeShown

요청이 성공하려면 지정된 아이콘을 성공적으로 가져와 표시해야 하는지 여부를 나타냅니다.

details

사용자에게 표시할 결제 수단에 대한 선택적 추가 세부 정보 문자열입니다.

참고: details의 국제화에 관한 논의는 § 14 국제화 고려 사항을 참조하시기 바랍니다.

7.2. 사전

dictionary PaymentEntityLogo {
    required USVString url;
    required USVString label;
};

PaymentEntityLogo 사전에는 현재 거래를 지원하는 결제 주체의 로고를 설명하는 정보가 포함됩니다. 다음과 같은 멤버가 포함됩니다.

url

로고의 URL입니다.

참고: url은 인터넷에서 접근할 수 있는 서버의 이미지(예: https://bank.com/logo.png)를 가리키거나, 데이터 URL [RFC2397]을 통해 로고 데이터를 직접 인코딩할 수 있습니다. 두 URL 유형 중 데이터 URL은 신뢰 당사자에게 여러 이점을 제공합니다. 신뢰성을 높일 수 있습니다(예: 로고 호스팅 서버를 사용할 수 없는 경우). 또한 신뢰 당사자가 브라우저에서 사용자에게 표시한 내용에 대한 암호학적 증거를 확보하므로 검증도 강화할 수 있습니다. 로고 URL은 CollectedClientAdditionalPaymentData 구조의 일부로 서명됩니다.

label

로고에 대한 설명 레이블입니다. 사용자 에이전트는 이 레이블을 사용자에게 표시할 수 있지만 반드시 표시해야 하는 것은 아닙니다( § 4.10 거래 확인 사용자 경험 표시 참조). 접근성을 위해 이를 사용하는 것이 좋습니다(예: 사용자 인터페이스에서 이 로고를 설명할 때 화면 낭독기가 소리 내어 읽도록 함).

8. 권한 정책 통합

이 명세는 PaymentRequest 생성자에 따라 SPC 인증에 대한 접근을 제어하기 위해 [payment-request]의 "payment" 정책 식별자 문자열을 사용합니다.

이 명세의 이전 버전과의 하위 호환성을 위해 자격 증명 관리 자격 증명 유형 등록부를 확장하여 public-key 유형에 대한 대체 생성 권한 정책으로 "payment" 정책 식별자 문자열을 추가합니다. 이 명세의 향후 버전에서는 이러한 동작을 완전히 폐기할 수 있습니다.

테스트

참고: [CREDENTIAL-MANAGEMENT-1]에 명시된 알고리즘이 실제 권한 정책 평가를 수행합니다. 이러한 정책 평가는 현재 설정 객체에 접근할 수 있을 때 수행되어야 하기 때문입니다. [[Create]](origin, options, sameOriginWithAncestors) 및 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors) 내부 메서드는 [CREDENTIAL-MANAGEMENT-1]에 명시된 알고리즘에 의해 병렬로 호출되므로 이러한 접근 권한이 없습니다.

9. SPC 신뢰 당사자 작업

9.1. 인증 어서션 검증

보안 결제 확인을 위한 인증 절차를 수행하려면 신뢰 당사자는 반드시 다음과 같이 진행해야 합니다.

  1. credential을 SPC caller가 보안 결제 확인 결제 처리기를 성공적으로 호출하여 반환받은 PublicKeyCredential로 설정합니다.

    참고: SPC는 판매자의 인증 제어를 지원하도록 설계되었으므로 SPC를 호출하는 주체가 신뢰 당사자가 아닐 수도 있습니다. 이 첫 단계에서는 SPC 호출자가 SPC를 통해 얻은 자격 증명을 신뢰 당사자에게 반환했다고 가정합니다.

  2. 다음과 같이 변경하여 WebAuthn에 명시된 대로 3~21단계를 수행합니다.

    1. 5단계에서 credential.id가 신뢰 당사자가 SPC caller에게 제공한 공개 키 자격 증명 중 하나를 식별하는지 확인합니다.

    2. 11단계에서 C["type"]의 값이 문자열 payment.get인지 확인합니다.

    3. 12단계에서 C["challenge"]의 값이 신뢰 당사자가 SPC caller에게 제공한 챌린지의 base64url 인코딩과 일치하는지 확인합니다.

    4. 13단계에서 C["origin"]의 값이 신뢰 당사자가 SPC 호출을 예상한 출처와 일치하는지 확인합니다.

    5. 13단계 뒤에 다음 단계를 삽입합니다.

      • C["payment"]["rpId"]의 값이 신뢰 당사자의 출처와 일치하는지 확인합니다.

      • C["payment"]["topOrigin"]의 값이 신뢰 당사자가 예상한 최상위 출처와 일치하는지 확인합니다.

      • C["payment"]["payeeName"]의 값이 존재하는 경우 사용자에게 표시되어야 했던 수취인 이름과 일치하는지 확인합니다.

      • C["payment"]["payeeOrigin"]의 값이 존재하는 경우 사용자에게 표시되어야 했던 수취인 출처와 일치하는지 확인합니다.

      • C["payment"]["paymentEntitiesLogos"]의 값이 존재하는 경우 사용자에게 표시되어야 했던 로고의 엄격한 순서 유지 부분집합인지 확인합니다.

        참고: 사용자 에이전트는 모든 로고를 표시하지 않아도 되지만, 사용자에게 표시하지 않은 로고를 CollectedClientAdditionalPaymentData에 포함해서는 안 됩니다.

      • C["payment"]["total"]의 값이 사용자에게 표시되어야 했던 거래 금액과 일치하는지 확인합니다.

      • C["payment"]["instrument"]의 값이 사용자에게 표시되어야 했던 결제 수단 세부 정보와 일치하는지 확인합니다.

10. 사용자 에이전트 자동화

사용자 에이전트 자동화와 웹사이트 테스트를 위해 이 문서는 다음 [WebDriver2] 확장 명령을 정의합니다. 관심 있는 관계자는 [webauthn-3]의 상응하는 자동화 절도 참조하는 것이 좋습니다.

10.1. SPC 거래 모드 설정

SPC 거래 모드 설정 WebDriver 확장 명령은 사용자 에이전트에 보안 결제 확인을 사용자가 거래 확인 사용자 경험을 수락하거나 거부하는 동작을 자동으로 시뮬레이션하는 모드로 전환하도록 지시합니다.

현재 거래 자동화 모드는 SPC에서 현재 활성화된 자동화 모드를 추적합니다. 기본값은 "none"입니다.

HTTP 메서드 URI 템플릿
POST /session/{session id}/secure-payment-confirmation/set-mode

원격 끝점 단계는 다음과 같습니다.

  1. parameters가 JSON Object가 아니면 WebDriver 오류를 반환합니다. 이때 WebDriver 오류 코드는 잘못된 인수입니다.

  2. mode를 parameters에서 "mode"라는 이름의 속성을 가져온 결과로 설정합니다.

  3. mode가 undefined이거나 "autoAccept", "autoChooseToAuthAnotherWay", "autoReject", "autoOptOut" 중 하나가 아니면 WebDriver 오류를 반환합니다. 이때 WebDriver 오류 코드는 잘못된 인수입니다.

  4. 현재 거래 자동화 모드를 mode로 설정합니다.

  5. 데이터 null과 함께 성공을 반환합니다.

11. 보안 고려 사항

이 명세는 WebAuthn을 기반으로 하므로 WebAuthn 보안 고려 사항이 적용됩니다. 아래 하위 절에서는 이 명세가 WebAuthn과 다른 부분에 대한 현재의 보안 결제 확인 전용 보안 고려 사항을 설명합니다.

11.1. 교차 출처 인증 절차

보안 결제 확인이 WebAuthn과 크게 다른 점은 제3자가 다른 신뢰 당사자의 자격 증명을 사용하여 인증 절차를 시작하고 어서션을 제3자에게 반환할 수 있다는 것입니다. 이 기능은 신뢰 당사자를 로그인 공격과 결제 공격 모두에 노출할 수 있으며, 이를 여기서 설명합니다.

11.1.1. 로그인 공격

보안 결제 확인을 위해 생성한 자격 증명은 유효한 WebAuthn 자격 증명이므로, 신뢰 당사자가 특정 사용자의 동일한 자격 증명을 로그인과 결제 모두에 사용하려 할 수 있습니다. 이 경우 수신한 어서션을 신중하게 검증하지 않으면 신뢰 당사자의 로그인 시스템에 대한 공격이 가능해집니다.

공격 과정은 다음과 같습니다.

  1. 사용자가 판매자 사이트이거나 판매자 사이트로 위장한 attacker.example에 방문합니다.

  2. attacker.example이 relyingparty.example에서 사용자의 자격 증명을 가져옵니다. 이는 합법적인 방법이거나 relyingparty.example 또는 relyingparty.example이 자격 증명을 공유한 다른 주체로부터 탈취하는 방법일 수 있습니다.

  3. attacker.example이 SPC 인증을 시작하고 사용자는 거래에 동의합니다(이 거래는 합법적일 수도 있고 아닐 수도 있습니다).

  4. attacker.example이 API 호출에서 받은 결제 어서션을 relyingparty.example의 로그인 끝점으로 보냅니다. 예를 들어 https://relyingparty.example/login에 POST 요청을 보냅니다.

  5. relyingparty.example은 잘못된 어서션 검증 코드를 사용하여 서명만 확인하고 필요한 필드(아래 참조)는 검증하지 않으므로 로그인 시도가 합법적이라고 판단합니다.

  6. relyingparty.example은 예를 들어 로그인 쿠키를 attacker.example에 반환합니다. 이제 relyingparty.example의 사용자 계정이 침해되었습니다.

신뢰 당사자는 두 가지 방법으로 이러한 공격을 방어할 수 있습니다.

첫째, 신뢰 당사자는 상황에 따라 WebAuthn 로그인 또는 SPC 결제에 대한 올바른 어서션 검증 단계를 항상 따라야 합니다. 특히 다음 필드는 모두 자격 증명의 부적절한 사용을 감지하는 데 사용할 수 있습니다.

둘째, 신뢰 당사자는 결제 자격 증명과 로그인 자격 증명을 분리하는 것을 고려할 수 있습니다. 이 경우 신뢰 당사자는 보안 결제 확인에 사용할 자격 증명을 하위 도메인(예: https//payment.relyingparty.example)에서만 등록하고, 데이터베이스에서도 결제 자격 증명과 로그인 자격 증명을 분리하는 것이 좋습니다.

참고: 현재 작성된 보안 결제 확인 명세에서는 모든 WebAuthn 자격 증명을 SPC 인증에 사용할 수 있습니다. 그러나 현재 구현에서는 그렇지 않으며, payment 확장을 지정하여 생성한 자격 증명만 SPC 인증에 참여할 수 있도록 허용합니다. 향후 명세가 이러한 현실을 반영하도록 갱신될 수 있습니다.

현재 구현과 명세 모두에서 payment 확장으로 생성한 자격 증명은 신뢰 당사자가 원한다면 로그인에도 사용할 수 있습니다. 이 점은 변경되지 않을 것으로 예상됩니다.

11.1.2. 결제 공격

보안 결제 확인 어서션은 진행 중인 온라인 거래의 일부가 아니면 사실상 쓸모가 없습니다.

다양한 메커니즘이 악의적인 제3자가 사용자 계정을 탈취하려는 대신, 합법적이거나 부정한 방법으로 얻은 보안 결제 확인 자격 증명을 사용하여 무단 결제를 시작하는 공격을 방어합니다.

11.1.3. 신뢰 당사자에게만 허용되는 WebAuthn 확장

WebAuthn은 인증 절차 중 인증 확장을 사용할 수 있도록 허용합니다. 일부 확장은 신뢰 당사자에게 민감한 데이터를 (인증기에) 저장하거나 가져오는 데 사용할 수 있습니다.

보안 결제 확인 인증 절차에서 제3자( 호출자)는 다른 신뢰 당사자의 민감한 데이터 중에서 소유한 자격 증명에 대한 절차를 시작할 수 있습니다. 호출자가 임의의 WebAuthn 확장을 지정할 수 있다면 신뢰 당사자가 해당 신뢰 당사자가 호출자와 공유하려 하지 않았던 데이터에 접근할 수 있습니다.

예를 들어 largeBlob 확장은 대량의 데이터를 저장하고 가져올 수 있도록 합니다. 공격자가 largeBlob 확장으로 SPC 절차를 시작할 수 있다면 사용자가 해당 절차를 승인한다는 전제하에 신뢰 당사자가 저장한 데이터를 읽을 수 있습니다.

이러한 위험을 완화하기 위해 보안 결제 확인은 교차 출처 인증 절차에서 WebAuthn 확장 사용을 금지하며, 호출자가 신뢰 당사자인 경우에만 허용합니다.

11.2. 판매자가 제공하는 인증 데이터

은행은 수신한 인증 어서션을 검증하여 판매자가 제공한 거래 세부 정보와 일치하는지 확인함으로써 스푸핑 공격을 방어할 수 있으며, 그렇게 하는 것이 좋습니다.

이 명세의 제3자 인증 절차에서는 유효한 거래(즉, 신뢰 당사자가 예상하는 거래)에서도 제3자가 사용자에게 표시할 거래 세부 정보를 제공하기 때문입니다.

이는 판매자가 사용자에게 잘못된 데이터를 표시하는 스푸핑 공격으로 이어질 수 있습니다. 예를 들어 판매자가 (백엔드에서) 은행에 100달러짜리 구매를 시작한다고 알리면서 SPC API에는 1달러를 전달하여 사용자에게 1달러 거래를 확인하도록 표시할 수 있습니다. 또는 판매자가 정확한 거래 세부 정보를 제공하면서도 신뢰 당사자가 예상한 것과 일치하지 않는 보안 결제 확인 자격 증명을 전달할 수도 있습니다.

보안 결제 확인은 실제로 이러한 공격을 방어하는 일을 현재 웹보다 더 쉽게 만듭니다. 현재 온라인 결제에서 은행은 판매자가 결제 과정에서 사용자에게 정확한 금액을 표시했다고 신뢰해야 합니다(사기 행위는 사용자가 계좌 명세서를 확인하는 결제 이후에야 발견됩니다).

11.3. 공격자가 생성한 브라우저 바인딩 키

신뢰 당사자(예: 은행)는 인증 어서션을 검증하고, BBK 공개 키가 포함된 암호문의 서명이 유효하지 않으면 해당 키를 무시함으로써 공격자가 생성한 BBK를 방어할 수 있으며, 그렇게 하는 것이 좋습니다. SPC 자격 증명의 서명과 BBK의 서명이라는 두 개의 서명이 존재하지만, 어서션은 BBK뿐만 아니라 패스키를 사용하여 검증해야 합니다. BBK는 추가 서명을 제공할 뿐 패스키 서명을 대체하지 않습니다.

판매자로 위장한 공격자는 BBK 공개 키를 공격자가 해당 비공개 키를 제어하는 다른 공개 키로 바꾸려 할 수 있습니다. 이후 공격자는 사용자를 사칭하여 판매자 웹사이트에 방문하고, 판매자가 SPC를 호출하면 공격자의 비공개 키를 사용하여 SPC 암호문에 서명합니다. 공격자는 BBK의 기기 바인딩 특성을 무력화한 것입니다.

그러나 이러한 공격은 실행 가능하지 않습니다.

  1. 공격자가 BBK를 바꾸는 경우: 신뢰 당사자는 패스키 공개 키를 사용하여 BBK 공개 키가 포함된 CollectedClientData를 검증할 때 잘못된 서명을 감지합니다. 신뢰 당사자는 이 거래를 거부하고 해당 BBK 공개 키를 신뢰할 수 없는 것으로 취급하는 것이 좋습니다.

  2. 공격자가 사용자를 사칭하려는 경우: 신뢰 당사자는 패스키 공개 키를 사용하여 검증할 때 잘못된 서명을 감지합니다. 신뢰 당사자는 해당 BBK 공개 키를 계속해서 신뢰할 수 없는 것으로 취급하는 것이 좋습니다.

11.4. 사용자 활성화 요구 사항의 부재

§ 4.3 사용자 활성화 요구 사항 수정에서 설명한 대로 사용자 에이전트가 사용자 활성화를 요구하지 않는 경우 추가적인 보안 완화 조치를 고려하는 것이 좋습니다. 사용자 활성화를 요구하지 않으면 사용자가 직전에 페이지와 상호 작용하지 않아도 보안 결제 확인 흐름을 시작할 수 있으므로 스팸과 클릭재킹 공격의 위험이 커집니다.

스팸을 완화하기 위해 사용자 에이전트는 일정 임계값에 도달하면 사용자 활성화를 요구하도록 결정할 수 있습니다. 예를 들어 현재 페이지에서 사용자 활성화 없이 보안 결제 확인 흐름이 이미 사용자에게 표시된 경우입니다. 클릭재킹 공격을 완화하기 위해 대화 상자가 표시된 직후 일정 시간 동안 클릭을 무시하는 시간 임계값을 구현할 수도 있습니다.

관련된 또 다른 완화 조치는 PaymentRequest.show()에 존재합니다. Payment Request API는 문서가 표시되어 있어야 한다고 요구하므로, SPC는 백그라운드 탭, 최소화된 창 또는 이와 유사하게 숨겨진 상황에서 시작할 수 없습니다.

12. 개인정보 보호 고려 사항

이 명세는 WebAuthn을 기반으로 하므로 WebAuthn 개인정보 보호 고려 사항이 적용됩니다. 아래 하위 절에서는 이 명세가 WebAuthn과 다른 부분에 대한 현재의 보안 결제 확인 전용 개인정보 보호 고려 사항을 설명합니다.

12.1. 자격 증명 ID 탐색

WebAuthn의 인증 절차의 개인정보 보호 절에 따라 보안 결제 확인 구현자는 악의적인 호출자(이제는 신뢰 당사자가 아닐 수도 있습니다)가 다음 두 경우를 구별하지 못하도록 해야 합니다.

위 경우를 구별할 수 있다면 정보가 유출되어 악의적인 신뢰 당사자가 어떤 자격 증명을 사용할 수 있는지 탐색하여 사용자를 식별할 수 있습니다.

보안 결제 확인에서는 항상 거래 확인 사용자 경험을 표시하고, 사용 가능한 SPC 자격 증명이 없는 경우와 SPC 자격 증명이 있지만 사용자가 사용하지 않기로 선택한 경우 모두 동일한 오류( "NotAllowedError" DOMException)를 반환하여 이 위험을 완화합니다.

12.2. 서로 다른 결제 수단 연결

신뢰 당사자가 한 사용자의 여러 결제 수단에 동일한 자격 증명을 사용하면 판매자가 원래는 연결되지 않을 수 있는 결제 수단의 정보를 연결할 수 있습니다. 즉, 사용자 U가 결제 수단 P1과 P2로 수행한 두 개의 서로 다른 거래에서(동일한 판매자 M 또는 공모하는 두 판매자 M1과 M2를 이용한 경우 모두) 판매자가 P1과 P2가 동일한 사용자에 속한다는 사실을 알아낼 수 있습니다.

현재 많은 온라인 결제 흐름에서는 사용자가 이러한 연결에 충분한 정보(예: 이름, 이메일 주소, 배송 주소)를 이미 제공하는 경우가 많으므로 큰 위험이 아닐 수 있습니다.

그러나 식별 정보가 더 적은 결제 수단 (예: 토큰화)이 보편화된다면 생태계 이해관계자가 사용자 개인정보를 보호하기 위한 조치를 취하는 것이 중요합니다. 예를 들면:

12.3. 추적 수단으로서의 자격 증명 ID

단일 결제 수단에 대해서도 신뢰 당사자가 반환한 자격 증명 ID는 강력한 사이트 간 식별자이므로 악의적인 주체가 추적 수단으로 사용할 수 있습니다. 그러나 판매자가 신뢰 당사자로부터 이를 얻으려면 이미 신뢰 당사자에게 전달할 만큼 강력한 식별자(예: 신용카드 번호)가 필요합니다.

12.4. 추적 수단으로서의 브라우저 바인딩 키

BBK 공개 키는 각 SPC 결제 어서션에서만 반환됩니다(그리고 최초 자사 SPC 자격 증명 생성 시 한 번 반환됩니다). 그러나 판매자가 BBK를 얻으려면 SPC를 시작하기 위해 신뢰 당사자로부터 자격 증명 ID를 얻어야 하고, 사용자는 패스키로 거래를 인증해야 합니다. BBK 공개 키에 접근하려면 먼저 자격 증명 ID에 접근해야 하므로 BBK 공개 키는 추가적인 추적 가능성을 제공하지 않습니다.

12.5. securePaymentConfirmationAvailability를 통한 핑거프린팅

securePaymentConfirmationAvailability API는 특정 프레임에서 보안 결제 확인 API를 사용할 수 없는 구체적인 이유를 사용자에게 알리지 않고 반환할 수 있으므로 핑거프린팅 위험이 발생할 수 있습니다. 이러한 이유가 중요한 정보를 유출한다고 보지는 않지만 다음 사항을 고려해야 합니다.

위 고려 사항 외에도 이 명세에서는 사용자 에이전트가 구체적인 이유를 알고 있는 경우에도 unavailable-unknown-reason을 반환하도록 선택할 수 있습니다. 이는 사용자 개인정보를 보호하기 위한 것입니다. 예를 들어 사용자 에이전트가 현재 프레임에서 이미 핑거프린팅 위험이 있는 다른 API에 접근했다는 사실을 감지한 경우 이렇게 할 수 있습니다.

12.6. getSecurePaymentConfirmationCapabilities를 통한 핑거프린팅

getSecurePaymentConfirmationCapabilities API는 사용자 기기의 기능 또는 기능 부재에 대한 구체적인 정보를 사용자에게 알리지 않고 반환할 수 있으므로 핑거프린팅 위험이 발생할 수 있습니다.

이러한 위험을 줄이기 위해 사용자 에이전트는 반환되는 레코드에서 false 값을 반환하기보다 키를 생략하는 것이 좋습니다(SHOULD). 키를 생략하는 것은(§ 4.7 보안 결제 확인 기능의 사용 가능 여부에서 설명한 대로) 기능이 지원되지 않는다고 명시적으로 확인하는 것보다 핑거프린팅에 노출되는 정보가 적습니다. 사용자 에이전트는 개인정보 보호를 위해 지원되는 기능도 생략하도록 선택할 수 있습니다(MAY).

SecurePaymentConfirmationCapability에 나열된 특정 기능에 대한 고려 사항은 다음과 같습니다.

12.7. 사용자 탈퇴

API 옵션 showOptOut은 사용자 에이전트에 사용자가 신뢰 당사자의 정보 저장에서 탈퇴하려는 의사를 표시할 방법을 제공하도록 지시합니다. 사용자가 탈퇴를 선택하면 OptOutError가 호출자에게 반환되어 사용자의 탈퇴 의사를 나타냅니다. 이후 사용자의 저장된 결제 정보를 삭제하는 등의 탈퇴 처리 책임은 호출자에게 있습니다.

구현자는 OptOutError의 반환으로 인해 사용자가 자격 증명을 보유하고 있지만 인증을 완료하지 않았다는 사실이 드러나지 않도록 해야 합니다. 이는 § 12.1 자격 증명 ID 탐색과 유사한 방법으로 완화할 수 있습니다. 예를 들어 자격 증명이 일치하지 않는 경우에도 중간 사용자 인터페이스에서 사용자가 탈퇴할 기회를 제공하는 것입니다.

이는 브라우저 데이터나 자격 증명을 삭제하기 위한 메커니즘이 아닙니다. 개발자가 사용자 에이전트를 통해 사용자에게 탈퇴 여부를 묻기 위한 것입니다. 사용자 에이전트는 예를 들어 다음과 같은 설명 문구로 이를 명확히 알려야 합니다. "이 제공업체는 결제 수단에 관한 정보를 저장했을 수 있으며, 해당 정보의 삭제를 요청하실 수 있습니다."

12.8. 로케일을 통한 핑거프린팅

locale 멤버는 보안 결제 확인 대화 상자에서 사용하는 로케일을 사용자에게 알리지 않고 노출할 수 있으므로 핑거프린팅 위험이 발생할 수 있습니다. 공격자는 서로 다른 로케일로 여러 보안 결제 확인 요청을 생성하고 PaymentRequest.canMakePayment() 호출이 오류로 거부되는지 관찰하여 보안 결제 확인 대화 상자에서 사용하는 로케일을 식별할 때까지 반복할 수 있습니다.

보안 결제 확인 대화 상자에서 사용하는 로케일이 비교적 드물다면 공격자가 사용자를 고유하게 식별하는 수단이 될 수 있습니다.

이는 핑거프린팅 수단이지만, 해당 로케일은 이미 다른 API를 통해 노출될 수도 있습니다(예: HTML § 8.10.1.2 언어 기본 설정).

13. 접근성 고려 사항

사용자 에이전트는 icon과 displayName을 함께 렌더링합니다. 신뢰 당사자는 displayName을 통해 충분한 정보를 제공하여 아이콘 표시의 접근성을 보장합니다(예: 아이콘이 은행을 나타내는 경우 displayName에 은행 이름을 포함합니다).

이 명세를 구현하는 사용자 에이전트는 WebAuthn의 접근성 고려 사항과 PaymentRequest의 접근성 고려 사항을 모두 따르는 것이 좋습니다.

14. 국제화 고려 사항

API 호출자는 locale 멤버를 사용하여 거래 대화 상자의 로케일을 API 입력으로 제공하는 표시 가능한 문자열(예: displayName)의 로케일과 일치시키는 것이 좋습니다. 특히 호출자는 다음을 수행하는 것이 좋습니다.

구현(및 값을 표시하려는 다른 프로세스)은 표시 가능한 문자열 값을 사용자 인터페이스에 삽입할 때 양방향 격리를 적용하는 것이 좋습니다. 방향을 알고 있다면 해당 방향을 설정하고, 모르는 경우에는 첫 번째 강한 문자 기준("auto")을 기본값으로 사용하는 것이 좋습니다.

15. IANA 고려 사항

이 절에서는 [RFC8809]에 의해 설립된 IANA "WebAuthn 확장 식별자" 등록부 [IANA-WebAuthn-Registries]에 아래 나열된 확장 식별자를 추가합니다.

적합성

문서 규칙

적합성 요구 사항은 설명적 단언과 RFC 2119 용어를 조합하여 표현합니다. 이 문서의 규범적 부분에 사용된 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL”이라는 핵심 용어는 RFC 2119에 설명된 대로 해석해야 합니다. 다만 가독성을 위해 이 명세에서는 이러한 용어를 모두 대문자로 표기하지 않습니다.

이 명세의 모든 텍스트는 명시적으로 비규범적이라고 표시된 절, 예제 및 참고 사항을 제외하고 규범적입니다. [RFC2119]

이 명세의 예제는 “예를 들어”라는 표현으로 소개하거나 class="example"을 사용하여 규범적 텍스트와 구분합니다. 다음과 같습니다.

정보 제공용 예제의 예시입니다.

정보 제공용 참고 사항은 “참고”라는 표현으로 시작하며 class="note"를 사용하여 규범적 텍스트와 구분합니다. 다음과 같습니다.

참고: 정보 제공용 참고 사항입니다.

테스트

이 명세의 내용과 관련된 테스트는 이와 같은 “테스트” 블록에 문서화될 수 있습니다. 이러한 블록은 모두 비규범적입니다.


적합한 알고리즘

알고리즘의 일부로 명령형으로 표현된 요구 사항 (예: "선행 공백 문자를 모두 제거합니다" 또는 "false를 반환하고 이 단계를 중단합니다")은 해당 알고리즘을 소개할 때 사용된 핵심 용어("must", "should", "may" 등)의 의미에 따라 해석해야 합니다.

알고리즘이나 구체적인 단계로 표현된 적합성 요구 사항은 최종 결과가 동등하다면 어떤 방식으로든 구현할 수 있습니다. 특히 이 명세에서 정의한 알고리즘은 이해하기 쉽도록 작성되었으며 성능을 고려하여 작성된 것은 아닙니다. 구현자는 최적화하는 것이 권장됩니다.

색인

이 명세에서 정의한 용어

참조를 통해 정의된 용어

참고 문헌

규범적 참고 문헌

[CREDENTIAL-MANAGEMENT-1]
Nina Satragno; Marcos Caceres. 자격 증명 관리 레벨 1. 2026년 9월 3일. WD. URL: https://www.w3.org/TR/credential-management-1/
[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 언어 명세. URL: https://tc39.es/ecma262/multipage/
[FETCH]
Anne van Kesteren. Fetch 표준. 현행 표준. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; 외. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[I18N-GLOSSARY]
Richard Ishida; Addison Phillips. 국제화 용어집. 2024년 10월 17일. NOTE. URL: https://www.w3.org/TR/i18n-glossary/
[IANA-COSE-ALGS-REG]
IANA CBOR 객체 서명 및 암호화(COSE) 알고리즘 등록부. URL: https://www.iana.org/assignments/cose/cose.xhtml#algorithms
[IANA-WebAuthn-Registries]
웹 인증 (WebAuthn) 등록부. URL: https://www.rfc-editor.org/rfc/rfc8809.html
[IMAGE-RESOURCE]
Aaron Gustafson; Rayan Kanso; Marcos Caceres. 이미지 리소스. 2021년 6월 4일. WD. URL: https://www.w3.org/TR/image-resource/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[PAYMENT-METHOD-ID]
Marcos Caceres. 결제 수단 식별자. 2022년 9월 8일. REC. URL: https://www.w3.org/TR/payment-method-id/
[PAYMENT-REQUEST]
Marcos Caceres; Ian Jacobs; Stephen McGruer. 결제 요청 API. 2026년 6월 22일. CRD. URL: https://www.w3.org/TR/payment-request/
[RFC2119]
S. Bradner. RFC에서 요구 수준을 나타내는 데 사용하는 핵심 용어. 1997년 3월. 현행 모범 사례. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC8809]
J. Hodges; G. Mandyam; M. Jones. 웹 인증(WebAuthn) 등록부. 2020년 8월. 정보 제공용. URL: https://www.rfc-editor.org/info/rfc8809/
[URL]
Anne van Kesteren. URL 표준. 현행 표준. URL: https://url.spec.whatwg.org/
[WEBAUTHN-3]
Akshay Kumar; 외. 웹 인증: 공개 키 자격 증명에 접근하기 위한 API - 레벨 3. 2026년 8월 25일. REC. URL: https://www.w3.org/TR/webauthn-3/
[WEBAUTHN-4]
Akshay Kumar; 외. 웹 인증: 공개 키 자격 증명에 접근하기 위한 API - 레벨 4. 2026년 9월 15일. FPWD. URL: https://www.w3.org/TR/webauthn-4/
[WEBCRYPTO-2]
Daniel Huigens. 웹 암호화 레벨 2. 2025년 4월 22일. FPWD. URL: https://www.w3.org/TR/webcrypto-2/
[WebDriver2]
Simon Stewart; David Burns. WebDriver. 2026년 7월 2일. WD. URL: https://www.w3.org/TR/webdriver2/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/

비규범적 참고 문헌

[BCP47]
Addison Phillips; Mark Davis. 언어 식별 태그. 2009년 9월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/bcp47
[DBSC]
Ian Clelland; Daniel Rubery; thefrog t. 기기 바인딩 세션 자격 증명. 2025년 8월 21일. FPWD. URL: https://www.w3.org/TR/dbsc-1/
[FS]
Austin Sullivan. 파일 시스템 표준. 현행 표준. URL: https://fs.spec.whatwg.org/
[RFC2397]
L. Masinter. "data" URL 스킴. 1998년 8월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc2397/
[WEBAUTHN-CONDITIONAL-UI]
WebAuthn 조건부 UI 제안. URL: https://github.com/w3c/webauthn/issues/1545

IDL 색인

dictionary SecurePaymentConfirmationRequest {
    required BufferSource challenge;
    required USVString rpId;
    required sequence<BufferSource> credentialIds;
    required PaymentCredentialInstrument instrument;
    unsigned long timeout;
    USVString payeeName;
    USVString payeeOrigin;
    sequence<PaymentEntityLogo> paymentEntitiesLogos;
    AuthenticationExtensionsClientInputs extensions;
    sequence<PublicKeyCredentialParameters> browserBoundPubKeyCredParams;
    sequence<USVString> locale;
    boolean showOptOut;
};

enum SecurePaymentConfirmationAvailability {
  "available",
  "unavailable-unknown-reason",
  "unavailable-feature-not-enabled",
  "unavailable-no-permission-policy",
  "unavailable-no-user-verifying-platform-authenticator",
};

partial interface PaymentRequest {
    static Promise<SecurePaymentConfirmationAvailability> securePaymentConfirmationAvailability();
};

partial interface PaymentRequest {
    static Promise<SecurePaymentConfirmationCapabilities> getSecurePaymentConfirmationCapabilities();
};

typedef record<DOMString, boolean> SecurePaymentConfirmationCapabilities;

enum SecurePaymentConfirmationCapability {
  "browserBoundKeyHardware",
};

partial dictionary AuthenticationExtensionsClientInputs {
  AuthenticationExtensionsPaymentInputs payment;
};

dictionary AuthenticationExtensionsPaymentInputs {
  boolean isPayment;
  sequence<PublicKeyCredentialParameters> browserBoundPubKeyCredParams;

  // 인증에만 사용됩니다.
  USVString rpId;
  USVString topOrigin;
  USVString payeeName;
  USVString payeeOrigin;
  sequence<PaymentEntityLogo> paymentEntitiesLogos;
  PaymentCurrencyAmount total;
  PaymentCredentialInstrument instrument;
};

partial dictionary AuthenticationExtensionsClientOutputs {
  AuthenticationExtensionsPaymentOutputs payment;
};

dictionary AuthenticationExtensionsPaymentOutputs {
  BrowserBoundSignature browserBoundSignature;
};

dictionary BrowserBoundSignature {
  required ArrayBuffer signature;
};

dictionary CollectedClientPaymentData : CollectedClientData {
    required (CollectedClientAdditionalPaymentData or CollectedClientAdditionalPaymentRegistrationData) payment;
};

dictionary CollectedClientAdditionalPaymentData {
    required USVString rpId;
    required USVString topOrigin;
    USVString payeeName;
    USVString payeeOrigin;
    sequence<PaymentEntityLogo> paymentEntitiesLogos;
    required PaymentCurrencyAmount total;
    required PaymentCredentialInstrument instrument;
    USVString browserBoundPublicKey;
};

dictionary CollectedClientAdditionalPaymentRegistrationData {
    USVString browserBoundPublicKey;
};

dictionary PaymentCredentialInstrument {
    required USVString displayName;
    required USVString icon;
    boolean iconMustBeShown = true;
    USVString details;
};

dictionary PaymentEntityLogo {
    required USVString url;
    required USVString label;
};

    

이슈 색인

이 명세의 현재 버전은 각 PaymentEntityLogo에 하나의 URL만 지원하므로 데이터 구조를 그대로 복사하고 서명하는 것만으로 사용자에게 표시된 내용을 나타내기에 충분합니다. 향후 이 명세의 버전에서는 예를 들어 다크 모드를 기본적으로 지원하기 위해 각 PaymentEntityLogo에 여러 URL을 추가할 수 있습니다. 그렇게 되면 명세는 특정 PaymentEntityLogo에 대해 어떤 URL이 표시되었는지 신뢰 당사자에게 알려야 합니다. ↵
이 명세에서는 먼저 하드웨어 저장소의 알고리즘을 (지정된 순서대로) 선호하고, 그다음 소프트웨어의 알고리즘을 (동일한 지정 순서대로) 선호하도록 규정할 수 있습니다. 현재로서는 Chrome이 플랫폼당 하드웨어에서 하나의 알고리즘만 지원할 계획이므로 이 논의가 불필요할 수 있습니다. 보안 결제 확인 이슈 #288을 참조하시기 바랍니다. 이 이슈에서는 BBK의 저장소 유형과 함께 허용해야 하는 저장소 유형 및 신뢰 당사자에게 저장소 유형을 공개하는 문제도 논의합니다. ↵