Potwierdzenie uwierzytelnienia za pomocą bezpiecznej płatności

Sprzedawcy mogą korzystać z potwierdzenia bezpiecznych płatności (SPC) w ramach silnego uwierzytelniania klienta (SCA) w przypadku danej karty kredytowej lub konta bankowego. WebAuthn przeprowadza uwierzytelnianie (często za pomocą danych biometrycznych). WebAuthn musi być zarejestrowany z wyprzedzeniem. Więcej informacji znajdziesz w artykule Rejestracja potwierdzenia bezpiecznej płatności.

Jak działa typowa implementacja

Najczęściej używa się SPC, gdy klient dokonuje zakupu w witrynie sprzedawcy, a wystawca karty kredytowej lub bank wymaga uwierzytelnienia płatnika.

Proces uwierzytelniania.

Przyjrzyjmy się procesowi uwierzytelniania:

  1. Klient podaje sprzedawcy swoje dane uwierzytelniające płatność (np. dane karty kredytowej).
  2. Jeśli płatnik wymaga osobnego uwierzytelniania, sprzedawca pyta właściwego wystawcę danych uwierzytelniających lub banku (podmiotu uzależnionego lub podmiot zabezpieczeń). Taka wymiana może nastąpić na przykład przy użyciu systemu EMV® 3-D Secure.
    • Jeśli sprzedawca chce, aby sprzedawca używał SPC, a użytkownik wcześniej się zarejestrował, w odpowiedzi przesyła listę identyfikatorów danych logowania zarejestrowanych przez płatnika oraz test zabezpieczający.
    • Jeśli uwierzytelnienie nie jest potrzebne, sprzedawca może kontynuować transakcję.
  3. Jeśli wymagane jest uwierzytelnianie, sprzedawca określa, czy przeglądarka obsługuje SPC.
    • Jeśli przeglądarka nie obsługuje SPC, kontynuuj proces uwierzytelniania.
  4. Sprzedawca wywołuje SPC. Przeglądarka wyświetli okno potwierdzenia.
    • Jeśli do usługi objętej ograniczeniami nie zostały przekazane żadne identyfikatory danych logowania, skorzystaj z dotychczasowego procesu uwierzytelniania. Po udanym uwierzytelnieniu zastanów się nad wykorzystaniem rejestracji SPC w celu usprawnienia przyszłych uwierzytelniania.
  5. Użytkownik potwierdza i uwierzytelnia kwotę oraz miejsce docelowe płatności, odblokowując urządzenie.
  6. Sprzedawca otrzymuje dane logowania z uwierzytelnienia.
  7. RP otrzymuje dokument od sprzedawcy i weryfikuje jego autentyczność.
  8. RP wysyła wyniki weryfikacji do sprzedawcy.
  9. Sprzedawca wyświetla użytkownikowi komunikat informujący o tym, czy płatność została zrealizowana, czy nie.

Wykrywanie cech

Aby sprawdzić, czy przeglądarka obsługuje SPC, możesz wysłać fałszywe wywołanie do canMakePayment().

Skopiuj i wklej ten kod, aby włączyć wykrywanie SPC w witrynie sprzedawcy.

const isSecurePaymentConfirmationSupported = async () => {
  if (!'PaymentRequest' in window) {
    return [false, 'Payment Request API is not supported'];
  }

  try {
    // The data below is the minimum required to create the request and
    // check if a payment can be made.
    const supportedInstruments = [
      {
        supportedMethods: "secure-payment-confirmation",
        data: {
          // RP's hostname as its ID
          rpId: 'rp.example',
          // A dummy credential ID
          credentialIds: [new Uint8Array(1)],
          // A dummy challenge
          challenge: new Uint8Array(1),
          instrument: {
            // Non-empty display name string
            displayName: ' ',
            // Transparent-black pixel.
            icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg==',
          },
          // A dummy merchant origin
          payeeOrigin: 'https://non-existent.example',
        }
      }
    ];

    const details = {
      // Dummy shopping details
      total: {label: 'Total', amount: {currency: 'USD', value: '0'}},
    };

    const request = new PaymentRequest(supportedInstruments, details);
    const canMakePayment = await request.canMakePayment();
    return [canMakePayment, canMakePayment ? '' : 'SPC is not available'];
  } catch (error) {
    console.error(error);
    return [false, error.message];
  }
};

isSecurePaymentConfirmationSupported().then(result => {
  const [isSecurePaymentConfirmationSupported, reason] = result;
  if (isSecurePaymentConfirmationSupported) {
    // Display the payment button that invokes SPC.
  } else {
    // Fallback to the legacy authentication method.
  }
});

Uwierzytelnienie użytkownika

Aby uwierzytelnić użytkownika, wywołaj metodę PaymentRequest.show() z parametrami secure-payment-confirmation i WebAuthn:

Oto parametry, które należy podać we właściwości SecurePaymentConfirmationRequest formy płatności: data.

Parametr Opis
rpId Nazwa hosta punktu początkowego RP jako identyfikator grupy objętej ograniczeniami.
challenge To losowe wyzwanie, które uniemożliwia ponowne odtworzenie ataku.
credentialIds Tablica identyfikatorów danych logowania. W ramach uwierzytelniania WebAuthn właściwość allowCredentials akceptuje tablicę obiektów PublicKeyCredentialDescriptor, ale w SPC przesyła tylko listę identyfikatorów danych logowania.
payeeName (opcjonalnie) Nazwa odbiorcy płatności.
payeeOrigin Miejsce pochodzenia odbiorcy płatności. W powyższym scenariuszu jest to pochodzenie sprzedawcy.
instrument Ciąg znaków dla displayName i adres URL dla icon, który wskazuje zasób obrazu. Opcjonalna wartość logiczna (domyślnie true) dla metody iconMustBeShown określająca, że ikona musi zostać pobrana i wyświetlona, aby żądanie zostało zrealizowane.
timeout Czas oczekiwania na podpisanie transakcji (w milisekundach)
extensions Dodano rozszerzenia do wywołania WebAuthn. Nie musisz samodzielnie określać rozszerzenia „płatność”.

Zapoznaj się z tym przykładowym kodem:

// After confirming SPC is available on this browser via a feature detection,
// fetch the request options cross-origin from the RP server.
const options = fetchFromServer('https://rp.example/spc-auth-request');
const { credentialIds, challenge } = options;

const request = new PaymentRequest([{
  // Specify `secure-payment-confirmation` as payment method.
  supportedMethods: "secure-payment-confirmation",
  data: {
    // The RP ID
    rpId: 'rp.example',

    // List of credential IDs obtained from the RP server.
    credentialIds,

    // The challenge is also obtained from the RP server.
    challenge,

    // A display name and an icon that represent the payment instrument.
    instrument: {
      displayName: "Fancy Card ****1234",
      icon: "https://rp.example/card-art.png",
      iconMustBeShown: false
    },

    // The origin of the payee (merchant)
    payeeOrigin: "https://merchant.example",

    // The number of milliseconds to timeout.
    timeout: 360000,  // 6 minutes
  }
}], {
  // Payment details.
  total: {
    label: "Total",
    amount: {
      currency: "USD",
      value: "5.00",
    },
  },
});

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

  // response.details is a PublicKeyCredential, with a clientDataJSON that
  // contains the transaction data for verification by the issuing bank.
  // Make sure to serialize the binary part of the credential before
  // transferring to the server.
  const result = fetchFromServer('https://rp.example/spc-auth-response', response.details);
  if (result.success) {
    await response.complete('success');
  } else {
    await response.complete('fail');
  }
} catch (err) {
  // SPC cannot be used; merchant should fallback to traditional flows
  console.error(err);
}

Funkcja .show() zwraca obiekt PaymentResponse, ale details zawiera dane uwierzytelniające klucza publicznego z clientDataJSON, który zawiera dane transakcji (payment) na potrzeby weryfikacji przez RP.

Otrzymane dane logowania należy przenieść z innych domen do RP i zweryfikować.

Jak RP weryfikuje transakcję

Zweryfikowanie danych transakcji na serwerze RP jest najważniejszym etapem procesu płatności.

Aby zweryfikować dane transakcji, w RPA może przejść proces weryfikacji potwierdzenia uwierzytelniania WebAuthn. Musi też zweryfikować payment.

Przykładowy ładunek elementu clientDataJSON:

{
  "type":"payment.get",
  "challenge":"SAxYy64IvwWpoqpr8JV1CVLHDNLKXlxbtPv4Xg3cnoc",
  "origin":"https://spc-merchant.glitch.me",
  "crossOrigin":false,
  "payment":{
    "rp":"spc-rp.glitch.me",
    "topOrigin":"https://spc-merchant.glitch.me",
    "payeeOrigin":"https://spc-merchant.glitch.me",
    "total":{
      "value":"15.00",
      "currency":"USD"
    },
    "instrument":{
      "icon":"https://cdn.glitch.me/94838ffe-241b-4a67-a9e0-290bfe34c351%2Fbank.png?v=1639111444422",
      "displayName":"Fancy Card 825809751248"
    }
  }
}
  • rp odpowiada punktowi pochodzenia grupy objętej ograniczeniami.
  • topOrigin pasuje do źródła najwyższego poziomu, którego oczekuje dana grupa objęte ograniczeniami (pochodzenie sprzedawcy w przykładzie powyżej).
  • Pole payeeOrigin jest zgodne z pierwotnym adresem odbiorcy płatności, który powinien się wyświetlić użytkownikowi.
  • total odpowiada kwocie transakcji, która powinna zostać wyświetlona użytkownikowi.
  • instrument odpowiada szczegółami instrumentu płatności, które powinny zostać wyświetlone użytkownikowi.
const clientData = base64url.decode(response.clientDataJSON);
const clientDataJSON = JSON.parse(clientData);

if (!clientDataJSON.payment) {
  throw 'The credential does not contain payment payload.';
}

const payment = clientDataJSON.payment;
if (payment.rp !== expectedRPID ||
    payment.topOrigin !== expectedOrigin ||
    payment.payeeOrigin !== expectedOrigin ||
    payment.total.value !== '15.00' ||
    payment.total.currency !== 'USD') {
  throw 'Malformed payment information.';
}

Gdy wszystkie kryteria weryfikacji zostaną spełnione, RP może powiadomić sprzedawcę, że transakcja się powiodła.

Dalsze kroki