Digital Credentials Module
The Digital Credentials module allows you to simulate a virtual digital wallet during automated testing, enabling end-to-end verification of credential presentation flows without requiring a real wallet application.
Overview
The Digital Credentials module allows you to:
- Simulate a wallet that presents a predefined credential response
- Simulate a wallet that declines or cancels a credential request
- Leave credential requests in a pending state to test timeouts
- Scope wallet behavior to a specific browsing context
- Clear any active simulated wallet behavior
Accessing the Module
DigitalCredentialsModule digitalCredentials = driver.DigitalCredentials;
Timeout and Cancellation
All commands in this module accept optional timeoutOverride and CancellationToken parameters. Use timeoutOverride to set a per-command timeout (defaults to BiDiDriver.DefaultCommandTimeout when omitted). Use CancellationToken for cooperative cancellation. See the API Design Guide for details and examples.
Setting the Virtual Wallet Behavior
The module exposes a single command, SetVirtualWalletBehaviorAsync, which configures how the browser's virtual wallet responds to a navigator.credentials.get() or navigator.credentials.create() call that uses the Digital Credentials API.
Declining a Credential Request
Simulate a user who cancels or rejects the wallet prompt:
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Decline);
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
Console.WriteLine("Virtual wallet will decline credential requests");
Responding with a Credential
Simulate a successful presentation by returning a predefined response object:
Dictionary<string, object?> credentialResponse = new Dictionary<string, object?>
{
["token"] = "eyJhbGciOiJFUzI1NiJ9...",
["format"] = "jwt_vc"
};
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Respond)
{
Protocol = "openid4vp-v1-unsigned",
Response = credentialResponse
};
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
Console.WriteLine("Virtual wallet will return the predefined credential response");
Protocol and Response are a required pair for VirtualWalletAction.Respond: a conforming remote end
answers with invalid argument if either is missing. Every other action requires both to be absent, so
Decline, Wait and Clear are sent with neither.
The Response property accepts any Dictionary<string, object?> whose shape matches the credential
response your application expects for the protocol you name.
Choosing the Credential Protocol
Protocol is not a filter. It names the protocol the simulated credential is presented under, and its
value is written into the credential the page receives as DigitalCredential.protocol:
Dictionary<string, object?> credentialResponse = new Dictionary<string, object?>
{
["documents"] = new List<object?>
{
new Dictionary<string, object?>
{
["docType"] = "org.iso.18013.5.1.mDL"
}
}
};
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Respond)
{
Protocol = "org-iso-mdoc",
Response = credentialResponse
};
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
Console.WriteLine("Virtual wallet will present the credential as an org-iso-mdoc response");
The value must be one of the identifiers enumerated by DigitalCredentialProtocol in the
Digital Credentials API; anything else is rejected with
invalid argument. At the time of writing those are:
| Identifier | Kind |
|---|---|
openid4vp-v1-unsigned |
Presentation |
openid4vp-v1-signed |
Presentation |
openid4vp-v1-multisigned |
Presentation |
org-iso-mdoc |
Presentation |
openid4vci-v1 |
Issuance |
Identifiers are added to that enumeration as user agents adopt new protocols, so check the specification rather than treating this list as closed.
Leaving the Request Pending
Simulate an active, unresolved wallet prompt to test timeout handling or concurrent request behavior:
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Wait);
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
Console.WriteLine("Virtual wallet will leave the credential request pending");
Clearing the Active Behavior
Remove any previously configured virtual wallet behavior, returning to the browser's default handling:
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Clear);
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
Console.WriteLine("Virtual wallet behavior cleared");
Scoping Behavior
The browsing context is the only axis the command scopes by. Apply the wallet behavior to a specific tab
or frame by setting the BrowsingContextId property; omit it and the behavior becomes the session
default:
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Decline)
{
BrowsingContextId = contextId
};
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
Console.WriteLine($"Virtual wallet will decline requests in context {contextId}");
VirtualWalletAction Values
| Value | Description | Protocol and Response |
|---|---|---|
VirtualWalletAction.Decline |
Simulates a user cancellation; the credential request is aborted | Both must be omitted |
VirtualWalletAction.Respond |
Returns the object supplied in Response as the credential data |
Both are required |
VirtualWalletAction.Wait |
Leaves the active promise unsettled; useful for timeout or concurrency tests | Both must be omitted |
VirtualWalletAction.Clear |
Removes any active virtual wallet behavior | Both must be omitted |
Supplying either property with an action other than Respond, or omitting either one with Respond, is
answered with invalid argument.
Common Patterns
Testing a Declined Credential Request
// Configure wallet to decline
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Decline);
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
// Navigate to a page that requests digital credentials
await driver.BrowsingContext.NavigateAsync(
new NavigateCommandParameters(contextId, "https://example.com/verify-id")
{ Wait = ReadinessState.Complete });
Console.WriteLine("Page loaded; wallet will reject any credential request");
Testing a Successful Credential Flow
// Build a minimal mdoc response
Dictionary<string, object?> mdocResponse = new Dictionary<string, object?>
{
["version"] = "1.0",
["documents"] = new List<object?>
{
new Dictionary<string, object?>
{
["docType"] = "org.iso.18013.5.1.mDL",
["issuerSigned"] = "..."
}
}
};
// Configure wallet to respond with the prepared credential
SetVirtualWalletBehaviorCommandParameters @params = new SetVirtualWalletBehaviorCommandParameters(
VirtualWalletAction.Respond)
{
Protocol = "org-iso-mdoc",
BrowsingContextId = contextId,
Response = mdocResponse
};
await driver.DigitalCredentials.SetVirtualWalletBehaviorAsync(@params);
// Navigate and trigger the credential request
await driver.BrowsingContext.NavigateAsync(
new NavigateCommandParameters(contextId, "https://example.com/verify-id")
{ Wait = ReadinessState.Complete });
Console.WriteLine("Wallet is ready to present the mDL credential");
Browser Support
| Browser | Support Level |
|---|---|
| Chrome/Edge | ⚠️ Experimental |
| Firefox | ❌ Not supported |
| Safari | ❌ Not supported |
Note: The Digital Credentials API and its WebDriver BiDi test automation support are experimental. Check your browser's release notes for availability.
Best Practices
- Set behavior before navigation: Configure the virtual wallet before navigating to the page that triggers a credential request.
- Clear behavior between tests: Call
SetVirtualWalletBehaviorAsyncwithVirtualWalletAction.Clearafter each test to avoid state leaking between test cases. - Use context scoping for isolation: When running multiple contexts in parallel, scope the wallet behavior to a specific context to prevent interference.
- Match the response shape to your protocol:
RespondrequiresProtocolas well asResponse, and theResponsedictionary must conform to the structure expected by the protocol you name. - Test all action paths: Verify your application handles
Decline,Respond, andWait(timeout) outcomes.
Common Issues
Credential Request Not Intercepted
Problem: The page's credential request is not intercepted by the virtual wallet.
Solution:
- Ensure the browser version supports the Digital Credentials API.
- Set the wallet behavior before the page issues the credential request.
- Confirm the browser was launched with any required experimental feature flags.
Response Shape Rejected by the Page
Problem: The page throws an error when processing the credential response.
Solution:
- Verify the
Responsedictionary matches the schema your application expects for the protocol named inProtocol. - Confirm
Protocolnames the protocol the page actually requested; its value reaches the page asDigitalCredential.protocol. - Check browser console errors for schema validation messages.
Behavior Persists After Test
Problem: Wallet behavior configured in one test affects subsequent tests.
Solution:
- Call
SetVirtualWalletBehaviorAsyncwithVirtualWalletAction.Clearin your test teardown. - Use an isolated browsing context for each test; the command scopes only by browsing context, via the
BrowsingContextIdproperty.
Next Steps
- Permissions Module: Browser permission management
- Emulation Module: Device and environment emulation
- Browser Module: User context management
- API Reference: Complete API documentation