Virtual Authenticator

A representation of the Web Authenticator model.

Page being translated from English to Japanese. Do you speak Japanese? Help us to translate it by sending us pull requests!

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.

    VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
      .setIsUserVerified(true)
      .setHasUserVerification(true)
      .setIsUserConsenting(true)
      .setTransport(VirtualAuthenticatorOptions.Transport.USB)
      .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
      .setHasResidentKey(false);
Show full example
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.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
  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);
Show full example
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
Show full example
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);
Show full example
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.

    VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
      .setProtocol(VirtualAuthenticatorOptions.Protocol.U2F)
      .setHasResidentKey(false);

    VirtualAuthenticator authenticator =
      ((HasVirtualAuthenticator) driver).addVirtualAuthenticator(options);
Show full example
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.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
  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();
Show full example
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)
Show full example
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);
Show full example

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.

    ((HasVirtualAuthenticator) driver).removeVirtualAuthenticator(authenticator);
Show full example
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.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
  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);
Show full example
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()
Show full example
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();
Show full example

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(
      credentialId, "localhost", rsaPrivateKey, userHandle, /*signCount=*/0);
Show full example
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.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
  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);
Show full example
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)
Show full example
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);
Show full example

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.

    byte[] credentialId = {1, 2, 3, 4};
    Credential nonResidentCredential = Credential.createNonResidentCredential(
      credentialId, "localhost", ec256PrivateKey, /*signCount=*/0);
Show full example
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.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
  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);
Show full example
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)
Show full example
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);
Show full example

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.

    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);
Show full example
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.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
  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);
Show full example
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)
Show full example
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);
Show full example

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.

    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();
Show full example
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.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
  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();
Show full example
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()
Show full example
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();
Show full example

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.

            ((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);
Show full example
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"]);
        }
    }
}
    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);
Show full example
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.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
  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"));
  }
}
    driver.remove_credential(credential.id)
Show full example
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.

    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();
Show full example
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.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
  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();
Show full example
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()
Show full example
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();
Show full example

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.

    VirtualAuthenticatorOptions options = new VirtualAuthenticatorOptions()
      .setIsUserVerified(true);
Show full example
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.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
  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);
Show full example
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
Show full example
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);
Show full example

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);
  });
});