안전한 결제 확인

W3C 후보 권고안 초안,

이 문서에 대한 추가 정보
이 버전:
https://www.w3.org/TR/2026/CRD-secure-payment-confirmation-20260702/
최신 공개 버전:
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)은 결제 거래 중 간소화된 인증을 지원하는 웹 API입니다. 이는 다양한 인증 프로토콜 내에서 사용될 수 있도록 설계되었으며, 여러 가맹점에서 인증을 확장할 수 있고, 사용자가 거래 내역을 확인했음을 암호화 증거로 생성할 수 있습니다.

이 문서의 상태

이 섹션은 본 문서가 발행된 시점의 상태를 설명합니다. 최신 W3C 출판물 목록과 이 기술 보고서의 가장 최근 버전은 W3C 표준 및 드래프트 색인에서 확인할 수 있습니다.

본 문서는 웹 결제 워킹 그룹에서 권고안 경로(Recommendation track)를 이용해 후보 권고안 초안(Candidate Recommendation Draft)으로 발행되었습니다.

이전 후보 권고 스냅샷 이후 변경사항은 GitHub 변경 로그를 참조하세요.

후보 권고안으로 발행된다고 해서 W3C 및 회원이 이를 지지한다는 의미는 아닙니다. 후보 권고안 초안은 워킹 그룹이 다음 후보 권고 스냅샷에 포함할 계획인 이전 후보 권고안의 변경사항을 통합합니다.

이는 초안 문서로 언제든지 갱신, 대체 또는 폐기될 수 있습니다. 진행 중인 작업이므로 다른 용도로 인용하는 것은 부적절합니다.

이 사양이 제안 권고안(Proposed Recommendation)으로 진행되기 위해서는 사용자 에이전트에서 두 가지 독립적이고 상호운용 가능한 구현을 보여야 합니다. 관련 구현 보고서를 참조하세요.

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

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

후보 권고안으로 발행된다고 해서 W3C 및 회원이 이를 지지한다는 의미는 아닙니다. 후보 권고안 초안은 워킹 그룹이 다음 후보 권고 스냅샷에 포함할 계획인 이전 후보 권고안의 변경사항을 통합합니다.

이 문서는 W3C 특허 정책을 준수하는 그룹에 의해 제작되었습니다. W3C는 그룹의 결과물과 관련하여 공개된 특허 공개 목록을 유지하고 있습니다. 그 페이지에는 특허 공개 방법도 포함되어 있습니다. 어떤 개인이 본질적인 청구를 포함한다고 생각되는 특허에 대한 실제 정보를 알고 있으면 W3C 특허 정책 6절에 따라 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.

1. 소개

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

이 규격은 웹에서 결제 흐름 중 강력한 인증 방법 사용을 가능하게 하는 API를 정의합니다. 이는 [webauthn-3] 와 동일한 인증 장점과 사용자 프라이버시 초점을 제공하는 것을 목표로 하며, 결제 처리를 위한 요구사항을 충족하도록 개선되었습니다.

[webauthn-3] 와 유사하게, 이 규격은 사용자와 관련된 두 가지 프로세스를 정의합니다. 첫 번째는 § 3 등록 (이전 "등록(enrollment)"), 여기서 사용자와 릴라잉 파티 사이의 관계가 생성됩니다. 두 번째는 § 4 인증 - 안전한 결제 확인 결제 방식에서 사용자가 릴라잉 파티 (중개 결제 서비스 제공자를 통해 가능)로부터 챌린지에 응답하여 특정 결제에 동의합니다.

이 규격의 목표 중 하나는 결제 과정 중 인증 마찰을 줄이는 것이며, 그 한 요소는 사용자가 한 번 등록으로 가능한 한 많은 인증을 수행할 수 있도록 하는 것입니다. 즉, 릴라잉 파티의 동의 하에, 이상적으로 사용자는 "한 번 등록"으로 최초로 등록한 가맹점 오리진뿐만 아니라 모든 가맹점 오리진(및 결제 서비스 제공자를 통해)에서 인증할 수 있어야 합니다.

이를 위해, 안전한 결제 확인의 중요한 기능은 상점(또는 다른 단체)이 릴라잉 파티를 대신하여 인증 절차를 시작할 수 있다는 것입니다. 릴라잉 파티는 자격 증명 생성 시, 해당 동작을 허용하도록 명시적으로 동의해야 합니다.

기능적으로, 이 규격은 PaymentRequest API를 위한 새로운 결제 방식을 정의하고, 결제 특화 데이터 구조, 장치 바인딩 및 결제 맥락에서 API 호출을 허용하기 위한 가정 완화를 위해 WebAuthn 확장을 추가하여 [webauthn-3] 를 확장합니다.

1.1. 사용 사례

[webauthn-3] 가 웹을 위한 일반 인증 기능을 제공하지만, 아래와 같은 사용 사례를 통해 이 규격에서 정의된 결제 특화 확장 기능의 가치를 설명합니다.

온라인 거래에 대해 암호 기반 인증의 일반적 사용 사례는 이미 충분히 확립되어 있다고 가정합니다.

1.1.1. 거래 확인의 암호화 증거

많은 온라인 결제 시스템에서 결제 수단을 발급하는 기관(예: 은행)은 인증을 통해 사기 방지하려고 합니다. [webauthn-3] 및 이 규격을 사용하면 인증자를 통해 상점의 오리진, 거래 금액 및 통화 등 결제 특화 정보를 암호화 서명할 수 있습니다. 은행은 릴라잉 파티로서, 결제 승인 결정 시 해당 결제 특화 정보의 서명을 검증할 수 있습니다.

은행이 일반 [webauthn-3] 를 사용할 경우, 검증할 결제 특화 정보는 WebAuthn의 challenge 에 저장되어야 합니다. 이는 다음과 같은 문제를 야기합니다:

  1. challenge 필드의 오용(이 필드는 재사용 공격 방지 용도입니다).

  2. 명세가 없어 각 은행이 결제 특화 정보를 챌린지에 어떠한 형식과 인코딩으로 담을지 직접 설계해야 하므로, 배포가 복잡해지고 파편화가 증가합니다.

  3. 규제에 따라 사용자에게 결제 특화 정보가 표시되고 사용자 동의 증거가 요구될 수 있습니다. 일반 [webauthn-3] 에서는 이러한 정보 표시를 위한 UX가 명세되어 있지 않고, challenge 필드의 정보에 대한 UX가 제공되지 않습니다.

이러한 제한을 해소하기 위해 다음과 같은 안전한 결제 확인(SPC) 행동 양식이 도입됩니다:

  1. challenge 필드는 일반 [webauthn-3] 처럼 오직 재사용 공격 방지 용도로만 사용됩니다.

  2. SPC는 결제 특화 정보의 형식을 명세합니다. 이를 통해 범용 검증 코드와 테스트 스위트 개발이 가능합니다.

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

    • 결제 특화 정보는 CollectedClientData 딕셔너리에 포함되며, 자바스크립트에서 변조할 수 없습니다.

    참고: 결제 생태계에서 은행 등 이해당사자들은 오늘날 브라우저의 TLS, iframe 등 Web 기능을 이용해 결제에 충분한 신뢰를 두고 있습니다. 현재 명세는 웹 결제의 보안성 및 사용성을 향상시키려 설계되었습니다.

1.1.2. 가맹점의 인증 제어

가맹점들은 결제 진행 중 사용자 이탈을 방지하고 인증 마찰을 줄이고자 합니다. 릴라잉 파티 (예: 은행)가 [webauthn-3] 로 사용자를 인증하려는 경우, 보통 iframe을 통해 인증합니다. 하지만 가맹점들은 인증 사용자 경험을 직접 관리하면서도 릴라잉 파티 가 인증 결과를 검증할 수 있기를 원합니다.

이러한 제한을 해소하기 위해 다음과 같은 안전한 결제 확인(SPC) 행동 양식이 도입됩니다:

이 기능의 추가적 장점은 릴라잉 파티가 인증 프론트엔드 경험을 직접 구축하지 않아도 된다는 것입니다. 대신 결제 서비스 제공자가 상점들을 위해 이를 구축할 가능성이 높아집니다.

참고: 인증 사용자 경험을 직접 제공하고 싶은 릴라잉 파티는 SPC를 iframe에서 사용할 수 있습니다.

1.1.3. 장치 바인딩의 암호화 증거

결제 업계에서는 장치 소유 신호가 2차 요소로 중요한 역할을 합니다. WebAuthn은 하나의 자격증명이 여러 장치에서 동기화될 수 있는 패스키를 지원합니다(Web Authentication § 1.2.1 다중 장치 자격증명 사용 소비자). 동기화는 로그인 사용 사례에서 사용자 경험을 개선하지만, 일부 규제 환경에서는 동기화된 패스키만으로는 장치 소유 요건을 충족하지 못한다는 우려가 있습니다.

이런 우려를 해소하기 위해 사용자 에이전트가 생성하는 보조 공개/개인 키 쌍의 비밀키가 특정 장치에서만 존재(및 사용)하도록 만듭니다. 이러한 키와 SPC 내 사용을 브라우저 바인드 키 라고 합니다.

1.2. API 사용 예시 시나리오

이 절에서는 안전한 결제 확인을 위한 시나리오와 해당 API 사용 예시 코드를 설명합니다. 이것은 예시 흐름일 뿐이며 API 사용 범위를 제한하지 않습니다.

1.2.1. 결제 시 등록

이 흐름은 사용자가 어떤 상점에서 결제하는 과정 중 발급 은행이 새로운 자격증명을 생성해 저장하는 첫 등록 흐름입니다.

  1. 사용자가 merchant.example에 접속하여 상품을 선택하고 결제 과정을 진행합니다. 결제 수단 정보를 입력한 뒤 결제를 희망(예: "Pay" 버튼 누름)합니다.

  2. 상점은 발급 은행과 밴드 밖(out-of-band)(예: 다른 프로토콜 사용)으로 통신합니다. 발급 은행은 사용자 확인을 요청하고, 상점이 iframe에서 열 수 있도록 은행 제어의 URL을 제공합니다.

  3. 상점은 bank.example에 iframe을 열고 allow 속성을 "publickey-credentials-create"로 설정합니다.

  4. iframe 내에서 발급 은행은 기존 방식(예: SMS OTP 등)으로 사용자를 확인합니다. 확인 후, 은행은 향후 결제에 SPC 인증 등록을 권유합니다.

  5. 사용자가 동의(예: 은행 UX의 "Register" 버튼 클릭)하면, 은행은 iframe 내에서 코드를 실행합니다(예시 아래 참고).

  6. 사용자는 WebAuthn 등록 과정을 거칩니다. 새 자격증명이 생성되고, 발급 은행 서버 DB에 사용자 및 결제 수단과 연계해 저장됩니다.

  7. 확인이 완료되면 은행 iframe이 닫히고, 상점은 사용자의 결제 과정을 끝마칩니다.

이 방식으로 사용자를 등록하는 샘플 코드는 다음과 같다. 예제 코드는 더 읽기 쉬운 promise 처리를 위해 async/await에 접근할 수 있다고 가정한다.

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

const publicKey = {
  // challenge는 은행 서버가 생성하여 iframe으로 전송해야 한다.
  challenge: new Uint8Array([21,31,105 /* 서버가 생성한 추가 난수 바이트 29개 */]),

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

  // 사용자:
  user: {
    // WebAuthn의 일부. 이 정보는 SPC에서 요구하지 않지만
    // 은행 서버가 이후 거래에서 이 사용자를 식별하는 데
    // 사용할 수 있다. 동일 사용자에 대해 일관되지 않은 값은
    // 사용자에게 여러 자격 증명이 생성되는 결과를 낳을 수 있으며
    // 따라서 자격 증명 선택으로 인한 잠재적 UX 마찰이 생길 수 있다.
    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"
        }
      ]
    }
  }
};

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

1.2.2. 가맹점 사이트에서 인증

이미 등록된 자격증명을 가진 사용자가 거래를 수행하고, 발급 은행과 가맹점이 안전한 결제 확인(SPC)를 사용하고자 할 때의 흐름입니다.

  1. 사용자가 merchant.example에 방문하여 상품을 선택한 뒤 결제 과정을 진행합니다. 결제 수단 정보를 입력하고, 결제 의사를 표시합니다(예: "결제" 버튼 클릭).

  2. 가맹점은 결제 수단의 발급 은행과 밴드 밖(out-of-band)으로 통신합니다(예: 다른 프로토콜 사용). 발급 은행은 사용자 확인을 요청하며, 동시에 API 사용에 필요한 정보를 제공하여 SPC 사용을 승인했음을 상점에 알립니다. 이 정보에는 챌린지와 해당 사용자 및 결제 수단과 연계된 자격증명 ID 목록이 포함됩니다.

  3. 가맹점은 아래 예시 코드를 실행합니다.

  4. 사용자는 SPC UX에 표시된 결제 특화 정보에 동의하고, 이후 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도 은행에서 얻는다.
    challenge: new Uint8Array([21,31,105 /* 은행이 생성한 추가 난수 바이트 29개 */]),

    instrument: {
      displayName: "FancyBank Platinum Card",
      details: "****1234 | 01/29",
      icon: "https://fancybank.example/card-art.png",
    },

    payeeName: "Merchant Shop",
    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: "Total",
      amount: {
        currency: "USD",
        value: "5.00",
      },
    },
  });

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

  // response.data는 PublicKeyCredential이며, 발급 은행의
  // 검증을 위한 거래 데이터를 포함하는 clientDataJSON을 가진다.

  /* 검증을 위해 response.data를 발급 은행으로 보낸다 */
} catch (err) {
  /* SPC를 사용할 수 없음; 판매자는 기존 흐름으로 대체해야 한다 */
}

2. 용어

SPC 자격증명

이 규격에서 정의된 동작에 사용될 수 있는 WebAuthn 자격증명입니다.

이 규격은 릴라잉 파티가 SPC 자격증명을 다른 인증 흐름(예: 로그인)에 어떻게(혹은 하지 않고) 사용할지 제한하려는 목적이 아닙니다.

참고: 현 규격 버전에서는 릴라잉 파티가 자격증명이 1자 파티 또는 3자 파티 맥락에서 사용될 수 있도록 명확히 동의(opt-in)해야 함을 요구합니다. 장기적으로는 모든 WebAuthn 자격증명이 1자 파티 맥락(즉, 릴라잉 파티 도메인)에서 SPC에 사용할 수 있고, 3자 파티 사용만 opt-in이 필요하도록 발전하는 것이 목적입니다.

3자 파티 SPC 자격증명

SPC 자격증명릴라잉 파티가 자격증명 생성 시 명확히 동의(opt-in)하여, 릴라잉 파티 이외의 주체가 Secure Payment Confirmation 인증에 이를 사용할 수 있도록 허용한 자격증명입니다.

SPC 자격증명이 3자 파티 허용 여부를 조용히 판별하는 단계

아직 정의되지 않은 프로세스이며, 사용자 에이전트가 릴라잉 파티 식별자자격증명 ID 만으로, 사용자 조작 없이 해당 ID의 자격증명이 3자 파티 SPC 자격증명인지 판별하는 단계입니다.

참고: WebAuthn 이슈 1667 참고.

현재 기기에서 자격증명 사용 가능 여부를 조용히 판별하는 단계

아직 정의되지 않은 프로세스이며, 사용자 에이전트가 릴라잉 파티 식별자자격증명 ID만으로, 사용자 조작 없이 해당 자격증명이 현 기기에서 사용 가능한지 판별하는 단계입니다(즉, WebAuthn Get 호출에 성공적으로 사용할 수 있는지 여부).

사용자 에이전트는 해당 자격증명이 사용할 수 있을 확률이 있어야만 거래 확인 UX를 사용자에게 조건부로 표시할 수 있습니다.

참고: 이 특성은 SPC 자격증명탐색가능이어야 구현 가능하므로, 본 규격에서 요구사항으로 코딩되어 있습니다.

참고: 이 특성은 WebAuthn Conditional UI Proposal에 요구되는 것과 매우 유사합니다. 둘 다 동일한 기반 API로 지원될 가능성이 높습니다.

브라우저 바인드 키

WebAuthn 자격 증명에 더해 거래 세부 정보에 서명하며, 사용자 에이전트에 의해 단일 기기에 연결되는 공개-개인 키 쌍. 참고: 이 이름은 이 기능의 초기 구현이 브라우저용으로 만들어졌기 때문에 선택되었지만, 이 개념은 모든 사용자 에이전트에 적용될 수 있다.

키 쌍

키 쌍은 구조체로, 공개키개인키로 구성되며, 구현 종속 타입입니다.

참고: 공개키개인키는 IANA COSE 알고리즘 레지스트리에서 참조하는 암호 알고리즘별로 사용되는 매개변수입니다 [IANA-COSE-ALGS-REG].

참고: 공개키는 등록 시 CollectedClientAdditionalPaymentRegistrationData.browserBoundPublicKey 와 결제 인증 시 CollectedClientAdditionalPaymentData.browserBoundPublicKey에 반환됩니다.

참고: 개인키BrowserBoundSignature.signature에 포함되는 암호 서명 생성에 사용됩니다. 사용자 에이전트는 개인키를 외부로 내보내지 않으며, 기기의 보안 요소에 저장할 수도 있습니다.

3. 등록

사용자를 안전한 결제 확인에 등록하려면, 릴라잉 파티가 navigator.credentials.create() 를 호출하고 payment WebAuthn 확장 을 지정해야 합니다.

테스트

참고: 이 규격에서는 브라우저가 Conditional UI 없이도 SPC 자격증명 ID를 캐시할 수 있도록 확장을 정의합니다. 향후 WebAuthn에 해당 기능이 추가된다면 SPC에서 확장 필요성을 제거할 수 있습니다. SPC 자격증명(확장 포함)은 본질적으로 완전한 WebAuthn 자격증명입니다.

참고: 등록 시, Web Authentication은 namedisplayName 을 모두 요구하지만, user 멤버 정의에 따라, 구현에서는 이후 인증 절차에서 둘 중 어떤 것도 표시할 필요가 없습니다. 두 항목 중 2023년 10월 기준 name 이 더 꾸준히 표시되고 있습니다. 개발자들은 구현 변화를 모니터링해야 합니다.

4. 인증 - 안전한 결제 확인 결제 방식

안전한 결제 확인을 통해 결제를 인증하려면, 본 규격은 다음을 정의합니다:

  1. 결제 핸들러, 안전한 결제 확인 결제 핸들러, 결제 인증 요청을 처리합니다.

  2. 이 결제 핸들러의 표준화된 결제 방식 식별자, "secure-payment-confirmation"입니다.

안전한 결제 확인 결제 핸들러는 사용자와 거래를 확인한 후 인증 절차를 실행하여 사용자를 인증하고 인증 절차를 나타내는 서명된 blob을 생성합니다.

상위 수준에서, 안전한 결제 확인용 인증은 [webauthn-3]과 유사하지만 하나의 중요한 개념적 변화가 있습니다. 안전한 결제 확인은 제3자(예: 상점)가 릴라잉 파티를 대신해 인증 절차를 유발할 수 있도록 하며, 릴라잉 파티로부터 얻은 자격증명을 별도의 경로를 통해 전달할 수 있습니다. § 1.1.2 가맹점의 인증 제어 참고.

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

표준화된 결제 방식 레지스트리에 다음을 추가하세요: [payment-method-id]:

"secure-payment-confirmation"

안전한 결제 확인 규격.

4.2. 결제 요청 생성자 수정

PaymentRequest 객체 생성자 단계에, 4.3 단계 뒤에 새 단계를 추가합니다:

  1. 결제 방식 처리: [하위 단계 1-3 생략]

    1. seenPMIs에 "secure-payment-confirmation"이 포함돼 있고 seenPMIs의 크기가 1보다 크면 RangeError를 throw합니다.

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

PaymentRequest.show() 메서드 단계에서 2, 3단계를 다음과 같이 수정합니다:

  1. 관련 글로벌 객체에서 request일시적 활성화(transient activation)가 아니면, 사용자 에이전트는 다음을 수행할 수 있습니다:

    1. 거부된 promise"SecurityError" DOMException과 함께 반환.

  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시간. 기본값 및 허용값 범위는 사용자 에이전트가 정의하며, Web Authentication은 추가 타임아웃 가이드를 제공합니다.

payeeName

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

payeeOrigin

이 SPC 호출의 수취인(예: 상점)의 origin입니다. 선택사항이며, payeeName과 함께, 또는 대신 제공할 수 있습니다.

paymentEntitiesLogos

결제를 중개하는 개체의 로고 선택 목록이며, 표시 우선순위가 높은 순서대로 나열됩니다. 사용자 에이전트가 일부 또는 전체 로고를 표시할 필요는 없으며, § 4.9 결제 가능 여부 확인 단계 참고.

참고: 이 규격은 로고의 표시 방법을 명확히 규정하지 않으며, 사용자 에이전트가 렌더링을 제어할 수 있도록 하고 다양한 조건을 고려해 정보를 적절히 표시할 수 있음. 리스트 내 로고 순서는 중요하며, 개발자가 새로운 순서를 실험해 원하는 결과를 얻을 수 있음.

extensions

지정된 자격증명에 사용해야 할 WebAuthn 확장입니다. 호출자가 결제 확장을 명시할 필요 없으며, 자동 추가됩니다.

참고: 이 딕셔너리가 비어 있지 않으면, 비공개 데이터를 저장할 수 있는 신뢰 당사자 확장에 대한 공격을 피하기 위해 서드 파티 SPC 호출은 예외를 던진다. § 11.1.3 WebAuthn 확장은 신뢰 당사자에게만 허용됨을 참조하라.

browserBoundPubKeyCredParams

브라우저 바인드 키에 적용할 암호 알고리즘 유형을 제약하는 자격증명 허용 목록.

참고: 이 멤버는 브라우저 바인드 키가 새로 생성되어야 할 때만 사용됩니다.

locale

우선순위가 높은 순서대로 나열한 언어 태그 선택 목록입니다([BCP47] 참고). 이는 웹사이트의 지역(locale) 선호를 식별하며, 언어 우선순위 목록 [RFC4647] 형태입니다. 사용자 에이전트가 언어 협상(language negotiation) 및 지역 기반 포맷을 호출자와 함께 수행하는 데 사용 가능합니다.

showOptOut

거래 확인 UX에서 사용자가 거부할 기회를 받을지 여부입니다. 선택사항, 기본값은 false.

4.5. 결제 방식 추가 데이터 타입

이 결제 방식의 추가 데이터 타입SecurePaymentConfirmationRequest 입니다.

4.6. 안전한 결제 확인 사용 가능 여부 확인

PaymentRequest 에 정적 API가 추가되어 개발자가 안전한 결제 확인 사용 가능 여부를 간단히 확인할 수 있습니다. 이 메서드 securePaymentConfirmationAvailability()는 열거형(enum) 멤버를 반환하며, 안전한 결제 확인이 사용 가능 또는 불가능(내부 사유 설명 포함)함을 나타냅니다. 열거형 출력 사용은 개발자가 사용자 인증 옵션 안내 및 메시징에 도움됩니다.

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를 사용할 수 없는 원인을 알 수 없음을 나타냅니다. 사용자 에이전트는 사용자 프라이버시 보호를 위해 항상 이 결과를 반환할 수 있습니다.

unavailable-feature-not-enabled

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

unavailable-no-permission-policy

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

unavailable-no-user-verifying-platform-authenticator

사용자 인증이 가능한 플랫폼 인증기가 없어 해당 프레임에서 안전한 결제 확인 API를 사용할 수 없음을 나타냅니다.

참고: isUserVerifyingPlatformAuthenticatorAvailable 호출로도 이 정보를 획득할 수 있으나, 개발자 편의상 본 API에도 포함시켰습니다.

securePaymentConfirmationAvailability() 메서드를 Document document에서 호출하면, 사용자 에이전트는 아래 단계를 수행합니다. 사용자 프라이버시 보호 또는 사용자 에이전트 특유의 사유로 단계 완료 불가시, 언제든지 "unavailable-unknown-reason"를 반환할 수 있습니다.

  1. 사용자 에이전트가 안전한 결제 확인을 지원하지 않거나, 지원하지만 기능이 비활성화된 경우 "unavailable-feature-not-enabled" 반환.

  2. "payment" 권한 정책이 document에 활성화 되어 있지 않으면 "unavailable-no-permission-policy" 반환.

  3. 플랫폼 인증기가 없으면 "unavailable-no-user-verifying-platform-authenticator" 반환.

  4. 기타 이유로 해당 프레임에서 안전한 결제 확인 기능이 동작하지 않으면 "unavailable-unknown-reason" 반환.

  5. "available" 반환.

개발자는 SPC 흐름 시작 여부 판단 시 다음과 같이 확인할 수 있습니다:

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

참고: SPC 기능 탐지는 이미 생성된 PaymentRequest 객체에서 canMakePayment 를 호출하기보다, 정적 메서드 securePaymentConfirmationAvailability 사용을 권장합니다.

참고: 본 API의 프라이버시 고려는 § 12.5 securePaymentConfirmationAvailability를 통한 지문채취 참고.

4.7. Secure Payment Confirmation 기능의 이용 가능성

개발자에게 Secure Payment Confirmation 기능의 이용 가능 여부를 판별할 수 있는 메서드를 제공하기 위해, 정적 API가 PaymentRequest 에 추가된다. 이 메서드 getSecurePaymentConfirmationCapabilities() 는 기능 키에서 Boolean 값으로의 레코드를 반환한다.

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

typedef record<DOMString, boolean> SecurePaymentConfirmationCapabilities;

SecurePaymentConfirmationCapabilities 에서의 는 반드시 사전식 오름차순으로 정렬되어야 한다. 의 집합은 SecurePaymentConfirmationCapability열거 값 집합을 포함해야 하지만, 사용자 에이전트는 필요하다고 판단하는 경우 를 생략해도 된다. 자세한 내용은 § 12.6 getSecurePaymentConfirmationCapabilities를 통한 지문 채취(fingerprinting)를 참조하라.

주어진 기능의 값이 true인 경우, 그 기능은 현재 이 사용자 에이전트의 Secure Payment Confirmation 구현에서 지원되는 것으로 알려져 있다.

주어진 기능의 값이 false인 경우, 그 기능은 현재 이 사용자 에이전트의 Secure Payment Confirmation 구현에서 지원되지 않는 것으로 알려져 있다.

기능이 키로서 존재하지 않는 경우, 이 사용자 에이전트의 Secure Payment Confirmation 구현에서의 해당 기능 지원 여부는 알 수 없다.

이 API를 사용하면 개발자가 Secure Payment Confirmation 플로를 시작할지 여부를 결정할 때, 특정 기능 지원 여부를 다음과 같이 확인할 수 있다:

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

Note: 이 API의 프라이버시 관련 고려사항은 § 12.6 getSecurePaymentConfirmationCapabilities를 통한 지문 채취(fingerprinting)를 참조하라.

4.7.1. SecurePaymentConfirmationCapability 열거형

enum SecurePaymentConfirmationCapability {
  "browserBoundKeyHardware",
};

이 열거형은 개발자가 특정 워크플로우 및 사용자 경험을 제공하기 위해 평가할 수 있는 제한된 Secure Payment Confirmation 기능 집합을 정의한다.

browserBoundKeyHardware

Secure Payment Confirmation API가 디바이스의 하드웨어 보안 요소에 저장된 browser bound key를 사용할 수 있음을 나타낸다.

자세한 내용은 § 6 Browser Bound Key Store를 참조하라.

4.8. 결제 방법 데이터를 검증하는 단계

이 결제 방법에 대한 결제 방법 데이터를 검증하는 단계는 입력 PaymentRequest requestSecurePaymentConfirmationRequest data에 대해 다음과 같다:

Tests
  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 파서를 실행한다. 이것이 failure를 반환하면, 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. parsedURLdata["payeeOrigin"]에 대해 URL 파서를 실행한 결과로 둔다.

    2. parsedURL이 failure이면, TypeError를 던진다.

    3. parsedURLscheme이 "https"가 아니면, TypeError를 던진다.

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

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

      1. logo["url"]이 비어 있으면, TypeError를 던진다.

      2. logo["url"]에 대해 URL 파서를 실행한다. 이것이 failure를 반환하면, TypeError를 던진다.

      3. logo["label"]이 비어 있으면, TypeError를 던진다.

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

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

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

      1. tag가 올바른 형식의 [BCP47] 언어 태그가 아니면, TypeError를 던진다.

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

4.9. 결제가 가능한지 확인하는 단계

이 결제 방법에 대한, 입력 SecurePaymentConfirmationRequest data 에 대한 결제가 가능한지 확인하는 단계(steps to check if a payment can be made)는 다음과 같다:

Tests
  1. 만약 data["payeeOrigin"] 이 존재한다면:

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

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

    3. parsedURLscheme 이 "https" 임을 단언한다.

    NOTE: 이러한 사전 조건들은 이전에 결제 방법 데이터를 검증하는 단계에서 이미 검사되었다.

    1. data["payeeOrigin"] 을 parsedURLorigin직렬화(serialization) 로 설정한다.

  2. 아이콘에 대해, «["src" → data["instrument"]["icon"]]» 를 image 에 전달하여 이미지 리소스를 가져온다. 실패한 경우:

    1. 만약 data["instrument"]["iconMustBeShown"] 이 true 라면 false 를 반환한다.

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

      Note: 이렇게 하면 출력 instrument 의 아이콘 문자열이 비게 되므로, 지정된 아이콘이 표시되지 않았음을 RP가 알 수 있다.

    Note: 어떤 자격 증명과 일치하는지와 무관하게 이미지 리소스는 반드시 가져와야 한다. 이는 자격 증명 존재 여부를 프로빙(probe)하려는 시도를 방지하기 위함이다.

  3. 선택적으로, 사용자 에이전트는 data["paymentEntitiesLogos"] 에서 목록의 끝에서 앞쪽으로 이동하면서 항목들을 제거할 수 있다.

    Note: 이를 통해 사용자 에이전트는 몇 개의 로고를 표시할지 제어할 수 있으며, 호출자에게는 로고들이 표시 우선순위의 내림차순으로 정렬되어 있다는 의미를 유지할 수 있다.

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

    1. logo 에 대해 «["src" → logo["url"]]» 를 image 에 전달하여 이미지 리소스를 가져오고, 결과를 디코딩한다.

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

      Note: 이렇게 하면 출력 paymentEntitiesLogos 시퀀스에서 해당 로고의 url 문자열이 비게 되므로, 지정된 로고가 표시되지 않았음을 RP가 알 수 있다.

    Note: 어떤 자격 증명과 일치하는지와 무관하게 로고 리소스는 반드시 가져와야 한다. 이는 자격 증명 존재 여부를 프로빙(probe)하려는 시도를 방지하기 위함이다.

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

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

    2. data["rpId"]가 request관련 설정 객체출처가 아니면, SPC 자격 증명이 서드 파티에서 활성화되어 있는지 사용자에게 알리지 않고 판별하는 단계를 실행하며, data["rpId"]와 id를 전달한다. 결과가 false이면, iddata["credentialIds"]에서 제거한다.

  6. true 를 반환한다.

4.10. 거래 확인 UX 표시

PaymentRequest.show() 가 호출되고, 해당 알고리즘의 19–24단계에서 Secure Payment Confirmation 결제 핸들러가 선택되면, 사용자 에이전트는 사용자가 계속 진행할지 여부와 방식을 선택할 수 있는 사용자 인터페이스를 반드시 제공해야 한다.

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

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

사용자 에이전트는, 존재하는 경우 locale 에 포함된 정보를 활용하여, 웹사이트와 일관된 언어 및 로케일 기반 포맷을 사용하는 현지화된 UX 를 표시해도 된다(MAY).

showOptOuttrue 인 경우, 사용자 에이전트는 사용자가 주어진 Relying Party 에 대한 이 프로세스에서 옵트아웃(opt out)하고자 함을 표시할 수 있는 기회를 반드시 제공해야 한다.

Tests

4.10.2. 거래 확인 UX 의 결과

사용자 에이전트는 사용자가 다음 중 하나를 선택하여 계속 진행 여부와 방식을 지정할 수 있도록 반드시 허용해야 한다:

사용자가 결제를 진행하기를 원하며, SPC Credential 을 사용해 인증하기를 원하는 경우,

사용자가 상호작용 중인 PaymentRequest 에 대해 사용자가 결제 요청을 승인하는 알고리즘(user accepts the payment request algorithm)을 실행한다.

사용자가 결제를 진행하기를 원하지만, (data["credentialIds"] 가 비어 있는 경우처럼) 그렇게 할 수 없거나, SPC Credential 사용을 원하지 않는 경우,

다음 단계를 실행한다:

  1. data["credentialIds"] 를 빈 리스트로 설정한다.

    Note: 이렇게 하면 PaymentRequest.show() 프라미스는 "NotAllowedError" DOMException 로 거부된다. 자세한 내용은 § 4.11 결제 요청에 응답하는 단계를 참조하라.

  2. 사용자가 상호작용 중인 PaymentRequest 에 대해 사용자가 결제 요청을 승인하는 알고리즘을 실행한다.

Tests
사용자가 결제를 진행하기를 원하지 않는 경우,

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

Note: 이렇게 하면 PaymentRequest.show() 프라미스는 "AbortError" DOMException 으로 거부된다.

사용자가 주어진 Relying Party 에 대한 프로세스에서 옵트아웃하기를 원하는 경우,

PaymentRequest.show() 를 "OptOutError" DOMException 으로 거부한다. 자세한 내용은 § 12.7 User opt out를 참조하라.

Note: 이 옵션은 showOptOuttrue 로 설정된 경우에만 사용자에게 제공되면 된다.

4.10.3. 테스트 자동화 지원

현재 거래 자동화 모드(current transaction automation mode)가 "none" 이 아니라면, 사용자 에이전트는 먼저 자신이 자동화 컨텍스트에 있는지(예: WebDriver 의 보안 고려사항 참조) 확인해야 한다(should). 이후 사용자 에이전트는 위에서 설명한 정보 전달 및 사용자 동의 수집 과정을 건너뛰고, 대신 현재 거래 자동화 모드 값에 따라 다음을 수행해야 한다:

"autoAccept"

사용자가 거래 세부 정보를 보고, 이를 수락한 것처럼 동작한다.

"autoChooseToAuthAnotherWay"

사용자가 거래 세부 정보를 보고 이를 수락했지만, 인증에 SPC Credential 사용을 원하지 않는 것처럼 동작한다. 만약 data["credentialIds"] 가 비어 있다면, 이는 "autoAccept" 와 동일하다.

"autoReject"

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

"autoOptOut"

사용자가 거래 세부 정보를 보고 옵트아웃하기를 원하는 것처럼 동작한다.

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

이 결제 방법에 대한, 주어진 PaymentRequest requestSecurePaymentConfirmationRequest data 에 대한 결제 요청에 응답하는 단계(steps to respond to a payment request)는 다음과 같다.

Note: 이 단계들은 사용자가 거래 확인 UX 를 수락한 경우에만 실행되며, 사용자가 결제 요청을 승인하는 알고리즘에 의해 호출된다.

  1. 만약 data["credentialIds"] 가 비어 있다면 "NotAllowedError" DOMException 를 던진다. 이는 사용자가 SPC 를 사용해 인증할 수 없거나 사용하고 싶지 않은 경우에 Authentication Ceremony Privacy 를 보존하기 위함이다.

    Note: 여기서 예외를 던지면 PaymentRequest.show() 프라미스는 "NotAllowedError" DOMException 으로 거부된다.

  2. topOriginrequestrelevant settings object최상위 origin(top-level origin) 으로 설정한다.

  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 이 사용자에게 표시되었는지 Relying Party 에게 알려줄 필요가 있다.

    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

    Note: 이 알고리즘은 userVerification 의 값으로 "required" 를 하드코딩한다. 이는 Chrome 초기 구현이 지원하는 값이기 때문이다. 이러한 제한은 향후 변경될 수 있다. 워킹 그룹은 다른 값(예: "preferred" 또는 "discouraged")을 지원함으로써 이득을 보는 사용 사례를 구현자들이 공유해 주기를 요청한다.

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

    1. descriptor 를 새 PublicKeyCredentialDescriptor 딕셔너리로 설정하고, 필드는 다음과 같다:

      type

      public-key

      id

      id

      transports

      단일 원소만 가지며 길이가 1인 시퀀스로, 그 유일한 원소는 internal 이다.

    2. Append descriptorpublicKeyOpts["allowCredentials"] 에 추가한다.

  7. outputCredential 을, «["publicKey" → publicKeyOpts]» 를 넘겨 Request a Credential 알고리즘을 실행한 결과로 설정한다.

    Note: Chrome 초기 구현은 전체 data.credentialIds 리스트를 Request a Credential 에 전달하지 않는다. 대신 현재 디바이스와 일치하는 리스트 내의 한 자격 증명만 선택하여 그 하나만 전달한다.

    Note: 이는 [webauthn-3]Get 동작을 트리거한다.

  8. outputCredential 을 반환한다.

5. WebAuthn 확장 - "payment"

클라이언트 등록 확장인증 확장은 각각 자격증명이 안전한 결제 확인용으로 생성 또는 사용됨을 나타냅니다.

등록 시, 이 확장은 브라우저가 안전한 결제 확인 자격증명 ID를 식별·캐시할 수 있도록 합니다. 인증 시, 이 확장은 제3자가 릴라잉 파티를 대신하여 인증 절차를 실행할 수 있도록 하며, 동시에 거래 정보를 서명된 암호문에 추가합니다.

특히, 웹사이트는 navigator.credentials.get() 를 이용하여 이 확장에 직접 접근하면 안 됩니다; 인증은 반드시 PaymentRequest 에서 "secure-payment-confirmation" 결제 방식과 함께 사용해야만 활성화됩니다.

참고: 과거에는 payment 확장이 교차(origin) iframe에서 자격증명 생성을 허용했으나, 이제 WebAuthn에서 기본 허용됨(WebAuthn PR #1801).

테스트

이 테스트는 명세 라인에 직접 대응하지는 않으며, 교차(origin) iframe 내부에서 인증을 트리거할 수 있음을 테스트합니다. 해당 동작은 금지 라인이 없음을 통해 명세됩니다.


확장 식별자

payment

동작 적용 대상

등록인증

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

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

  // Only used for authentication.
  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, clientDataJson, create credential 14단계 사용)

    3. [[clientExtensionsResults]]["payment"] 에 payment_outputs 설정.

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

AuthenticationExtensionsPaymentInputs extension_inputs어트리뷰션(assertion) 실행 시:

  1. "secure-payment-confirmation" 결제 핸들러가 아니면 "NotAllowedError" DOMException 반환.

    테스트

    참고: 사이트가 SPC의 확장 권한도 트랜잭션 UX를 통하지 않고 접근하려는 것을 막습니다.

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

    1. 6.1단계(options.rpIdeffectiveDomain 비교) 건너뜀

    테스트

    참고: 이는 교차 도메인 인증 절차를 가능케 하며, § 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 사용). null이면 지정하지 않음.

      3. 나머지 필드는 기존 10단계와 동일.

      테스트
    3. "어떤 인증기도 성공 신호" 단계에서, 2단계(세팅 [[clientExtensionsResults]]):

      1. payment_outputs = AuthenticationExtensionsPaymentOutputs 생성(필드들):

        browserBoundSignature

        bbk_and_algorithm이 null이 아니면, BrowserBoundSignature 생성(필드들:)

        signature

        브라우저 바인드 서명 생성(bbk_and_algorithm, clientDataJson, create credential 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;
};

The 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;
};

The CollectedClientAdditionalPaymentData 사전은 다음 필드를 포함합니다:

rpId

자격 증명을 생성한 Relying Party의 ID이다.

NOTE: 역사적인 이유로, 일부 구현에서는 이 매개변수를 rp라는 이름으로도 함께 포함할 수 있다. rprpId가 모두 존재하는 경우 두 값은 반드시 같아야 한다.

topOrigin

거래 세부 정보에 서명을 요청한 최상위 컨텍스트의 origin이다.

payeeName

존재하는 경우, 사용자에게 표시된 수취인(payee)의 이름이다.

payeeOrigin

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

paymentEntitiesLogos

거래 대화 상자에서 사용자에게 표시된(있다면) 로고들이다. 이 로고들은 이 거래를 중개·지원하는 엔티티를 나타내기 위한 것이다.

total

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

instrument

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

browserBoundPublicKey

browser bound key 공개키의 base64url 인코딩 값이다. WebAuthn의 Base64url encoding을 참조하라.

참고로 CollectedClientAdditionalPaymentData에는 paymentRequestOrigin 필드가 없습니다. 호출 프레임의 출처는 이미 CollectedClientData에 포함되어 있기 때문입니다.

5.3. CollectedClientAdditionalPaymentRegistrationData 사전

dictionary CollectedClientAdditionalPaymentRegistrationData {
    USVString browserBoundPublicKey;
};

The CollectedClientAdditionalPaymentRegistrationData 사전은 다음 필드를 포함합니다:

browserBoundPublicKey

browser bound key 공개키의 base64url 인코딩 값이다. WebAuthn의 Base64url encoding을 참조하라.

6. 브라우저 바운드 키 저장소

이는 사용자 에이전트가 소유하는 내부 구성 요소로, SPC 자격 증명(즉, 패스키)과의 연결을 포함하여 플랫폼 의존적인 암호화 키 쌍을 관리한다. 각 브라우저 바인딩 키 저장소는 단일 사용자 에이전트가 소유하며, 해당 사용자 에이전트는 이를 기기와 브라우저 모두에 바인딩한다. 각 사용자 에이전트는 여러 브라우저 바인딩 키 저장소를 보유할 수 있다. 예를 들어 사용자 에이전트에 여러 프로필이 있는 경우가 그렇다. 이 절에서는 브라우저 바인딩 키 저장소와 브라우저 바인딩 키 쌍을 생성, 바인딩, 검색하고 이를 사용해 서명하는 절차를 설명한다.

참고: 브라우저 바인딩 키 저장소는 키 쌍 생성, 키 쌍 검색, 공개 키 내보내기, 서명 생성을 수행해야 한다. 많은 운영 체제는 이러한 작업을 구현하고, 사용 가능한 경우 기기의 보안 요소에 개인 키를 저장하는 API를 제공한다. 예를 들어 Android KeyStore, Apple CryptoKit, 또는 Windows Cryptography API: Next Generation이 있다.

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

브라우저 바인딩 키 저장소는 다음을 포함한다:

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_algorithmallowed_algorithms[0]으로 합니다.

    2. chosen_algorithm에 해당하는 확립된 절차를 사용하여 공개/개인 키 쌍을 생성한 결과를 bbk로 합니다. 확립된 키 생성 알고리즘은 IANA COSE Algorithms 레지스트리를 참조하세요. 결과가 실패이면 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의 저장 유형과 허용되어야 할 저장 유형, 저장 유형을 의존 당사자에 노출하는 문제 등을 논의하는 Secure Payment Confirmation issue #288을 참조하세요.

6.2. 키 쌍 바인딩

키 쌍을 바인딩하려면, 키 쌍 식별자를 포함하는 바이트 배열 bbk_id와 바이트 배열 credential_id가 주어졌을 때, failure를 반환할 수도 있으며 다음 단계를 수행한다:

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

  1. 설정: browser_bound_map[credential_id]을 bbk_id로 설정한다. InvalidStateError, TypeErrorQuotaExceededError 오류를 잡은 다음 failure를 반환한다.

    참고: 오류는 write(buffer, options)와 같은 하위 파일 시스템 작업에서 발생할 수 있다. 여기서는 False가 반환되며, 이로 인해 사용자 에이전트는 거래에 브라우저 바인딩 키를 포함하지 않게 되고, 이 경우 신뢰 당사자는 이 거래에서 브라우저 바인딩 키를 얻지 못한다. 이후 결제 assertion에서는 새 키 쌍 생성이 시도된다.

6.3. 키 쌍 검색

바이트 배열 credential_idPublicKeyCredentialParameters목록 allowed_algorithms가 주어졌을 때, 그 COSEAlgorithmIdentifier가 있는 키 쌍튜플을 반환하는 브라우저 바인딩 키를 가져오거나 생성하려면:

참고: 자격 증명 ID에 대해 기존의 연결된 키 쌍을 찾거나 새 연결된 키 쌍을 생성하고, 그 키 쌍을 알고리즘과 함께 반환한다.

  1. browser_bound_map[credential_id]가 존재하면

    1. bbk_idbrowser_bound_map[credential_id]로 둔다.

    2. bbk_and_algorithmkeypair_map[bbk_id]로 둔다.

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

    1. (new_bbk_and_algorithm, bbk_id)를 allowed_algorithms를 사용해 키 쌍을 생성한 결과로 둔다.

    2. binding_resultbbk_idcredential_id를 사용해 키 쌍을 바인딩한 결과로 둔다. 결과가 failure이면, bbk_and_algorithm을 null로 둔다.

    3. binding_result가 failure가 아니면, bbk_and_algorithmnew_bbk_and_algorithm으로 둔다.

  3. bbk_and_algorithm을 반환한다.

6.4. 브라우저 바운드 공개키 가져오기

브라우저 바운드 공개키 가져오기는 키 쌍과 COSEAlgorithmIdentifier튜플bbk_and_algorithm이 주어지면 바이트 배열을 반환한다:

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

  1. bbkbbk_and_algorithm[0]으로 합니다.

  2. algorithmbbk_and_algorithm[1]으로 합니다.

  3. public_keyalgorithm에 대한 확립된 절차에 따라 검색한 bbk의 공개키로 합니다.

  4. encoded_public_keypublic_key의 COSE_Key 인코딩으로 합니다. WebAuthn의 credentialPublicKey를 참조하세요.

  5. encoded_public_key를 반환합니다.

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

브라우저 바운드 서명 생성은 키 쌍과 COSEAlgorithmIdentifier튜플(bbk_and_algorithm)과 바이트 배열 client_data_json이 주어지면 바이트 배열을 반환한다:

참고: CollectedClientData (CollectedClientAdditionalPaymentData 또는 CollectedClientAdditionalPaymentRegistrationData 포함)의 내용을 브라우저 바운드 키개인키로 서명한다.

  1. bbkbbk_and_algorithm[0]으로 합니다.

  2. algorithmbbk_and_algorithm[1]으로 합니다.

  3. signaturealgorithm을 사용하여 bbk의 개인키로 client_data_json에 대해 수행한 결과로 합니다. IANA COSE Algorithms 레지스트리를 참조하세요.

    참고: 결과는 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)를 식별하거나, Data URL [RFC2397]을 통해 아이콘 데이터를 직접 인코딩할 수 있다. 두 유형의 URL 중에서 Data 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)를 식별하거나, Data URL [RFC2397]을 통해 로고 데이터를 직접 인코딩할 수 있다. 두 유형의 URL 중에서 Data URL은 신뢰 당사자에게 여러 이점을 제공한다. 신뢰성을 향상시킬 수 있다(예: 로고 호스팅 서버를 사용할 수 없는 경우). 또한 신뢰 당사자가 브라우저가 사용자에게 표시한 내용에 대한 암호학적 증거를 가지므로 검증도 강화할 수 있다. 로고 URL은 CollectedClientAdditionalPaymentData 구조의 일부로 서명된다.

label

로고에 대한 설명 레이블. 사용자 에이전트는 이 레이블을 사용자에게 표시할 수 있지만 반드시 그럴 필요는 없다(§ 4.10 거래 확인 UX 표시 참조). 또한 접근성 목적(예: UX에서 이 로고를 설명할 때 화면 읽기 프로그램이 소리 내어 읽도록)에 사용해야 한다.

8. 권한 정책 통합

본 명세는 SPC 인증 접근 제어를 위해 [payment-request]의 "payment" 정책 식별자 문자열을 PaymentRequest 생성자와 같이 사용합니다.

이 명세의 이전 버전과의 하위 호환을 위해 Credential Management Credential Type Registry에 "payment" 정책 식별자 문자열을 타입 public-key의 대체 Create Permissions Policy로 확장합니다. 향후 버전에서는 이 동작을 완전히 폐기할 수 있습니다.

테스트

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

9. SPC Relying Party 작업

9.1. 인증 어설션 검증

Secure Payment Confirmation에 대해 인증 절차를 수행하기 위해, 신뢰 당사자는 반드시 다음과 같이 진행해야 한다:

  1. credentialSPC callerSecure Payment Confirmation 결제 핸들러를 성공적으로 호출하여 반환된 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에게 제공한 challenge의 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의 자동화 섹션도 참고하시기 바랍니다 ([webauthn-3]).

10.1. SPC 거래 모드 설정

SPC 거래 모드 설정 WebDriver 확장 명령은 사용자 에이전트에게 Secure Payment Confirmation을 사용자가 거래 확인 UX를 자동으로 승인 또는 거절하도록 시뮬레이션하는 모드로 전환하도록 지시합니다.

현재 거래 자동화 모드는 SPC에 대해 현재 어떤 자동화 모드가 활성화되어 있는지 추적합니다. 초기값은 "none"입니다.

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

원격 측 단계는 아래와 같습니다:

  1. parameters가 JSON Object가 아니면, WebDriver 오류와 함께 WebDriver 오류 코드 invalid argument를 반환합니다.

  2. modeparameters에서 "mode"라는 이름의 프로퍼티 값으로 둡니다.

  3. modeundefined이거나 "autoAccept", "autoChooseToAuthAnotherWay", "autoReject", "autoOptOut" 중 하나가 아니면 WebDriver 오류와 함께 WebDriver 오류 코드 invalid argument를 반환합니다.

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

  5. 성공과 함께 data null을 반환합니다.

11. 보안 고려사항

이 명세는 WebAuthn을 기반으로 하므로, WebAuthn 보안 고려사항 이 적용됩니다. 아래 하위 섹션은 Secure Payment Confirmation에서 WebAuthn과 다른 부분에 대한 보안 고려사항입니다.

11.1. 크로스 오리진 인증 절차

Secure Payment Confirmation이 WebAuthn과 크게 달라지는 점은 서드 파티가 다른 신뢰 당사자의 자격 증명을 사용하여 인증 절차를 시작하고, 그 assertion을 서드 파티에 반환할 수 있도록 허용한다는 점이다. 이 기능은 신뢰 당사자를 로그인 공격과 결제 공격 모두에 노출시킬 수 있으며, 여기에서 이를 논의한다.

11.1.1. 로그인 공격

Secure Payment Confirmation용으로 생성된 자격 증명은 유효한 WebAuthn 자격 증명이므로, 신뢰 당사자가 특정 사용자에 대해 로그인과 결제 모두에 동일한 자격 증명을 사용하고자 할 수 있다. 이 경우 수신한 assertion을 주의 깊게 검증하지 않으면, 신뢰 당사자의 로그인 시스템에 대한 잠재적 공격이 가능해진다.

공격은 다음과 같다:

  1. 사용자가 판매자 사이트이거나 판매자 사이트인 척하는 attacker.example을 방문한다.

  2. attacker.examplerelyingparty.example에서 사용자의 자격 증명을 획득한다. 이는 적법하게 이루어질 수도 있고, relyingparty.example 또는 relyingparty.example이 자격 증명을 공유했던 다른 당사자로부터 훔쳐 이루어질 수도 있다.

  3. attacker.example이 SPC 인증을 시작하고, 사용자가 거래에 동의한다(그 거래가 적법할 수도 있고 아닐 수도 있다).

  4. attacker.example은 API 호출에서 받은 결제 assertion을 가져와 relyingparty.example의 로그인 엔드포인트로 보낸다. 예를 들어 https://relyingparty.example/login으로 POST를 전송한다.

  5. relyingparty.example은 결함 있는 assertion 검증 코드를 사용하고 있으며, 이 코드는 서명은 검사하지만 필요한 필드(아래 참조)를 검증하지 못하므로 로그인 시도가 적법하다고 믿는다.

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

신뢰 당사자는 두 가지 방식으로 이 공격을 방어할 수 있다.

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

둘째, 신뢰 당사자는 결제 자격 증명과 로그인 자격 증명을 분리해 유지하는 것을 고려할 수 있다. 이렇게 하는 경우, 신뢰 당사자는 Secure Payment Confirmation용 자격 증명을 하위 도메인(예: https//payment.relyingparty.example)에만 등록해야 하며, 데이터베이스에서 결제 자격 증명과 로그인 자격 증명을 분리해 유지해야 한다.

참고: 현재 작성된 Secure Payment Confirmation 명세는 모든 WebAuthn 자격 증명이 SPC 인증에 사용될 수 있도록 허용한다. 그러나 오늘날의 구현에서는 그렇지 않으며, SPC 인증에 참여하려면 payment 확장을 지정하여 생성된 자격 증명만 허용한다. 명세는 향후 이를 반영하도록 업데이트될 수 있다.

오늘날 구현과 명세 모두에서, payment 로 생성된 자격 증명은 신뢰 당사자가 원한다면 로그인에 사용할 수 있다. 이는 변경될 것으로 예상되지 않는다.

11.1.2. 결제 공격

Secure Payment Confirmation assertion은 진행 중인 온라인 거래의 일부가 아니라면 본질적으로 쓸모가 없다.

악의적인 서드 파티가 사용자 계정을 탈취하려고 시도하는 대신, Secure Payment Confirmation 자격 증명 (적법하게 또는 다른 방식으로 획득한 것)을 사용하여 승인되지 않은 결제를 시작하는 공격에 대해 여러 메커니즘이 보호한다:

11.1.3. WebAuthn 확장은 신뢰 당사자에게만 허용됨

WebAuthn은 인증 확장이 인증 절차 중에 사용될 수 있도록 허용한다. 일부 확장은 신뢰 당사자에게 민감한 데이터(인증기 상의)를 저장하거나 검색하는 데 사용될 수 있다.

Secure Payment Confirmation 인증 절차에서는 서드 파티(호출자)가 다른 신뢰 당사자가 소유한 자격 증명에 대한 절차를 시작할 수 있다. 호출자가 임의의 WebAuthn 확장을 지정할 수 있도록 허용된다면, 호출자는 신뢰 당사자가 호출자와 공유하려고 의도하지 않은, 해당 신뢰 당사자에 속한 민감한 데이터에 접근할 수 있을지도 모른다.

예를 들어, largeBlob 확장은 많은 양의 데이터를 저장하고 검색할 수 있게 한다. 공격자가 largeBlob 확장으로 SPC 절차를 시작할 수 있다면, 사용자가 절차를 승인한다고 가정할 때, 신뢰 당사자가 그곳에 저장해 둔 데이터를 읽을 수 있을지도 모른다.

이 위험을 완화하기 위해, Secure Payment Confirmation은 교차 출처 인증 절차에서 WebAuthn 확장의 사용을 허용하지 않는다. 이 확장은 호출자가 신뢰 당사자인 경우에만 허용된다.

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

은행은 수신한 인증 assertion을 검증하여 그것이 판매자가 제공한 거래 세부 정보와 일치하는지 확인함으로써 스푸핑을 방지할 수 있으며 방지해야 한다.

그 이유는 이 명세의 서드 파티 인증 절차의 결과로, 유효한 거래(즉, 신뢰 당사자가 예상하는 거래)에서도 서드 파티가 사용자에게 표시되는 거래 세부 정보를 제공하기 때문이다:

이는 판매자가 사용자에게 잘못된 데이터를 제시하는 스푸핑 공격으로 이어질 수 있다. 예를 들어, 판매자는 (백엔드에서) 은행에 $100 구매를 시작한다고 알리면서, SPC API에는 $1을 전달할 수 있다(따라서 사용자에게 검증할 $1 거래를 표시한다). 또는 판매자가 올바른 거래 세부 정보를 제공하지만, 신뢰 당사자가 예상하는 것과 일치하지 않는 Secure Payment Confirmation 자격 증명을 전달할 수도 있다.

Secure Payment Confirmation은 실제로 이런 종류의 공격을 물리치는 일을 현재 웹에서보다 더 쉽게 만든다. 오늘날 온라인 결제에서 은행은 판매자가 checkout 흐름에서 사용자에게 올바른 금액을 표시했다고 신뢰해야 한다 (그리고 모든 사기 발견은 결제 후, 사용자가 자신의 계좌 명세서를 확인할 때 이루어진다).

11.3. 공격자가 생성한 브라우저 바운드 키

신뢰 당사자(예: 은행)는 인증 assertion을 검증하여, BBK 공개 키를 포함하는 assertion을 확인하고 유효하지 않은 서명이 있는 크립토그램의 BBK 공개 키를 무시함으로써, 공격자가 생성한 BBK로부터 보호할 수 있으며 보호해야 한다. 두 개의 서명, 즉 SPC 자격 증명에서 온 서명과 BBK에서 온 서명이 존재하겠지만, assertion은 BBK에 더해 패스키를 사용하여 검증되어야 한다. BBK는 추가 서명을 제공하는 것이며, 패스키 서명을 대체하는 것이 아니다.

판매자로 가장한 공격자는 BBK 공개 키를 다른 공개 키로 대체하려고 시도할 수 있으며, 이 경우 공격자는 그에 대응하는 개인 키를 제어한다. 이후 공격자는 이제 사용자를 가장하여 판매자 웹사이트를 방문하고, 판매자가 SPC를 호출할 때 공격자의 개인 키를 사용하여 SPC 크립토그램에 서명한다. 공격자는 BBK의 기기 바인딩 측면을 무력화한 것이다.

그러나 이 공격은 실현 가능하지 않다:

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

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

11.4. 사용자 활성화 요건 부재

만약 사용자 에이전트가 § 4.3 사용자 활성화 요건 수정에서 설명한 바와 같이 사용자 활성화를 요구하지 않는다면, 추가적인 보안 완화책을 고려해야 합니다. 사용자 활성화가 요구되지 않으면 사용자가 페이지와 바로 상호작용하지 않아도 Secure Payment Confirmation 플로가 시작될 수 있어 스팸 및 클릭재킹 공격의 위험이 증가합니다.

이런 스팸을 완화하기 위해, 사용자 에이전트는 예를 들어 현재 페이지에서 이미 사용자 활성화 없이 SPC 플로를 보여준 이후에는 사용자 활성화 요건을 enforced 할 수 있습니다. 클릭재킹 공격을 완화하기 위해, 사용자 에이전트는 다이얼로그 표시 직후 일정 시간 동안 클릭을 무시하도록 임계값을 구현할 수 있습니다.

추가적으로, PaymentRequest.show()에도 관련된 완화책이 있습니다: Payment Request API는 문서가 보여지고 있을 때만 호출할 수 있으므로, SPC는 백그라운드 탭, 최소화된 창, 기타 숨겨진 상황에서는 트리거될 수 없습니다.

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

이 명세는 WebAuthn을 기반으로 하므로, WebAuthn 개인정보 보호 사항 이 적용됩니다. 아래 하위 섹션은 Secure Payment Confirmation에서 WebAuthn과 다른 부분에 대한 현재 개인정보 보호 관련 사항입니다.

12.1. 자격(credential) id 탐색

WebAuthn의 인증 절차 개인정보 보호 절에 따라, Secure Payment Confirmation 구현자는 악의적인 호출자(이제는 신뢰 당사자조차 아닐 수 있음)가 다음 경우들을 구별할 수 없도록 해야 한다:

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

Secure Payment Confirmation에서는 항상 거래 확인 UX를 표시하고, 사용할 수 있는 SPC 자격 증명이 없는 경우와, 사용할 수 있는 SPC 자격 증명이 있지만 사용자가 이를 사용하지 않기로 선택한 경우 모두에서 동일한 반환 오류("NotAllowedError" DOMException)를 반환함으로써 이 위험을 완화한다.

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

신뢰 당사자가 특정 사용자에 대해 여러 결제 수단 전반에서 동일한 자격 증명을 사용하는 경우, 이는 판매자가 원래는 연결되지 않았을 수도 있는 결제 수단에 대한 정보를 결합할 수 있게 할 수 있다. 즉, 사용자 U가 결제 수단 P1 및 P2로 수행하는 서로 다른 두 거래(동일한 판매자 M에서 또는 공모하는 두 판매자 M1 및 M2에서) 전반에서, 판매자(들)는 이제 P1과 P2가 동일한 사용자에 대한 것임을 알 수 있게 될 수 있다.

현재 많은 온라인 결제 흐름에서는 이것이 중대한 위험이 아닐 수 있다. 사용자가 어차피 이러한 결합을 가능하게 할 만큼 충분한 정보 (예: 이름, 이메일 주소, 배송 주소)를 제공하는 경우가 많기 때문이다.

그러나 식별 정보가 더 적게 포함되는 결제 방법 (예: 토큰화)이 일반화된다면, 생태계 이해관계자가 사용자 개인정보 보호를 보존하기 위한 조치를 취하는 것이 중요하다. 예를 들면:

12.3. Credential ID의 추적 벡터화

단일 결제 수단의 경우에도, 신뢰 당사자가 반환한 자격 증명 ID는 강력한 교차 사이트 식별자이므로, 악의적인 엔티티에 의해 추적 벡터로 사용될 수 있다. 그러나 이를 신뢰 당사자로부터 얻기 위해서는, 판매자가 이미 신뢰 당사자에게 제공할 그만큼 강력한 식별자 (예: 신용 카드 번호)를 필요로 한다.

12.4. 브라우저 바운드 키의 추적 벡터화

BBK 공개키는 오직 SPC 결제 어설션의 각각(및 최초의 일차 SPC Credential 생성 시 한 번)만 반환됩니다. 그러나 BBK를 얻으려면 상점이 Relying Party에서 credential ID를 얻어야 하며, 사용자가 패스키로 거래를 인증해야만 합니다. 즉 credential ID가 선행되지 않으면 BBK 공개키 접근도 불가하므로 BBK 공개키가 추가 추적 요소가 되지는 않습니다.

12.5. securePaymentConfirmationAvailability를 통한 핑거프린팅

securePaymentConfirmationAvailability API는, Secure Payment Confirmation API가 특정 프레임에서 불가한 경우 그 이유를 조용히 반환할 수 있으므로, 핑거프린팅 위험 요소가 됩니다. 이러한 이유들은 중요한 정보를 누설하는 것으로 보이지 않지만 다음과 같이 고려되어야 합니다:

또한 이 명세는, 사용자 프라이버시 보호를 위해 원한다면 사용자 에이전트가 구체적 이유를 알 때 다른 이유 대신 unavailable-unknown-reason 을 반환하게 허용합니다. 예를 들어 현재 프레임이 이미 위험한 타 API를 사용 중임을 감지했다면, 이렇게 처리할 수 있습니다.

12.6. getSecurePaymentConfirmationCapabilities를 통한 지문 채취(fingerprinting)

getSecurePaymentConfirmationCapabilities API는 사용자의 디바이스가 가진(또는 가지지 않은) 기능에 대한 구체적인 정보를 조용히 반환할 수 있으므로, 잠재적인 지문 채취(fingerprinting) 위험을 야기한다.

이 위험을 줄이기 위해, 사용자 에이전트는 false 값을 반환하는 대신, 반환되는 레코드에서 키를 생략하는 방식을 선호해야 한다(SHOULD). 키를 생략하는 것 (§ 4.7 Secure Payment Confirmation 기능의 이용 가능성에서 설명된 대로)은 어떤 기능이 지원되지 않음을 명시적으로 확인해 주는 것보다 지문 채취 표면(fingerprinting surface)을 더 적게 제공한다. 사용자 에이전트는 사용자 프라이버시를 보호하기 위해, 기능이 실제로 지원되더라도 해당 기능을 생략하기로 선택할 수도 있다(MAY).

SecurePaymentConfirmationCapability 에 나열된 개별 기능에 대한 고려사항은 다음과 같다:

12.7. 사용자 옵트아웃(User opt out)

API 옵션 showOptOut 은 사용자 에이전트에게, 사용자가 Relying Party 의 정보 보관에서 옵트아웃하고자 함을 표시할 수 있는 방법을 제공하라고 지시한다. 사용자가 이 옵트아웃을 실행하면, 호출자에게 사용자가 옵트아웃 의사를 나타냈음을 알리기 위해 OptOutError 가 반환된다. 이후에는, 예를 들어 사용자에 대해 저장된 결제 정보를 삭제하는 등, 옵트아웃에 따라 어떻게 조치할지는 호출자에게 달려 있다.

구현자는 OptOutError 가 반환되는 것이, 사용자가 자격 증명은 가지고 있지만 인증을 완료하지 않았다는 사실을 드러내지 않도록 반드시 보장해야 한다. 이는 § 12.1 자격 증명 ID를 프로빙하기(Probing for credential ids)와 유사한 방식으로 완화할 수 있다. 예를 들어, 자격 증명 일치 항목이 발견되지 않은 경우에도, 중간(interstitial) UX 에서 사용자에게 옵트아웃 기회를 제공하는 방식이 있다.

이 메커니즘은 브라우저 데이터나 자격 증명을 삭제하기 위한 수단이 아니라, 개발자가 사용자 에이전트를 통해 옵트아웃을 요청(prompt)할 수 있도록 하기 위한 것이다. 사용자 에이전트는 예를 들어 다음과 같은 설명 문구를 통해, 이를 사용자에게 명확히 알려야 한다: "이 제공자는 귀하의 결제 수단에 대한 정보를 저장했을 수 있으며, 귀하는 그 삭제를 요청할 수 있습니다."

13. 접근성 고려사항

사용자 에이전트는 icondisplayName 을 함께 랜더링합니다. Relying Party는 displayName 을 통해 아이콘 표시 접근성을 충분히 보장해야 합니다(예: 아이콘이 은행 로고라면 displayName에 은행명을 포함).

본 명세를 구현하는 사용자 에이전트는 WebAuthn 접근성 고려사항PaymentRequest 접근성 고려사항을 모두 따라야 합니다.

14. 국제화(i18n) 고려사항

API 호출자는 거래 대화상자에서 사용될 locale 및 표시용 문자열의 현지화를 locale 멤버로 지정해야 합니다. 일반적으로 이 멤버는 요청이 시작된 페이지의 현지화(예: 요청 트리거 버튼의 lang 속성)와 일치해야 합니다.

현재 이 명세에는 API에 입력하는 표시 문자열(예: displayName)에 언어나 방향 메타데이터를 연결하는 메커니즘은 포함되어 있지 않습니다.

그 동안 API 호출자는 다음을 준수해야 합니다:

구현체(및 값을 표시하려는 다른 프로세스)는 사용자 인터페이스에 표시 문자열을 삽입할 때 반드시 bidi isolation을 적용해야 합니다. 방향성이 알려져 있다면 명시적으로, 그렇지 않으면 기본(자동 추론)으로 설정해야 합니다.

15. IANA 고려사항

본 절은 확장 식별자를 IANA "WebAuthn Extension Identifiers" 레지스트리에 추가합니다([IANA-WebAuthn-Registries], [RFC8809] 참고).

적합성(Conformance)

문서 규약(Document conventions)

적합성 요구사항은 설명적 진술과 RFC 2119 용어의 조합으로 표현됩니다. 이 명세의 준거(normative) 부분에서 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL"과 같은 핵심 단어들은 RFC 2119에서 정의된 대로 해석되어야 합니다. 다만, 가독성을 위해 본 명세에서는 이러한 단어들이 모두 대문자로 나타나지 않습니다.

이 명세의 모든 텍스트는 별도 비준거, 예제 또는 주석임이 명시된 부분을 제외하고 준거성이 있습니다. [RFC2119]

이 명세의 예제는 "for example"이라는 단어로 시작하거나 class="example"를 통해 준거 텍스트와 구분됩니다. 예시는 아래와 같습니다:

이것은 참고용 예제의 예시입니다.

참고 주석(Informative notes)은 "Note"라는 단어로 시작하며, class="note"를 통해 준거 텍스트와 구분됩니다. 아래와 같이 사용합니다:

Note, 이것은 참고용 노트입니다.

테스트

이 명세와 관련된 테스트는 본문과 같이 “Tests” 블록으로 문서화될 수 있습니다. 이와 같은 블록은 모두 비준거(non-normative)입니다.


적합한 알고리즘(Conformant Algorithms)

알고리즘의 일부로 명령형으로 표현된 요구사항(예: "strip any leading space characters" 또는 "return false and abort these steps")은 알고리즘 도입부에 사용된 핵심 단어("must", "should", "may" 등)의 의미로 해석해야 합니다.

알고리즘이나 특정 단계로 표현된 적합성 요구사항은 결과만 동일하다면 어떤 방식으로 구현해도 됩니다. 특히, 본 명세에 정의된 알고리즘은 이해하기 쉽도록 설계되었으며 성능을 염두에 둔 것이 아닙니다. 구현자는 최적화를 권장합니다.

색인(Index)

이 명세에서 정의한 용어(Terms defined by this specification)

참조에 의해 정의되는 용어(Terms defined by reference)

참고문헌

표준(규범) 참고문헌

[CREDENTIAL-MANAGEMENT-1]
Nina Satragno; Marcos Caceres. 자격 증명 관리 Level 1. 2026년 7월 2일. 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; et al. 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 Object Signing and Encryption (COSE) Algorithms 레지스트리. URL: https://www.iana.org/assignments/cose/cose.xhtml#algorithms
[IANA-WebAuthn-Registries]
Web Authentication (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. Payment Request 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. Web Authentication (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; et al. Web Authentication: 공개 키 자격 증명에 접근하기 위한 API - Level 3. 2026년 5월 26일. CR. URL: https://www.w3.org/TR/webauthn-3/
[WEBCRYPTO-2]
Daniel Huigens. Web Cryptography Level 2. 2025년 4월 22일. FPWD. URL: https://www.w3.org/TR/webcrypto-2/
[WebDriver2]
Simon Stewart; David Burns. WebDriver. 2026년 5월 28일. WD. URL: https://www.w3.org/TR/webdriver2/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 리빙 스탠더드. URL: https://webidl.spec.whatwg.org/

참고(정보) 참고문헌

[BCP47]
A. Phillips, 편집.; M. Davis, 편집.. 언어를 식별하기 위한 태그. 2009년 9월. 최선 현행 관행. URL: https://www.rfc-editor.org/info/rfc5646/
[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/
[RFC4647]
A. Phillips, 편집.; M. Davis, 편집.. 언어 태그의 매칭. 2006년 9월. 최선 현행 관행. URL: https://www.rfc-editor.org/info/rfc4647/
[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;

  // Only used for authentication.
  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을 허용할 수 있습니다. 그런 경우 명세는 Relying Party에게 어떤 URL이 특정 PaymentEntityLogo에 대해 사용자에게 실제 표시되었는지 명확히 알려야 합니다.
명세는 하드웨어 저장소의 알고리즘(주어진 순서)을 우선한 뒤, 소프트웨어의 알고리즘(같은 순서)을 우선하도록 지정할 수도 있습니다. 현재로서는 Chrome이 하드웨어별로 플랫폼당 한 가지 알고리즘만 지원하려 하기 때문에 이 주제가 무의미할 수 있습니다. BBK의 저장 유형 및 허용 가능한 저장 유형, Relying Party에 저장 유형 노출 등 주제를 다루는 Secure Payment Confirmation 이슈 #288을 참조하세요.