Skip to content

Commit ff19ab8

Browse files
authored
[py] fix: SecurityError: Invalid Domain problem (#10653)
* [py] fix: Fixed the Invalid Domain error while executing JS - Fixed the Invalid Domain error while executing JS in Virtual Authenticator tests. - Added more tests for Virtual Authenticator. - Updated SimpleWebserver to use 'localhost' instead of '127.0.0.1' - added tests for removing credential using bytearray - replaced Int8Array with Uint8Array in registercredential return since python bytearray accepts range(0,256)
1 parent 7f6a93e commit ff19ab8

6 files changed

Lines changed: 226 additions & 111 deletions

File tree

common/src/web/virtual-authenticator.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ <h1>Virtual Authenticator Tests</h1>
1919
options=Object.assign({
2020
authenticatorSelection: {
2121
requireResidentKey: false,
22-
userVerification: 'preferred'
2322
},
2423
rp: {
2524
id: "localhost",
@@ -41,7 +40,7 @@ <h1>Virtual Authenticator Tests</h1>
4140
status: "OK",
4241
credential: {
4342
id: credential.id,
44-
rawId: Array.from(new Int8Array(credential.rawId)),
43+
rawId: Array.from(new Uint8Array(credential.rawId)),
4544
transports: credential.response.getTransports(),
4645
}
4746
};
@@ -62,7 +61,7 @@ <h1>Virtual Authenticator Tests</h1>
6261
return {
6362
status: "OK",
6463
attestation: {
65-
userHandle: new Int8Array(attestation.response.userHandle),
64+
userHandle: new Uint8Array(attestation.response.userHandle),
6665
},
6766
};
6867
} catch(error) {

py/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ def pytest_exception_interact(node, call, report):
187187
@pytest.fixture
188188
def pages(driver, webserver):
189189
class Pages:
190-
def url(self, name):
191-
return webserver.where_is(name)
190+
def url(self, name, localhost=False):
191+
return webserver.where_is(name, localhost)
192192

193193
def load(self, name):
194194
driver.get(self.url(name))

py/selenium/webdriver/common/virtual_authenticator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,12 @@ def to_dict(self):
223223

224224
@classmethod
225225
def from_dict(cls, data):
226-
_id = urlsafe_b64decode(data['credentialId'])
226+
_id = urlsafe_b64decode(f"{data['credentialId']}==")
227227
is_resident_credential = bool(data['isResidentCredential'])
228-
rp_id = str(data['rpId'])
229-
private_key = urlsafe_b64decode(data['privateKey'])
228+
rp_id = data.get('rpId', None)
229+
private_key = urlsafe_b64decode(f"{data['privateKey']}==")
230230
sign_count = int(data['signCount'])
231-
user_handle = urlsafe_b64decode(data['userHandle']) \
231+
user_handle = urlsafe_b64decode(f"{data['userHandle']}==") \
232232
if data.get('userHandle', None) else None
233233

234234
return cls(_id, is_resident_credential, rp_id, user_handle, private_key, sign_count)

py/selenium/webdriver/remote/webdriver.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import warnings
2929

3030
from abc import ABCMeta
31-
from base64 import b64decode
31+
from base64 import b64decode, urlsafe_b64encode
3232
from contextlib import asynccontextmanager, contextmanager
3333

3434
from .bidi_connection import BidiConnection
@@ -1612,21 +1612,21 @@ def _get_cdp_details(self):
16121612
return version, websocket_url
16131613

16141614
# Virtual Authenticator Methods
1615-
def add_virtual_authenticator(self, options: VirtualAuthenticatorOptions):
1615+
def add_virtual_authenticator(self, options: VirtualAuthenticatorOptions) -> None:
16161616
"""
16171617
Adds a virtual authenticator with the given options.
16181618
"""
16191619
self._authenticator_id = self.execute(Command.ADD_VIRTUAL_AUTHENTICATOR, options.to_dict())['value']
16201620

16211621
@property
1622-
def virtual_authenticator_id(self):
1622+
def virtual_authenticator_id(self) -> str:
16231623
"""
16241624
Returns the id of the virtual authenticator.
16251625
"""
16261626
return self._authenticator_id
16271627

16281628
@required_virtual_authenticator
1629-
def remove_virtual_authenticator(self):
1629+
def remove_virtual_authenticator(self) -> None:
16301630
"""
16311631
Removes a previously added virtual authenticator. The authenticator is no
16321632
longer valid after removal, so no methods may be called.
@@ -1635,7 +1635,7 @@ def remove_virtual_authenticator(self):
16351635
self._authenticator_id = None
16361636

16371637
@required_virtual_authenticator
1638-
def add_credential(self, credential: Credential):
1638+
def add_credential(self, credential: Credential) -> None:
16391639
"""
16401640
Injects a credential into the authenticator.
16411641
"""
@@ -1645,33 +1645,36 @@ def add_credential(self, credential: Credential):
16451645
)
16461646

16471647
@required_virtual_authenticator
1648-
def get_credentials(self):
1648+
def get_credentials(self) -> List[Credential]:
16491649
"""
16501650
Returns the list of credentials owned by the authenticator.
16511651
"""
16521652
credential_data = self.execute(Command.GET_CREDENTIALS, {'authenticatorId': self._authenticator_id})
1653-
print("Get_Credential from authenticator", credential_data)
1654-
return credential_data['value']
1653+
return [Credential.from_dict(credential) for credential in credential_data['value']]
16551654

16561655
@required_virtual_authenticator
1657-
def remove_credential(self, credential_id: str):
1656+
def remove_credential(self, credential_id: Union[str, bytearray]) -> None:
16581657
"""
16591658
Removes a credential from the authenticator.
16601659
"""
1660+
# Check if the credential is bytearray converted to b64 string
1661+
if type(credential_id) is bytearray:
1662+
credential_id = urlsafe_b64encode(credential_id).decode()
1663+
16611664
self.execute(
16621665
Command.REMOVE_CREDENTIAL,
16631666
{'credentialId': credential_id, 'authenticatorId': self._authenticator_id}
16641667
)
16651668

16661669
@required_virtual_authenticator
1667-
def remove_all_credentials(self):
1670+
def remove_all_credentials(self) -> None:
16681671
"""
16691672
Removes all credentials from the authenticator.
16701673
"""
16711674
self.execute(Command.REMOVE_ALL_CREDENTIALS, {'authenticatorId': self._authenticator_id})
16721675

16731676
@required_virtual_authenticator
1674-
def set_user_verified(self, verified: bool):
1677+
def set_user_verified(self, verified: bool) -> None:
16751678
"""
16761679
Sets whether the authenticator will simulate success or fail on user verification.
16771680
verified: True if the authenticator will pass user verification, False otherwise.

0 commit comments

Comments
 (0)