Repository: StellarCN/py-stellar-base

Issue:
SEP-10 v3.1 Changes (from the SDF)
## SEP-10 3.1 Support

### TL;DR

Implement the changes described the [SEP-10 3.1 commit](https://github.com/stellar/stellar-protocol/commit/6c8c9cf6685c85509835188a136ffb8cd6b9c11c).

This likely involves adding an optional argument to the SEP-10 utility functions for adding an additional Manage Data operation containing the domain of the SEP-10 server (`web_auth_domain`).

### Background & Description

Thank you for implementing [SEP-10 v3.0](9d121f9), which reintroduced verification of the home domain of the service requiring SEP-10 authentication, ensuring that signed challenges cannot be used for any other service.

SEP-10 v3.1 adds an optional Manage Data operation that includes the home domain of the service issuing SEP-10 challenges. This allows clients and servers to verify the issuer of the challenge.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422?src=pr&el=h1) Report
> Merging [#422](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422?src=pr&el=desc) (c0b0c60) into [v2-dev](https://codecov.io/gh/StellarCN/py-stellar-base/commit/4aa7982ab5f3416ecdc4bc8920c6fa0decb180ee?el=desc) (4aa7982) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422/graphs/tree.svg?width=650&height=150&src=pr&token=kHAKcotfqv)](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           v2-dev     #422   +/-   ##
=======================================
  Coverage   99.05%   99.06%           
=======================================
  Files         127      127           
  Lines        7708     7780   +72     
=======================================
+ Hits         7635     7707   +72     
  Misses         73       73           
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `99.06% <100.00%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [stellar\_sdk/sep/stellar\_web\_authentication.py](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422/diff?src=pr&el=tree#diff-c3RlbGxhcl9zZGsvc2VwL3N0ZWxsYXJfd2ViX2F1dGhlbnRpY2F0aW9uLnB5) | `93.29% <100.00%> (+0.08%)` | :arrow_up: |
| [tests/sep/test\_stellar\_web\_authentication.py](https://codecov.io/gh/StellarCN/py-stellar-base/pull/422/diff?src=pr&el=tree#diff-dGVzdHMvc2VwL3Rlc3Rfc3RlbGxhcl93ZWJfYXV0aGVudGljYXRpb24ucHk=) | `100.00% <100.00%> (ø)` | |


Patch:
diff --git a/stellar_sdk/sep/stellar_web_authentication.py b/stellar_sdk/sep/stellar_web_authentication.py
index 05b1f569..32315a29 100644
--- a/stellar_sdk/sep/stellar_web_authentication.py
+++ b/stellar_sdk/sep/stellar_web_authentication.py
@@ -40,6 +40,7 @@ def build_challenge_transaction(
     server_secret: str,
     client_account_id: str,
     home_domain: str,
+    web_auth_domain: str,
     network_passphrase: str,
     timeout: int = 900,
 ) -> str:
@@ -50,6 +51,7 @@ def build_challenge_transaction(
     :param client_account_id: The stellar account that the wallet wishes to authenticate with the server.
     :param home_domain: The `fully qualified domain name <https://en.wikipedia.org/wiki/Fully_qualified_home_domain>`_
         of the service requiring authentication, for example: `example.com`.
+    :param web_auth_domain: The fully qualified domain name of the service issuing the challenge.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
     :param timeout: Challenge duration in seconds (default to 15 minutes).
@@ -71,6 +73,10 @@ def build_challenge_transaction(
         data_name=f"{home_domain} auth",
         data_value=nonce_encoded,
         source=client_account_id,
+    ).append_manage_data_op(
+        data_name="web_auth_domain",
+        data_value=web_auth_domain,
+        source=server_account.account_id,
     )
     transaction = transaction_builder.build()
     transaction.sign(server_keypair)
@@ -81,6 +87,7 @@ def read_challenge_transaction(
     challenge_transaction: str,
     server_account_id: str,
     home_domains: Union[str, Iterable[str]],
+    web_auth_domain: str,
     network_passphrase: str,
 ) -> Tuple[TransactionEnvelope, str, str]:
     """Reads a SEP 10 challenge transaction and returns the decoded transaction envelope and client account ID contained within.
@@ -97,6 +104,8 @@ def read_challenge_transaction(
     :param server_account_id: public key for server's account.
     :param home_domains: The home domain that is expected to be included in the first Manage Data operation's string
         key. If a list is provided, one of the domain names in the array must match.
+    :param web_auth_domain: The home domain that is expected to be included as the value of the Manage Data operation with
+        the 'web_auth_domain' key. If no such operation is included, this parameter is not used.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
     :raises: :exc:`InvalidSep10ChallengeError <stellar_sdk.sep.exceptions.InvalidSep10ChallengeError>` - if the
@@ -187,9 +196,7 @@ def read_challenge_transaction(
         )
 
     if manage_data_op.data_value is None:
-        raise InvalidSep10ChallengeError(
-            "Operation value should not be null."
-        )
+        raise InvalidSep10ChallengeError("Operation value should not be null.")
 
     if len(manage_data_op.data_value) != 64:
         raise InvalidSep10ChallengeError(
@@ -212,6 +219,15 @@ def read_challenge_transaction(
             raise InvalidSep10ChallengeError(
                 "The transaction has operations that are unrecognized."
             )
+        if op.data_value is None:
+            raise InvalidSep10ChallengeError("Operation value should not be null.")
+        if (
+            op.data_name == "web_auth_domain"
+            and op.data_value != web_auth_domain.encode()
+        ):
+            raise InvalidSep10ChallengeError(
+                f"'web_auth_domain' operation value does not match {web_auth_domain}."
+            )
 
     # verify that transaction envelope has a correct signature by server's signing key
     if not _verify_te_signed_by_account_id(transaction_envelope, server_account_id):
@@ -227,6 +243,7 @@ def verify_challenge_transaction_signers(
     challenge_transaction: str,
     server_account_id: str,
     home_domains: Union[str, Iterable[str]],
+    web_auth_domain: str,
     network_passphrase: str,
     signers: List[Ed25519PublicKeySigner],
 ) -> List[Ed25519PublicKeySigner]:
@@ -242,6 +259,8 @@ def verify_challenge_transaction_signers(
     :param server_account_id: public key for server's account.
     :param home_domains: The home domain that is expected to be included in the first Manage Data operation's string
         key. If a list is provided, one of the domain names in the array must match.
+    :param web_auth_domain: The home domain that is expected to be included as the value of the Manage Data
+        operation with the 'web_auth_domain' key, if present.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
     :param signers: The signers of client account.
@@ -254,7 +273,11 @@ def verify_challenge_transaction_signers(
         raise InvalidSep10ChallengeError("No signers provided.")
 
     te, _, _ = read_challenge_transaction(
-        challenge_transaction, server_account_id, home_domains, network_passphrase
+        challenge_transaction,
+        server_account_id,
+        home_domains,
+        web_auth_domain,
+        network_passphrase,
     )
     server_keypair = Keypair.from_public_key(server_account_id)
 
@@ -310,6 +333,7 @@ def verify_challenge_transaction_signed_by_client(
     challenge_transaction: str,
     server_account_id: str,
     home_domains: Union[str, Iterable[str]],
+    web_auth_domain: str,
     network_passphrase: str,
 ) -> None:
     """An alias for :func:`stellar_sdk.sep.stellar_web_authentication.verify_challenge_transaction`.
@@ -318,6 +342,8 @@ def verify_challenge_transaction_signed_by_client(
     :param server_account_id: public key for server's account.
     :param home_domains: The home domain that is expected to be included in the first Manage Data operation's string
         key. If a list is provided, one of the domain names in the array must match.
+    :param web_auth_domain: The home domain that is expected to be included as the value of the Manage Data operation with
+        the 'web_auth_domain' key. If no such operation is included, this parameter is not used.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
 
@@ -331,7 +357,11 @@ def verify_challenge_transaction_signed_by_client(
     )  # pragma: no cover
 
     return verify_challenge_transaction_signed_by_client_master_key(
-        challenge_transaction, server_account_id, home_domains, network_passphrase
+        challenge_transaction,
+        server_account_id,
+        home_domains,
+        web_auth_domain,
+        network_passphrase,
     )  # pragma: no cover
 
 
@@ -339,6 +369,7 @@ def verify_challenge_transaction_signed_by_client_master_key(
     challenge_transaction: str,
     server_account_id: str,
     home_domains: Union[str, Iterable[str]],
+    web_auth_domain: str,
     network_passphrase: str,
 ) -> None:
     """An alias for :func:`stellar_sdk.sep.stellar_web_authentication.verify_challenge_transaction`.
@@ -347,6 +378,8 @@ def verify_challenge_transaction_signed_by_client_master_key(
     :param server_account_id: public key for server's account.
     :param home_domains: The home domain that is expected to be included in the first Manage Data operation's string
         key. If a list is provided, one of the domain names in the array must match.
+    :param web_auth_domain: The home domain that is expected to be included as the value of the Manage Data operation with
+        the 'web_auth_domain' key. If no such operation is included, this parameter is not used.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
 
@@ -355,7 +388,11 @@ def verify_challenge_transaction_signed_by_client_master_key(
     """
 
     return verify_challenge_transaction(
-        challenge_transaction, server_account_id, home_domains, network_passphrase
+        challenge_transaction,
+        server_account_id,
+        home_domains,
+        web_auth_domain,
+        network_passphrase,
     )
 
 
@@ -363,6 +400,7 @@ def verify_challenge_transaction_threshold(
     challenge_transaction: str,
     server_account_id: str,
     home_domains: Union[str, Iterable[str]],
+    web_auth_domain: str,
     network_passphrase: str,
     threshold: int,
     signers: List[Ed25519PublicKeySigner],
@@ -378,6 +416,8 @@ def verify_challenge_transaction_threshold(
     :param server_account_id: public key for server's account.
     :param home_domains: The home domain that is expected to be included in the first Manage Data operation's string
         key. If a list is provided, one of the domain names in the array must match.
+    :param web_auth_domain: The home domain that is expected to be included as the value of the Manage Data operation with
+        the 'web_auth_domain' key. If no such operation is included, this parameter is not used.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
     :param threshold: The medThreshold on the client account.
@@ -392,6 +432,7 @@ def verify_challenge_transaction_threshold(
         challenge_transaction,
         server_account_id,
         home_domains,
+        web_auth_domain,
         network_passphrase,
         signers,
     )
@@ -409,6 +450,7 @@ def verify_challenge_transaction(
     challenge_transaction: str,
     server_account_id: str,
     home_domains: Union[str, Iterable[str]],
+    web_auth_domain: str,
     network_passphrase: str,
 ) -> None:
     """Verifies if a transaction is a valid
@@ -428,6 +470,8 @@ def verify_challenge_transaction(
     :param server_account_id: public key for server's account.
     :param home_domains: The home domain that is expected to be included in the first Manage Data operation's string
         key. If a list is provided, one of the domain names in the array must match.
+    :param web_auth_domain: The home domain that is expected to be included as the value of the Manage Data
+        operation with the 'web_auth_domain' key, if present.
     :param network_passphrase: The network to connect to for verifying and retrieving
         additional attributes from. (ex. 'Public Global Stellar Network ; September 2015')
     :raises: :exc:`InvalidSep10ChallengeError <stellar_sdk.sep.exceptions.InvalidSep10ChallengeError>` - if the
@@ -435,13 +479,18 @@ def verify_challenge_transaction(
     """
 
     _, client_account_id, _ = read_challenge_transaction(
-        challenge_transaction, server_account_id, home_domains, network_passphrase
+        challenge_transaction,
+        server_account_id,
+        home_domains,
+        web_auth_domain,
+        network_passphrase,
     )
     signers = [Ed25519PublicKeySigner(client_account_id, 255)]
     verify_challenge_transaction_signers(
         challenge_transaction,
         server_account_id,
         home_domains,
+        web_auth_domain,
         network_passphrase,
         signers,
     )


Test patch:
diff --git a/tests/sep/test_stellar_web_authentication.py b/tests/sep/test_stellar_web_authentication.py
index 47191995..251cd6d3 100644
--- a/tests/sep/test_stellar_web_authentication.py
+++ b/tests/sep/test_stellar_web_authentication.py
@@ -29,11 +29,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_account_id,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -41,13 +43,19 @@ class TestStellarWebAuthentication:
         transaction = TransactionEnvelope.from_xdr(
             challenge, network_passphrase
         ).transaction
-        assert len(transaction.operations) == 1
-        op = transaction.operations[0]
-        assert isinstance(op, ManageData)
-        assert op.data_name == f"{home_domain} auth"
-        assert len(op.data_value) == 64
-        assert len(base64.b64decode(op.data_value)) == 48
-        assert op.source == client_account_id
+        assert len(transaction.operations) == 2
+        op0 = transaction.operations[0]
+        assert isinstance(op0, ManageData)
+        assert op0.data_name == f"{home_domain} auth"
+        assert len(op0.data_value) == 64
+        assert len(base64.b64decode(op0.data_value)) == 48
+        assert op0.source == client_account_id
+
+        op1 = transaction.operations[1]
+        assert isinstance(op1, ManageData)
+        assert op1.data_name == "web_auth_domain"
+        assert op1.data_value.decode() == web_auth_domain
+        assert op1.source == server_kp.public_key
 
         now = int(time.time())
         assert now - 3 < transaction.time_bounds.min_time < now + 3
@@ -64,11 +72,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -77,7 +87,11 @@ class TestStellarWebAuthentication:
         transaction.sign(client_kp)
         challenge_tx = transaction.to_xdr()
         verify_challenge_transaction(
-            challenge_tx, server_kp.public_key, home_domain, network_passphrase
+            challenge_tx,
+            server_kp.public_key,
+            home_domain,
+            web_auth_domain,
+            network_passphrase,
         )
 
     def test_verify_challenge_transaction_with_multi_domain_names(self):
@@ -86,11 +100,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -102,7 +118,8 @@ class TestStellarWebAuthentication:
             challenge_tx,
             server_kp.public_key,
             ["example.com2", "example.com1", home_domain],
-            network_passphrase
+            web_auth_domain,
+            network_passphrase,
         )
 
     def test_verify_challenge_transaction_with_multi_domain_names_not_include(self):
@@ -111,11 +128,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -131,7 +150,8 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 ["example.com2", "example.com1"],
-                network_passphrase
+                web_auth_domain,
+                network_passphrase,
             )
 
     def test_verify_challenge_transaction_with_empty_domain_names(self):
@@ -140,11 +160,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -160,7 +182,8 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 [],
-                network_passphrase
+                web_auth_domain,
+                network_passphrase,
             )
 
     def test_verify_challenge_tx_sequence_not_zero(self):
@@ -168,6 +191,8 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
+
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -179,6 +204,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, now + 900)
             .build()
         )
@@ -195,6 +225,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -203,9 +234,14 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
-            server_kp.secret, client_kp.public_key, home_domain, network_passphrase
+            server_kp.secret,
+            client_kp.public_key,
+            home_domain,
+            web_auth_domain,
+            network_passphrase,
         )
 
         transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase)
@@ -220,6 +256,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 Keypair.random().public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -228,6 +265,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         server_account = Account(server_kp.public_key, -1)
         challenge_te = (
@@ -248,6 +286,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -256,6 +295,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -265,6 +305,11 @@ class TestStellarWebAuthentication:
             .append_manage_data_op(
                 data_name="{} auth".format(home_domain), data_value=nonce_encoded
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, now + 900)
             .build()
         )
@@ -280,14 +325,16 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
-    def test_verify_challenge_tx_operation_value_is_none(self):
+    def test_verify_challenge_tx_first_operation_value_is_none(self):
         server_kp = Keypair.random()
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce_encoded = None
         server_account = Account(server_kp.public_key, -1)
@@ -298,6 +345,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, now + 900)
             .build()
         )
@@ -307,13 +359,54 @@ class TestStellarWebAuthentication:
         challenge_tx_signed = challenge_te.to_xdr()
 
         with pytest.raises(
-            InvalidSep10ChallengeError,
-            match="Operation value should not be null.",
+            InvalidSep10ChallengeError, match="Operation value should not be null.",
+        ):
+            verify_challenge_transaction(
+                challenge_tx_signed,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
+                network_passphrase,
+            )
+
+    def test_verify_challenge_tx_not_first_operation_value_is_none(self):
+        server_kp = Keypair.random()
+        client_kp = Keypair.random()
+        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
+        home_domain = "example.com"
+        web_auth_domain = None
+        now = int(time.time())
+        nonce = os.urandom(48)
+        nonce_encoded = base64.b64encode(nonce)
+        server_account = Account(server_kp.public_key, -1)
+        challenge_te = (
+            TransactionBuilder(server_account, network_passphrase, 100)
+            .append_manage_data_op(
+                data_name="{} auth".format(home_domain),
+                data_value=nonce_encoded,
+                source=client_kp.public_key,
+            )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
+            .add_time_bounds(now, now + 900)
+            .build()
+        )
+
+        challenge_te.sign(server_kp)
+        challenge_te.sign(client_kp)
+        challenge_tx_signed = challenge_te.to_xdr()
+
+        with pytest.raises(
+            InvalidSep10ChallengeError, match="Operation value should not be null.",
         ):
             verify_challenge_transaction(
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -322,6 +415,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(32)
         nonce_encoded = base64.b64encode(nonce)
@@ -333,6 +427,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, now + 900)
             .build()
         )
@@ -349,6 +448,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -357,6 +457,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         timeout = 900
 
         now = int(time.time())
@@ -372,6 +473,10 @@ class TestStellarWebAuthentication:
             data_name="{} auth".format(home_domain),
             data_value=nonce_encoded,
             source=client_kp.public_key,
+        ).append_manage_data_op(
+            data_name="web_auth_domain",
+            data_value=web_auth_domain,
+            source=server_account.account_id,
         )
         challenge = transaction_builder.build().to_xdr()
 
@@ -383,7 +488,11 @@ class TestStellarWebAuthentication:
             match="Transaction not signed by server: {}".format(server_kp.public_key),
         ):
             verify_challenge_transaction(
-                challenge_tx, server_kp.public_key, home_domain, network_passphrase
+                challenge_tx,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
+                network_passphrase,
             )
 
     def test_verify_challenge_tx_transaction_is_not_signed_by_the_client(self):
@@ -392,11 +501,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.TESTNET_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_account_id,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -406,7 +517,11 @@ class TestStellarWebAuthentication:
             match="Transaction not signed by any client signer.",
         ):
             verify_challenge_transaction(
-                challenge, server_kp.public_key, home_domain, network_passphrase
+                challenge,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
+                network_passphrase,
             )
 
     def test_verify_challenge_tx_dont_contains_timebound(self):
@@ -414,6 +529,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
         server_account = Account(server_kp.public_key, -1)
@@ -424,6 +540,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .build()
         )
 
@@ -438,6 +559,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -446,6 +568,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -457,6 +580,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, 0)
             .build()
         )
@@ -473,6 +601,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -481,6 +610,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -492,6 +622,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now - 100, now - 50)
             .build()
         )
@@ -508,6 +643,85 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
+                network_passphrase,
+            )
+
+    def test_verify_challenge_transaction_auth_domain_mismatch_raise(self):
+        server_kp = Keypair.random()
+        client_kp = Keypair.random()
+        timeout = 600
+        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
+        home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
+        mismatch_web_auth_domain = "mismatch_auth.example.com"
+
+        challenge = build_challenge_transaction(
+            server_secret=server_kp.secret,
+            client_account_id=client_kp.public_key,
+            home_domain=home_domain,
+            web_auth_domain=mismatch_web_auth_domain,
+            network_passphrase=network_passphrase,
+            timeout=timeout,
+        )
+
+        transaction = TransactionEnvelope.from_xdr(challenge, network_passphrase)
+        transaction.sign(client_kp)
+        challenge_tx = transaction.to_xdr()
+        with pytest.raises(
+            InvalidSep10ChallengeError,
+            match=f"'web_auth_domain' operation value does not match {web_auth_domain}.",
+        ):
+            verify_challenge_transaction(
+                challenge_tx,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
+                network_passphrase,
+            )
+
+    def test_verify_challenge_transaction_auth_domain_op_source_not_equal_server_account_raise(
+        self,
+    ):
+        server_kp = Keypair.random()
+        client_kp = Keypair.random()
+        network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
+        home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
+
+        now = int(time.time())
+        nonce = os.urandom(48)
+        nonce_encoded = base64.b64encode(nonce)
+        server_account = Account(server_kp.public_key, -1)
+        challenge_te = (
+            TransactionBuilder(server_account, network_passphrase, 100)
+            .append_manage_data_op(
+                data_name="{} auth".format(home_domain),
+                data_value=nonce_encoded,
+                source=client_kp.public_key,
+            )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=client_kp.public_key,
+            )
+            .add_time_bounds(now, now + 900)
+            .build()
+        )
+
+        challenge_te.sign(server_kp)
+        challenge_te.sign(client_kp)
+        challenge_tx_signed = challenge_te.to_xdr()
+
+        with pytest.raises(
+            InvalidSep10ChallengeError,
+            match="The transaction has operations that are unrecognized.",
+        ):
+            verify_challenge_transaction(
+                challenge_tx_signed,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -518,11 +732,13 @@ class TestStellarWebAuthentication:
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
         invalid_home_domain = "invalid_example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -539,6 +755,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 invalid_home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -549,6 +766,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -560,11 +778,21 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .append_manage_data_op(
                 data_name="data key",
                 data_value="data value",
                 source=server_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, now + 900)
             .build()
         )
@@ -574,7 +802,11 @@ class TestStellarWebAuthentication:
         challenge_tx_signed = challenge_te.to_xdr()
 
         verify_challenge_transaction(
-            challenge_tx_signed, server_kp.public_key, home_domain, network_passphrase,
+            challenge_tx_signed,
+            server_kp.public_key,
+            home_domain,
+            web_auth_domain,
+            network_passphrase,
         )
 
     def test_verify_challenge_tx_contain_subsequent_manage_data_ops_without_the_server_account_as_the_source_account(
@@ -584,6 +816,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -595,6 +828,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .append_manage_data_op(
                 data_name="data key",
                 data_value="data value",
@@ -616,6 +854,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -626,6 +865,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -637,6 +877,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .append_bump_sequence_op(bump_to=0, source=server_kp.public_key,)
             .add_time_bounds(now, now + 900)
             .build()
@@ -653,6 +898,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -663,6 +909,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -674,6 +921,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .append_manage_data_op(data_name="Hello", data_value="world")
             .add_time_bounds(now, now + 900)
             .build()
@@ -690,6 +942,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -698,6 +951,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         server_account = Account(server_kp.public_key, -1)
@@ -719,6 +973,7 @@ class TestStellarWebAuthentication:
                 challenge_tx_signed,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
             )
 
@@ -730,11 +985,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -761,6 +1018,7 @@ class TestStellarWebAuthentication:
         client_kp = Keypair.random()
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
         now = int(time.time())
         nonce = os.urandom(48)
         nonce_encoded = base64.b64encode(nonce)
@@ -772,6 +1030,11 @@ class TestStellarWebAuthentication:
                 data_value=nonce_encoded,
                 source=client_kp.public_key,
             )
+            .append_manage_data_op(
+                data_name="web_auth_domain",
+                data_value=web_auth_domain,
+                source=server_account.account_id,
+            )
             .add_time_bounds(now, now + 900)
             .build()
         )
@@ -790,11 +1053,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -812,7 +1077,12 @@ class TestStellarWebAuthentication:
             Ed25519PublicKeySigner(Keypair.random().public_key, 255),
         ]
         signers_found = verify_challenge_transaction_signers(
-            challenge_tx, server_kp.public_key, home_domain, network_passphrase, signers
+            challenge_tx,
+            server_kp.public_key,
+            home_domain,
+            web_auth_domain,
+            network_passphrase,
+            signers,
         )
         assert signers_found == [
             Ed25519PublicKeySigner(client_kp_a.public_key, 1),
@@ -828,11 +1098,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -850,6 +1122,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
                 signers,
             )
@@ -862,11 +1135,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -891,6 +1166,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
                 signers,
             )
@@ -903,11 +1179,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -933,6 +1211,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
                 signers,
             )
@@ -947,11 +1226,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -976,6 +1257,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
                 signers,
             )
@@ -986,11 +1268,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -1001,7 +1285,11 @@ class TestStellarWebAuthentication:
         challenge_tx = transaction.to_xdr()
 
         verify_challenge_transaction_signed_by_client_master_key(
-            challenge_tx, server_kp.public_key, home_domain, network_passphrase
+            challenge_tx,
+            server_kp.public_key,
+            home_domain,
+            web_auth_domain,
+            network_passphrase,
         )
 
     def test_verify_challenge_transaction_signed_by_client_raise_not_signed(self):
@@ -1010,11 +1298,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -1027,7 +1317,11 @@ class TestStellarWebAuthentication:
             match="Transaction not signed by any client signer.",
         ):
             verify_challenge_transaction_signed_by_client_master_key(
-                challenge_tx, server_kp.public_key, home_domain, network_passphrase
+                challenge_tx,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
+                network_passphrase,
             )
 
     def test_verify_challenge_transaction_threshold(self):
@@ -1038,11 +1332,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -1064,6 +1360,7 @@ class TestStellarWebAuthentication:
             challenge_tx,
             server_kp.public_key,
             home_domain,
+            web_auth_domain,
             network_passphrase,
             med_threshold,
             signers,
@@ -1082,11 +1379,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -1112,6 +1411,7 @@ class TestStellarWebAuthentication:
                 challenge_tx,
                 server_kp.public_key,
                 home_domain,
+                web_auth_domain,
                 network_passphrase,
                 med_threshold,
                 signers,
@@ -1125,6 +1425,8 @@ class TestStellarWebAuthentication:
         destination = "GDQERENWDDSQZS7R7WKHZI3BSOYMV3FSWR7TFUYFTKQ447PIX6NREOJM"
         amount = "2000.0000000"
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
+
         inner_tx = (
             TransactionBuilder(
                 inner_source, Network.TESTNET_NETWORK_PASSPHRASE, 200, v1=True
@@ -1154,6 +1456,7 @@ class TestStellarWebAuthentication:
                 challenge,
                 inner_keypair.public_key,
                 home_domain,
+                web_auth_domain,
                 Network.TESTNET_NETWORK_PASSPHRASE,
             )
 
@@ -1167,11 +1470,13 @@ class TestStellarWebAuthentication:
         timeout = 600
         network_passphrase = Network.PUBLIC_NETWORK_PASSPHRASE
         home_domain = "example.com"
+        web_auth_domain = "auth.example.com"
 
         challenge = build_challenge_transaction(
             server_secret=server_kp.secret,
             client_account_id=client_kp_a.public_key,
             home_domain=home_domain,
+            web_auth_domain=web_auth_domain,
             network_passphrase=network_passphrase,
             timeout=timeout,
         )
@@ -1185,5 +1490,9 @@ class TestStellarWebAuthentication:
             InvalidSep10ChallengeError, match="Transaction has unrecognized signatures."
         ):
             verify_challenge_transaction_signed_by_client_master_key(
-                challenge_tx, server_kp.public_key, home_domain, network_passphrase
+                challenge_tx,
+                server_kp.public_key,
+                home_domain,
+                web_auth_domain,
+                network_passphrase,
             )