Potwierdzenie uwierzytelnienia za pomocą bezpiecznej płatności

Eiji Kitamura
Eiji Kitamura

Sprzedawcy mogą korzystać z potwierdzenie bezpiecznej płatności (SPC) w ramach silnego procesu uwierzytelniania klienta (SCA) w przypadku danej karty kredytowej lub danego konta bankowego. WebAuthn przeprowadza uwierzytelnianie (często za pomocą biometrii). Usługę WebAuthn należy zarejestrować z wyprzedzeniem. Więcej informacji znajdziesz w artykule Rejestrowanie potwierdzenia bezpiecznej płatności.

Jak działa typowa implementacja

Najczęściej są one stosowane, gdy klient dokonuje zakupu w witrynie sprzedawcy, a wydawca karty kredytowej lub bank wymaga uwierzytelnienia płatnika.

Proces uwierzytelniania.

Omówmy proces uwierzytelniania:

  1. Klient podaje sprzedawcy dane uwierzytelniające swoje dane karty kredytowej (np. dane karty kredytowej).
  2. Jeśli płatnik wymaga osobnego uwierzytelniania, sprzedawca prosi o dane uwierzytelniające płatność do odpowiedniego wydawcy lub banku (strony uzależnionej lub RP). Taka wymiana może mieć miejsce np. w przypadku technologii EMV® 3-D Secure.
    • Jeśli grupa z ograniczonym dostępem chce, aby sprzedawca skorzystał z SPC, a użytkownik się wcześniej zarejestrował, usługa odpowiada i zawiera listę identyfikatorów danych uwierzytelniających zarejestrowanych przez płatnika oraz wyzwanie.
    • Jeśli uwierzytelnianie nie jest potrzebne, sprzedawca może kontynuować transakcję.
  3. Jeśli wymagane jest uwierzytelnienie, 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. W przeglądarce pojawi się okno potwierdzenia.
    • Jeśli nie ma żadnych identyfikatorów danych logowania przekazanych z RP, wróć do istniejącego procesu uwierzytelniania. Po udanym uwierzytelnieniu rozważ użycie rejestracji w SPC, aby uprościć uwierzytelnianie w przyszłości.
  5. Użytkownik potwierdza i uwierzytelnia kwotę oraz miejsce docelowe płatności, odblokowując urządzenie.
  6. Sprzedawca otrzymuje dane uwierzytelniające.
  7. Grupa z ograniczonym dostępem otrzymuje od sprzedawcy dane uwierzytelniające i weryfikuje ich autentyczność.
  8. RP wysyła wyniki weryfikacji do sprzedawcy.
  9. Sprzedawca wyświetla użytkownikowi komunikat informujący o tym, czy płatność zakończyła się powodzeniem lub niepowodzeniem.

Wykrywanie funkcji

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

Skopiuj i wklej ten kod, aby wykryć 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.
  }
});

Uwierzytelnij 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 data formy płatnościSecurePaymentConfirmationRequest.

Parametr Opis
rpId Nazwa hosta punktu początkowego grupy objętej ograniczeniami jako identyfikator grupy objętej ograniczeniami.
challenge Jest to losowe wyzwanie, które zapobiega atakom metodą powtórzenia.
credentialIds Tablica identyfikatorów danych logowania. W ramach uwierzytelniania WebAuthn właściwość allowCredentials akceptuje tablicę obiektów PublicKeyCredentialDescriptor, ale w SPC przekazujesz tylko listę identyfikatorów danych logowania.
payeeName (opcjonalnie) nazwę odbiorcy płatności;
payeeOrigin Źródło odbiorcy płatności. W powyższym scenariuszu jest to pochodzenie sprzedawcy.
instrument Ciąg znaków displayName i adres URL w polu icon wskazujący zasób graficzny. Opcjonalna wartość logiczna (domyślnie true) dla parametru iconMustBeShown, która określa, że ikona została 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ści”.

Zobacz ten przykładowy kod:

// 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() powoduje wygenerowanie obiektu PaymentResponse, ale details zawiera dane uwierzytelniające klucza publicznego z clientDataJSON, które zawierają dane transakcji (payment) do weryfikacji przez grupę objętą ograniczeniami.

Uzyskane w ten sposób dane logowania należy przenieść z innej domeny do RP i zweryfikować.

Jak grupa z ograniczonym dostępem weryfikuje transakcję

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

Aby zweryfikować dane transakcji, organizacja z ograniczonym dostępem może przejść proces weryfikacji potwierdzenia uwierzytelniania w WebAuthn. Dodatkowo musi zweryfikować payment.

Przykładowy ładunek komponentu 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 pochodzeniu grupy objętej ograniczeniami.
  • topOrigin odpowiada źródłom najwyższego poziomu oczekiwanym przez grupę z ograniczonym dostępem (pochodzenie sprzedawcy z przykładu powyżej).
  • Wartość payeeOrigin odpowiada źródłom odbiorcy płatności, który powinien być wyświetlony użytkownikowi.
  • total odpowiada kwocie transakcji, która powinna być wyświetlana użytkownikowi.
  • instrument odpowiada danym instrumentu płatniczego, które powinny być wyświetlane 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, grupa z ograniczonym dostępem może poinformować sprzedawcę, że transakcja się powiodła.

Dalsze kroki