Virtual Authenticator
Web applications can enable a public key-based authentication mechanism known as Web Authentication to authenticate users in a passwordless manner. Web Authentication defines APIs that allows a user to create a public-key credential and register it with an authenticator. An authenticator can be a hardware device or a software entity that stores user’s public-key credentials and retrieves them on request.
As the name suggests, Virtual Authenticator emulates such authenticators for testing.
Virtual Authenticator Options
A Virtual Authenticatior has a set of properties. These properties are mapped as VirtualAuthenticatorOptions in the Selenium bindings.
public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
// Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
options.setHasUserVerification(true); options.setIsUserConsenting(true); options.setTransport(Transport['USB']); options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); assert(Object.keys(options).length === 6);
examples/javascript/test/virtual_authenticator/virtualAuthenticatorOptions.spec.js
const {VirtualAuthenticatorOptions, Transport, Protocol} = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') describe('Virtual authenticator options', function () { let options; it('Virtual options', async function () { options = new VirtualAuthenticatorOptions(); options.setIsUserVerified(true); options.setHasUserVerification(true); options.setIsUserConsenting(true); options.setTransport(Transport['USB']); options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); assert(Object.keys(options).length === 6); }); it('User verified', async function () { options.setIsUserVerified(true); assert(options.toDict()['isUserVerified']); }); });
Add Virtual Authenticator
It creates a new virtual authenticator with the provided properties.
public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator =
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
// Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials();
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options)
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options);
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Remove Virtual Authenticator
Removes the previously added virtual authenticator.
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator()
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator();
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Create Resident Credential
Creates a resident (stateful) credential with the given required credential parameters.
byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential(
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
# parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count)
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential);
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Create Non-Resident Credential
Creates a resident (stateless) credential with the given required credential parameters.
VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4};
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
# parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count)
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0);
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Add Credential
Registers the credential with the authenticator.
@Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential(
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
driver.add_credential(credential)
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential);
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Get Credential
Returns the list of credentials owned by the authenticator.
@Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential);
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials();
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
credential_list = driver.get_credentials()
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials();
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Remove Credential
Removes a credential from the authenticator based on the passed credential id.
@Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential);
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
driver.remove_credential(credential.id)
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
Remove All Credentials
Removes all the credentials from the authenticator.
@Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential);
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials();
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
driver.remove_all_credentials()
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials();
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });
Set User Verified
Sets whether the authenticator will simulate success or fail on user verification.
@Test public void testSetUserVerified() {
examples/java/src/test/java/dev/selenium/interactions/VirtualAuthenticatorTest.java
package dev.selenium.interactions; import dev.selenium.BaseChromeTest; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.InvalidArgumentException; import org.openqa.selenium.virtualauthenticator.Credential; import org.openqa.selenium.virtualauthenticator.HasVirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticator; import org.openqa.selenium.virtualauthenticator.VirtualAuthenticatorOptions; public class VirtualAuthenticatorTest extends BaseChromeTest { /** * A pkcs#8 encoded encrypted RSA private key as a base64url string. */ private final static String base64EncodedRsaPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private final static PKCS8EncodedKeySpec rsaPrivateKey = new PKCS8EncodedKeySpec(Base64.getMimeDecoder().decode(base64EncodedRsaPK)); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. String base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; PKCS8EncodedKeySpec ec256PrivateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); @Test public void testVirtualOptions() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true) .setHasUserVerification(true) .setIsUserConsenting(true) .setTransport(VirtualAuthenticatorOptions.Transport.USB) .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); Assertions.assertEquals(6, options.toMap().size()); } @Test public void testCreateAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(0, credentialList.size()); } @Test public void testRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions(); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator); Assertions.assertThrows(InvalidArgumentException.class, authenticator::getCredentials); } @Test public void testCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testAddResidentCredentialNotSupportedWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); PKCS8EncodedKeySpec privateKey = new PKCS8EncodedKeySpec(Base64.getUrlDecoder().decode(base64EncodedEC256PK)); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential credential = Credential.createResidentCredential( credentialId, "localhost", privateKey, userHandle, /*signCount=*/0); Assertions.assertThrows(InvalidArgumentException.class, () -> authenticator.addCredential(credential)); } @Test @Disabled("A fix was implemented and will be available in Selenium 4.34.") public void testCreateAndAddNonResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .setHasResidentKey(false); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; Credential nonResidentCredential = Credential.createNonResidentCredential( credentialId, "localhost", ec256PrivateKey, /*signCount=*/0); authenticator.addCredential(nonResidentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); } @Test public void testGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setProtocol(VirtualAuthenticatorOptions.Protocol.CTAP2) .setHasResidentKey(true) .setHasUserVerification(true) .setIsUserVerified(true); VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options); byte[] credentialId = {1, 2, 3, 4}; byte[] userHandle = {1}; Credential residentCredential = Credential.createResidentCredential( credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0); authenticator.addCredential(residentCredential); List<Credential> credentialList = authenticator.getCredentials(); Assertions.assertEquals(1, credentialList.size()); Credential credential = credentialList.get(0); Assertions.assertArrayEquals(credentialId, credential.getId()); Assertions.assertArrayEquals(rsaPrivateKey.getEncoded(), credential.getPrivateKey().getEncoded()); } @Test public void testRemoveCredential() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential credential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, 0); authenticator.addCredential(credential); authenticator.removeCredential(credentialId); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testRemoveAllCredentials() { VirtualAuthenticator authenticator = ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = {1, 2, 3, 4}; Credential residentCredential = Credential.createNonResidentCredential( credentialId, "localhost", rsaPrivateKey, /*signCount=*/0); authenticator.addCredential(residentCredential); authenticator.removeAllCredentials(); Assertions.assertEquals(0, authenticator.getCredentials().size()); } @Test public void testSetUserVerified() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .setIsUserVerified(true); Assertions.assertTrue((boolean) options.toMap().get("isUserVerified")); } }
VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true);
examples/dotnet/SeleniumDocs/Interactions/VirtualAuthenticatorTest.cs
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.IdentityModel.Tokens; using OpenQA.Selenium; using OpenQA.Selenium.VirtualAuth; using static OpenQA.Selenium.VirtualAuth.VirtualAuthenticatorOptions; using System.Collections.Generic; using System; namespace SeleniumDocs.VirtualAuthentication { [TestClass] public class VirtualAuthenticatorTest : BaseChromeTest { //A pkcs#8 encoded encrypted RSA private key as a base64 string. private static string base64EncodedRSAPK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuB" + "GVoPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi" + "9AyQFR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1P" + "vSqXlqGjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsui" + "zAgyPuQ0+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/" + "XYY22ecYxM8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtib" + "RXz5FcNld9MgD/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swyko" + "QKBgQD8hCsp6FIQ5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMC" + "S6S64/qzZEqijLCqepwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnK" + "ws1t5GapfE1rmC/h4olL2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63" + "ojKjegxHIyYDKRZNVUR/dxAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM /r8PSflNHQKBgDnWgBh6OQncChPUl" + "OLv9FMZPR1ZOfqLCYrjYEqiuzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8V" + "ASOmqM1ml667axeZDIR867ZG8K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6B" + "hZC7z8mx+pnJODU3cYukxv3WTctlUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJw" + "WkBwYADmkfTRmHDvqzQSSvoC2S7aa9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KI" + "NpLwcR8fqaYOdAHWWz636osVEqosRrHzJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fB" + "nzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4HBYGpI8g=="; private static byte[] bytes = System.Convert.FromBase64String(base64EncodedRSAPK); private string base64EncodedPK = Base64UrlEncoder.Encode(bytes); // A pkcs#8 encoded unencrypted EC256 private key as a base64url string. private string base64EncodedEC256PK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; [TestMethod] public void VirtualOptionsShouldAllowSettingOptions() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true) .SetHasUserVerification(true) .SetIsUserConsenting(true) .SetTransport(VirtualAuthenticatorOptions.Transport.USB) .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); Assert.AreEqual(6, options.ToDictionary().Count); } [TestMethod] public void ShouldBeAbleToCreateAuthenticator() { // Create virtual authenticator options VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); // Register a virtual authenticator ((WebDriver)driver).AddVirtualAuthenticator(options); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(0, credentialList.Count); } [TestMethod] public void ShouldBeAbleToRemoveAuthenticator() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); String virtualAuthenticatorId = ((WebDriver)driver).AddVirtualAuthenticator(options); ((WebDriver)driver).RemoveVirtualAuthenticator(virtualAuthenticatorId); // Since the authenticator was removed, any operation using it will throw an error Assert.ThrowsException<InvalidOperationException>(() => ((WebDriver)driver).GetCredentials()); } [TestMethod] public void ShouldBeAbleToCreateAndAddResidentialKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, credential.Id); } [TestMethod] public void ShouldNotAddResidentCredentialWhenAuthenticatorUsesU2FProtocol() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential credential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedEC256PK, userHandle, 0); Assert.ThrowsException<WebDriverArgumentException>(() => ((WebDriver)driver).AddCredential(credential)); } [TestMethod] public void ShouldBeAbleToCreateAndAddNonResidentKey() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(VirtualAuthenticatorOptions.Protocol.U2F) .SetHasResidentKey(false); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, nonResidentCredential.Id); } [TestMethod] public void ShouldBeAbleToGetCredential() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetProtocol(Protocol.CTAP2) .SetHasResidentKey(true) .SetHasUserVerification(true) .SetIsUserVerified(true); ((WebDriver)driver).AddVirtualAuthenticator(options); byte[] credentialId = { 1, 2, 3, 4 }; byte[] userHandle = { 1 }; Credential residentCredential = Credential.CreateResidentCredential( credentialId, "localhost", base64EncodedPK, userHandle, 0); ((WebDriver)driver).AddCredential(residentCredential); List<Credential> credentialList = ((WebDriver)driver).GetCredentials(); Assert.AreEqual(1, credentialList.Count); Credential credential = credentialList[0]; CollectionAssert.AreEqual(credentialId, residentCredential.Id); Assert.AreEqual(base64EncodedPK, credential.PrivateKey); } [TestMethod] public void ShouldBeAbleToRemoveCredential() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveCredential(credentialId); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeAbleToRemoveAllCredentias() { ((WebDriver)driver).AddVirtualAuthenticator(new VirtualAuthenticatorOptions()); byte[] credentialId = { 1, 2, 3, 4 }; Credential nonResidentCredential = Credential.CreateNonResidentCredential( credentialId, "localhost", base64EncodedEC256PK, 0); ((WebDriver)driver).AddCredential(nonResidentCredential); ((WebDriver)driver).RemoveAllCredentials(); Assert.AreEqual(0, ((WebDriver)driver).GetCredentials().Count); } [TestMethod] public void ShouldBeSetVerifiedOption() { VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions() .SetIsUserVerified(true); Assert.IsTrue((bool)options.ToDictionary()["isUserVerified"]); } } }
# Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True
examples/python/tests/interactions/test_virtual_authenticator.py
import pytest from base64 import urlsafe_b64decode, urlsafe_b64encode from selenium.common.exceptions import InvalidArgumentException from selenium.webdriver.chrome.webdriver import WebDriver from selenium.webdriver.common.virtual_authenticator import ( Credential, VirtualAuthenticatorOptions, ) BASE64__ENCODED_PK = ''' MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0 +j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM 8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD /Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ 5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8 K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa 9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H BYGpI8g== ''' @pytest.fixture(scope="module", autouse=True) def driver(): yield WebDriver() def test_virtual_authenticator_options(): options = VirtualAuthenticatorOptions() options.is_user_verified = True options.has_user_verification = True options.is_user_consenting = True options.transport = VirtualAuthenticatorOptions.Transport.USB options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False assert len(options.to_dict()) == 6 def test_add_authenticator(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # Get list of credentials credential_list = driver.get_credentials() assert len(credential_list) == 0 def test_remove_authenticator(driver): # Create default virtual authenticator option options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # Remove virtual authenticator driver.remove_virtual_authenticator() assert driver.virtual_authenticator_id is None def test_create_and_add_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verification = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_add_resident_credential_not_supported_when_authenticator_uses_u2f_protocol(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # Expect InvalidArgumentException with pytest.raises(InvalidArgumentException): driver.add_credential(credential) def test_create_and_add_non_resident_key(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.U2F options.has_resident_key = False # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 def test_get_credential(driver): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.protocol = VirtualAuthenticatorOptions.Protocol.CTAP2 options.has_resident_key = True options.has_user_verfied = True options.is_user_verified = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # get list of all the registered credentials credential_list = driver.get_credentials() assert len(credential_list) == 1 assert credential_list[0].id == urlsafe_b64encode(credential_id).decode() def test_remove_credential(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Non Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a non resident credential using above parameters credential = Credential.create_non_resident_credential(credential_id, rp_id, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(credential) # remove the credential created from virtual authenticator driver.remove_credential(credential.id) # credential can also be removed using Byte Array # driver.remove_credential(credential_id) assert len(driver.get_credentials()) == 0 def test_remove_all_credentials(driver): # Create default virtual authenticator options options = VirtualAuthenticatorOptions() options.has_resident_key = True # Register a virtual authenticator driver.add_virtual_authenticator(options) # parameters for Resident Credential credential_id = bytearray({1, 2, 3, 4}) rp_id = "localhost" user_handle = bytearray({1}) privatekey = urlsafe_b64decode(BASE64__ENCODED_PK) sign_count = 0 # create a resident credential using above parameters resident_credential = Credential.create_resident_credential(credential_id, rp_id, user_handle, privatekey, sign_count) # add the credential created to virtual authenticator driver.add_credential(resident_credential) # remove all credentials in virtual authenticator driver.remove_all_credentials() assert len(driver.get_credentials()) == 0 def test_set_user_verified(): # Create virtual authenticator options options = VirtualAuthenticatorOptions() options.is_user_verified = True assert options.to_dict().get("isUserVerified") is True
options.setIsUserVerified(true);
examples/javascript/test/virtual_authenticator/virtualAuthenticator.spec.js
const { Builder} = require("selenium-webdriver"); const { Credential, VirtualAuthenticatorOptions, Transport, Protocol } = require("selenium-webdriver/lib/virtual_authenticator"); const assert = require('assert') const { InvalidArgumentError } = require("selenium-webdriver/lib/error"); describe('Virtual authenticator', function() { const BASE64_ENCODED_PK = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbBOu5Lhs4vpowbCnmCyLUpIE7JM9sm9QXzye2G+jr+Kr" + "MsinWohEce47BFPJlTaDzHSvOW2eeunBO89ZcvvVc8RLz4qyQ8rO98xS1jtgqi1NcBPETDrtzthODu/gd0sjB2Tk3TLuBGV" + "oPXt54a+Oo4JbBJ6h3s0+5eAfGplCbSNq6hN3Jh9YOTw5ZA6GCEy5l8zBaOgjXytd2v2OdSVoEDNiNQRkjJd2rmS2oi9AyQ" + "FR3B7BrPSiDlCcITZFOWgLF5C31Wp/PSHwQhlnh7/6YhnE2y9tzsUvzx0wJXrBADW13+oMxrneDK3WGbxTNYgIi1PvSqXlq" + "GjHtCK+R2QkXAgMBAAECggEAVc6bu7VAnP6v0gDOeX4razv4FX/adCao9ZsHZ+WPX8PQxtmWYqykH5CY4TSfsuizAgyPuQ0" + "+j4Vjssr9VODLqFoanspT6YXsvaKanncUYbasNgUJnfnLnw3an2XpU2XdmXTNYckCPRX9nsAAURWT3/n9ljc/XYY22ecYxM" + "8sDWnHu2uKZ1B7M3X60bQYL5T/lVXkKdD6xgSNLeP4AkRx0H4egaop68hoW8FIwmDPVWYVAvo8etzWCtibRXz5FcNld9MgD" + "/Ai7ycKy4Q1KhX5GBFI79MVVaHkSQfxPHpr7/XcmpQOEAr+BMPon4s4vnKqAGdGB3j/E3d/+4F2swykoQKBgQD8hCsp6FIQ" + "5umJlk9/j/nGsMl85LgLaNVYpWlPRKPc54YNumtvj5vx1BG+zMbT7qIE3nmUPTCHP7qb5ERZG4CdMCS6S64/qzZEqijLCqe" + "pwj6j4fV5SyPWEcpxf6ehNdmcfgzVB3Wolfwh1ydhx/96L1jHJcTKchdJJzlfTvq8wwKBgQDeCnKws1t5GapfE1rmC/h4ol" + "L2qZTth9oQmbrXYohVnoqNFslDa43ePZwL9Jmd9kYb0axOTNMmyrP0NTj41uCfgDS0cJnNTc63ojKjegxHIyYDKRZNVUR/d" + "xAYB/vPfBYZUS7M89pO6LLsHhzS3qpu3/hppo/Uc/AM/r8PSflNHQKBgDnWgBh6OQncChPUlOLv9FMZPR1ZOfqLCYrjYEqi" + "uzGm6iKM13zXFO4AGAxu1P/IAd5BovFcTpg79Z8tWqZaUUwvscnl+cRlj+mMXAmdqCeO8VASOmqM1ml667axeZDIR867ZG8" + "K5V029Wg+4qtX5uFypNAAi6GfHkxIKrD04yOHAoGACdh4wXESi0oiDdkz3KOHPwIjn6BhZC7z8mx+pnJODU3cYukxv3WTct" + "lUhAsyjJiQ/0bK1yX87ulqFVgO0Knmh+wNajrb9wiONAJTMICG7tiWJOm7fW5cfTJwWkBwYADmkfTRmHDvqzQSSvoC2S7aa" + "9QulbC3C/qgGFNrcWgcT9kCgYAZTa1P9bFCDU7hJc2mHwJwAW7/FQKEJg8SL33KINpLwcR8fqaYOdAHWWz636osVEqosRrH" + "zJOGpf9x2RSWzQJ+dq8+6fACgfFZOVpN644+sAHfNPAI/gnNKU5OfUv+eav8fBnzlf1A3y3GIkyMyzFN3DE7e0n/lyqxE4H" + "BYGpI8g=="; const base64EncodedPK = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8_zMDQDYAxlU-Q" + "hk1Dwkf0v18GZca1DMF3SaJ9HPdmShRANCAASNYX5lyVCOZLzFZzrIKmeZ2jwU" + "RmgsJYxGP__fWN_S-j5sN4tT15XEpN_7QZnt14YvI6uvAgO0uJEboFaZlOEB"; let options; let driver; before(async function() { options = new VirtualAuthenticatorOptions(); driver = await new Builder().forBrowser('chrome').build(); }); after(async() => await driver.quit()); function arraysEqual(array1, array2) { return (array1.length === array2.length && array1.every((item) => array2.includes(item)) && array2.every((item) => array1.includes(item))); } it('Register a virtual authenticator', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); // Register a virtual authenticator await driver.addVirtualAuthenticator(options); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Remove authenticator', async function() { await driver.addVirtualAuthenticator(options); await driver.removeVirtualAuthenticator(); // Since the authenticator was removed, any operation using it will throw an error try { await driver.getCredentials() } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Createa and add residential key', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Add resident credential not supported when authenticator uses U2F protocol', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(true); await driver.addVirtualAuthenticator(options); let credential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); try { await driver.addCredential(credential) } catch (e) { if (e instanceof InvalidArgumentError) { assert(true) } else { assert(false) } } }); it('Create and add non residential key', async function() { options.setProtocol(Protocol['U2F']); options.setHasResidentKey(false); await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(base64EncodedPK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); }); it('Get credential', async function() { options.setProtocol(Protocol['CTAP2']); options.setHasResidentKey(true); options.setHasUserVerification(true); options.setIsUserVerified(true); await driver.addVirtualAuthenticator(options); let residentCredential = new Credential().createResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', new Uint8Array([1]), Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(residentCredential); let credentialList = await driver.getCredentials(); assert.equal(1, credentialList.length); let credential_id = credentialList[0].id(); let test_id = new Uint8Array([1, 2, 3, 4]); assert(arraysEqual(credential_id, test_id)); assert.equal(BASE64_ENCODED_PK, Buffer.from(credentialList[0].privateKey(), 'binary').toString('base64')); }); it('Remove all credentials', async function() { await driver.addVirtualAuthenticator(options); let nonResidentCredential = new Credential().createNonResidentCredential( new Uint8Array([1, 2, 3, 4]), 'localhost', Buffer.from(BASE64_ENCODED_PK, 'base64').toString('binary'), 0); await driver.addCredential(nonResidentCredential); await driver.removeAllCredentials(); let credentialList = await driver.getCredentials(); assert.equal(0, credentialList.length); }); it('Set is user verified', async function() { options.setIsUserVerified(true); assert.equal(options.getIsUserVerified(), true); }); });