1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
import pytest
from fido2.client import Fido2Client
from fido2.ctap2.extensions import (
PaymentCredentialInstrument,
PaymentCurrencyAmount,
ThirdPartyPaymentExtension,
)
from fido2.payment import (
CollectedClientAdditionalPaymentData,
PaymentClientDataCollector,
)
from fido2.server import Fido2Server
from . import TEST_PIN, CliInteraction
@pytest.fixture(autouse=True, scope="module")
def preconditions(dev_manager):
if "thirdPartyPayment" not in dev_manager.info.extensions:
pytest.skip("thirdPartyPayment not supported by authenticator")
def test_payment_extension(device, printer):
rp = {"id": "example.com", "name": "Example RP"}
server = Fido2Server(rp)
user = {"id": b"user_id", "name": "A. User"}
# Prepare parameters for makeCredential
create_options, state = server.register_begin(
user,
resident_key_requirement="required",
user_verification="required",
authenticator_attachment="cross-platform",
)
client = Fido2Client(
device,
client_data_collector=PaymentClientDataCollector("https://example.com"),
user_interaction=CliInteraction(printer, TEST_PIN),
extensions=[ThirdPartyPaymentExtension()],
)
# Create a credential
result = client.make_credential(
{
**create_options["publicKey"],
"extensions": {"payment": {"isPayment": True}},
}
)
# Complete registration
auth_data = server.register_complete(state, result)
credentials = [auth_data.credential_data]
print("Payment credential created!")
# Prepare parameters for getAssertion
request_options, state = server.authenticate_begin(
credentials, user_verification="required"
)
# Prepare payment options
payment = CollectedClientAdditionalPaymentData(
rp_id="example.com",
top_origin="https://top.example.com",
payee_name="Mr. Payee",
payee_origin="https://payee.example.com",
total=PaymentCurrencyAmount(
currency="USD",
value="1.00",
),
instrument=PaymentCredentialInstrument(
display_name="My Payment",
icon="https://example.com/icon.png",
),
)
# Authenticate the credential
result = client.get_assertion(
{
**request_options["publicKey"],
"extensions": {
"payment": dict(payment, isPayment=True),
},
}
)
# Only one cred in allowCredentials, only one response.
result = result.get_response(0)
# Verify that the key includes the payment extension
assert result.response.authenticator_data.extensions["thirdPartyPayment"] is True
# Verify that the client has added the payment data
assert result.response.client_data.type == "payment.get"
assert result.response.client_data.payment == payment
|