This post is joint work with Sukhi Chuhan and Pema Selden.
This post is an interim report on version v5 of a live demonstration of a multi-purpose driver's license credential. The demonstration is live and a step-by-step description of how to can be run as described below. The code of the seven Node.js servers used in the demonstration can be found in seven GitHub repositories referenced below.
As in version v4, which we presented at IIW last year, the credential comprises a JSON public key certificate in full disclosure and selective disclosure formats. It can be issued by showing a QR code that the driver scans after passing the driver's exam, and it can be presented at a traffic stop by scanning a QR code shown by the officer.
Version v5 demonstrates two new features:
Issuance by email, and
On-demand cross-device replication.
These features provide new capabilities, which are demonstrated below by new use cases following a discussion of the cryptographic and technological foundations of the demonstration.
The post concludes by showing how a traffic stop use case would allow the officer to display together, on the MDC of the patrol car, the licenses of two drivers that are speeding together; and how it would make it legal to drive while carrying neither a physical nor a digital license.
Cryptograhic Foundations
The demonstration is based on the following cryptographic concepts.
Public key certificates
Public key certificates are a basic concept of cryptography, which goes back at least to Kohnfelder's 1978 bachelor's thesis. A public key certificate is a data structure signed by a credential issuer that binds metadata and information about a subject to the public key component of a key pair generated by the subject. A public key certificate together with the associated private key comprises a third-party cryptographic credential that can be used to authenticate the subject to a relying party without prior registration.
Public key certificates are traditionally encoded in ASN.1 notation as specified in the X.509 standard and profiled for the internet in RFC 5280.
The information about the subject found in a public key certificate is usually said to be the subject's identity. However, besides identifying information carried in the Subject field, an X.509 v3 certificate can include any kind of attributes in the Subject Alternative Name extension or in custom extensions. Attributes can also be included in companion data structures such as Attribute Certificates or ancillary certificates included in a PIV card.
JSON certificates
We use the term JSON certificate to refer to a public certificate that is encoded in JSON rather than X.509 and may comprise any information about the subject including attributes and/or identifiers.
Selective disclosure JSON certificates
We use the term selective disclosure JSON certificate to refer to a JSON certificate where information about the user can be omitted without invalidating the signature, by contrast with a full disclosure JSON certificate where this is not possible. In this demo each credential is issued in both full disclosure and selective disclosure formats. The full disclosure format is functionally redundant, but more convenient for users and relying parties in use cases that require presentation of all the attributes.
We implement full and selective disclosure as follows.
In a full disclosure certificate, the attributes are properties of an object, the name and value of each attribute being the name and value of a property.
In a selective disclosure certificate, the attributes are instead items of an array. Each attribute is encoded as an object, with two properties called "saltedAttribute" and "digest_hex", where the value of the "digest_hex" property is a hex-encoded digest of the value of the "saltedAttribute" property. The value of the "saltedAttribute" property is itself an object with three properties, called "name", "value" and "salt_hex", where the value of the "name" property is the name of the attribute, the value of "value" property is the value of the attribute, and the value of the "salt_hex" property is a hex-encoded random salt. An attribute is omitted from a presentation by removing the "saltedAttribute" property. The signature on the certificate is computed and verified after removing all "saltedAttribute" properties, and a disclosed attribute is verified by comparing the digest of its "saltedAttribute" property to the value of its "digest_hex" property.
Technological foundations
Using a browser as a wallet with presentation-request interception by a service worker
We use a browser as a credential wallet, as described in Section 12.4 of Chapter 12 of the book-in-progress on Foundations of Cryptographic Authentication. When a relying party receives a request that requires authentication, it sends a credential presentation request on the browser from which it has received the request. The presentation request targets the credential issuer but is intercepted by a service worker, which finds the credential in the browser and presents it after asking the user for consent. Service workers were meant to enable offline use of progressive web apps, but we are repurposing them here for credential presentation as explained in Section 12.4.1 of the chapter.
In this version of the demo, credentials are stored in the localStorage facility provided by the Web Storage API, with security provided by the same-origin policy of the web enforced by the browser. In a future version we plan to provide the option of storing a high-security credential in Windows Hello or the Secure Enclave, using a non-discoverable passkey as the private key and the Large Blob extension of WebAuthn as certificate storage. The user will then be prompted for the platform unlocking PIN or biometric before using the credential.
Credential replication and passkey syncing
We use the term credential replica to refer to a data structure derived from an original credential that is certified by the same issuer and comprises the same attributes, possibly formated or encoded differently, but binds the attributes to a different proof-of-possession secret. An example of credential replication without modification of the attributes is key rotation. An example of replication with modification is server retrieval of the mDL as specified in the ISO/IEC 18013-5 standard, which encodes attributes in JSON whereas they are encoded in CBOR for device retrieval.
Passkeys are two-party credentials used for returning user authentication. While passkeys are credentials, passkey syncing differs from credential replication in that synced passkeys have the same private key. But while passkeys are not replicated, we use them to implement replication of third-party credentials, as follows.
When a credential is issued to a browser, the issuer creates a passkey in that browser using at the user.id parameter in the call to navigator.credentials.get() a retrieval token that references a driver record containing the attributes included in the credential. When a relying party asks for presentation of the credential on an instance of the same browser in a different device, where there is no credential and no service worker, the request reaches the issuer, which call navigator.credentials.get(). The value of the userHandle property or the response to the get() is the value if user.id parameter in the create() call, i.e. the retrival token. The issuer uses the token to retrieve the driver record, and replicates the credential using the attributes in the record.
A passkey syncing caveat
While implementing this, there was no problem replicating a credential from a laptop to a phone, but it seemed impossible to sync a passkey, and hence to replicate a credential, from an Android phone to a Windows laptop. After spending many hours over the course of two days working with a Google AI bot, the bot was finally able to figure out what the problem was.
Here is the end of a 700-line transcript of the interaction between the bot and myself:
MYSELF:
Success! The Resident Key fix worked. Thank you very much 🙂
THE BOT:
That is fantastic news! It’s always a relief when the "ghost in the machine" turns out to be a specific piece of logic in the code.
To wrap this up for your technical notes, here is why that worked:
The Android Logic: Unlike Windows, which is happy to store almost any credential in the cloud, Android’s Credential Manager treats "non-resident" keys as disposable session tokens. By explicitly setting residentKey: "required", you signaled to the Android OS: "This is a permanent identity that needs to live in the user's account."
The "Save" Prompt: Once Android sees that residentKey requirement, it finally triggers the "Save to Google Password Manager" flow because it now knows the credential is meant to be "discoverable" and synced across devices.
I'm glad we could get that sorted for your test site. Happy coding and enjoy your newly functional passkey flow!
Servers used in the demo
The demonstration has a Bhutan NDI theme and some of the servers play roles suggested by the Bhutan NDI case study.
As in slide 7 of last year's presentation there are two servers, now called v5-ci and v5-ci-admin, playing the roles of edge server and internal server of the data center of the Bhutan Road Safety and Transportation Authority (RSTA). They are implemented as Node.js servers within a virtual private server (VPS) whose loopback network is used to simulate physically secure communications between servers. They are reachable from the internet, through an nginx reverse proxy, as v5-ci.pomcor.com and v5-ci-admin.pomcor.com, and in the loopback network as localhost:3050 and localhost:3051. Their code can be found on GitHub at fcorella/v5-ci and fcorella/v5-ci-admin.
As in slides 13 and 53 of last year's presentation there are also two servers used by relying parties, called v5-rp-web and v5-rp-qr, reachable from the internet as v5-rp-web.pomcor.com and v5-rp-qr.pomcor.com. They do not comnunicate with each other but are hosted for convenience on the same VPS, distinct from the VPS that hosts the RSTA servers. Their code can be found on GitHub at fcorella/v5-rp-web and fcorella/v5-rp-qr.
In this version of the demo, there are three additional servers:
- A server called v5-ci-hsm that simulates a Hardware Security Module (HSM) within the RSTA data center, hosted on the same VPS as v5-ci and v5-ci-admin, accessed by v5-ci-admin through the loopback network at localhost:3054 and not reachable from the internet. It contains the private key used to sign the JSON certificates of the driver's license credentials, and a JSON CA certificate signed by the Trust Registry that identifies the associated public key as belonging to RSTA. It's code can be found on GitHub at fcorella/v5-ci-hsm.
- A server called v5-trust-registry that simulates a server used by the Bhutan Trust Registry to sign CA certificates for government agencies. In this demo it contains the private key used to sign the RSTA CA certificate, and the self-signed root certificate that follows the RSTA CA certificate in the certificate chains that back the driver's license certificates. This server is reachable from the internet at v5-trust-registry.pomcor.com, but for convenience in this version of the demo it is hosted on the same VPS as v5-ci, v5-ci-admin and v5-ci-hsm, and is accessed by v5-ci-hsm over the loopback network at localhost:3053. It's code can be found on GitHub at fcorella/v5-trust-registry.
- A server called v5-data-registry that maps the domain names of the relying parties to user-friendly domain designations when asking for consent to present a credential to the relying party, or to create a replica before presenting it. In this version of the demo, "v5-rp-web.pomcor.com" is mapped to "Bhutan Rentals Car Agency" and "v5-rp-qr.pomcor.com" is mapped to "Example City Police Department". This server is accessed over the internet at v5-data-registry.pomcor.com. It is hosted for convenience on the same VPS as as v5-ci, v5-ci-admin, v5-ci-hsm and v5-trust-registry, but it is not accessed by those servers over the loopback network. It's code can be found on GitHub at fcorella/v5-data-registry.
Mailto protocol
In last year's version of the demo the administrator used v4-ci-admin to collect attributes from the driver while the driver was at the RSTA office to take the driver's exam. If the driver passed the exam, the administrator clicked a link to generate a QR code containing a credential issuance URL. Before going home, the driver scanned the QR code with a phone and a credential containing the attributes was issued to the default browser of the phone.
Now, in v5, a driver who has not brought a phone to the RSTA office can provide an email address to the administrator and get the credential by email after going home. Instead of clicking a link to generate a QR code, the administrator can click a link with a URL that uses the mailto protocol to send the credential issuance URL to the driver's email address. The credential issuance URL is an https URL nested within the mailto URL as the body of the email message, and must be percent-encoded as specified in RFC 6068.
Clicking the mailto link causes the email message to be displayed, ready to be sent, on the administrator's default handler of the mailto protocol, which could be a native mail app such as Outlook or a webmail app such as gmail. When the message reaches the driver, it is displayed in the driver's email client, which may again be a native mail app such as Outlook or a webmail app, independently of the kind of mailto handler that the administrator has used.
The email received by the driver contains the credential issuance URL as text, not as the value of the href attribute of a link. After receiving the message, the driver may:
- Copy the URL and paste it on the address bar of the browser where the driver wants to have the credenial.
- Control-click on the URL if the email client is Outlook. This will launch the URL and install the credential on the default browser of the driver's platform.
- Click on the URL if the email client is a webmail app. This will launch the URL and install the credential on the browser where the webmail app is running.
Caveats of query strings and route parameters
In v4 the credential issuance URL was of the form:
`https://v4-ci.pomcor.com/retrieve-record?retrievalToken=${retrievalToken}`
where the retrieval token is a reference to the driver record containing the attributes collected by the administrator for inclusion in the credential.
But, according to Google AI, some webmail apps (not including gmail) may remove the query string when the user clicks on a link or a bare URL. So in v5 we now use route parameters instead of query strings to specify the retrievalToken, as follows:
`https://v5-ci.pomcor.com/retrieve-record/${retrievalToken}`
This change, however, caused modules imported by views rendered by the route handler to not be found. It seemed that using the route parameter caused the current directory to become "/retrieve-record" rather than "/" in those views. Google AI confirmed that using a route parameter can effectively change the current directory from the browser's perspective, and suggested using absolute paths in those views, which fixed the problem.
MongoDB, JSON documents, and data expiration
The MongoDB representation of database records as JSON documents, internally stored in Binary JSON (BSON), is a perfect fit for the representation of cryptographic credentials as full disclosure and selective disclosure certificates with their associated private keys. We use MongoDB as the DBMS for the backends of v5-ci-admin, v5-ci-hsm, v5-trust-registry, v5-rp-qr and v5-rp-web. The edge server v5-ci does not have a backend, and the backend of v5-data-registry is trivially implemented in the Node.js code itself.
Furthermore, MongoDB has a versatile data expiration feature that we use for multiple purposes.
When we create a credential presentation session containing a
challenge that will be used to verify a proof-of-possession signature,
we give it a time-to-live (TTL) of five minutes. This is implemented
using an index with an option called expiresAfterSeconds
on a field of the session document specifically created for that
purpose, conventionally called createdAt. We use the same method to
set a five minute TTL on a session that the issuer uses to verify the
replication passkey, and in the rental-car use case to set a 15-minute
TTL on login sessions.
When a user registers a username in the car rentals use case we create right away a user record with the username, but we may have to garbage-collect it if presentation of the driver's license credential fails. We automate this by combining the expiration feature with another innovative feature of MongoDB, the partial index feature, as follows.
We create again an index on a "createdAt" field, and set a TTL with
an expiresAfterSeconds option of 10 minutes. But we also add a
"status" field with a value of "inactive" and an option
partialFilterExpression: { status: "inactive"
} to the same index. This causes the user record
to be deleted only if it is still inactive after 10 minutes, and we
remove the inactive status when the driver's license credential is
successfully presented.
In production, a TTL would not be set for the documents containing the driver records created by the RSTA administrator, the driver's license certificates presented at traffic stops, or the user records of the car rentals agency. In this demo, however, we set a TTL of one week for these documents to keep the amount of storage used by the demo from growing out of control. This requires a second index in the car rentals use case.
New capabilities
QR issuance to a phone browser, followed by presentation over a laptop browser
This capability, demonstrated below in the website registration use case, is implemented as follows:
The user requests a driver's license credential on a phone browser by scanning a QR code.
The issuer issues a credential to the phone browser and sets a replication passkey in the phone browser.
The user visits a relying party, such as a website, on a laptop browser where there is no driver's license credential and hence no service worker.
The relying party sends a credential presentation request to the credential issuer over the laptop browser, which reaches the issuer.
The issuer uses the replication passkey, synced from the phone browser to the laptop browser, to create a replica and present it over the laptop browser.
Email issuance to a laptop browser, followed by scanning a QR code for credential presentation over a phone browser
This capability, demonstrated below in the traffic stop use case, is implemented as follows:
The issuer sends a credential issuance URL to the driver by email.
The driver uses the URL to send a credential request to the issuer on a laptop browwer.
The issuer issues a credential to the laptop browser and sets a replication passkey.
A relying party agent, such as a police officer making a traffic stop, requests presentation of the mobile driver's credential by asking the driver to scan a QR code.
The driver scans the QR code with a phone where the default browser is an instance of the laptop browser to which the credential has been issued.
The phone sends a GET request to the URL in the QR code.
A relying party backend, such as a police department server supporting a fleet of patrol cars, redirects the GET request to a credential request endpoint of the credential issuer as a POST request comprising a challenge and a callback endpoint.
As there is no credential yet in the phone browser, there is no service worker to intercept the POST request, so the request reaches the issuer.
The issuer uses the replication passkey, synced from the laptop browser to the phone browser, to create a replica and present it over the phone browser.
Step-by-step demonstration
Setup
The demo has been tested on Chrome and Android using the Google Passord Manager (GPM) for passkey syncing. It may or may not work on other combinations of platforms. At this time, interception of credential requests by a service worker does not work on Firefox or Safari, but works on Edge and Brave.
To run the demo, use a Windows laptop and an Android phone both having Chrome as the default browser. Make sure you are logged in to Google on Chrome in both devices.
Delete any passkeys in the GPM pertaining to the v5-ci.pomcor.com origin.
Go to v5-ci.pomcor.com in the instances of Chrome that you are going to use and click on the cleanup link to delete any previously issued credential and unregister the service worker.
Website use case: QR issuance to phone, replication to laptop
On your laptop, go to the internal server of the RSTA data center at v5-ci-admin.pomcor.com, where you will play the role of RSTA administrator. You will be redirected to the home page of the administrator, where there are three links. The bottom link will list driver records created by all users of the demo, not just by you, and the top link will delete all of them.
Click the middle link to go to the "Driver record creation" page, which has a form where you are asked to enter five attributes plus your email address. The email address is not an attribute, it's just for email issuance.
Submitting the form takes you to a page were you see the driver record that you have created. What the page shows reflects very closely a MongoDB document within the "driverRecords" collection of the "rstaDb" database. The document has three fields called "createdAt", "retrievalToken", and "attributes", plus an "_id" field automatically created by MongoDB that is not shown in this page.
The value of the "attributes" field is a JSON object containing attributes conformant to the mDL data model, with names that can be found in Table 5 of the ISO/IEC 18013-5 specification.
The value of the retrieval token is a cryptographically random hex string with 128 bits of entropy that is used as a reference to the driver record, and as a secret that will authenticate the driver to whom the credential and its replicas will be issued.
The value of the createdAt attribute is a BSON date displayed as an ISO date string, used as explained above to set a one-week TTL for the record in order to keep the amount of storage used by the demo under control. It is not used for any other purpose and it will not be included in the credential.
At the bottom of the page there is a credential issuance URL that targets the edge server v5-ci and includes the retrieval token as a route parameter. Above that there are two links that you can use to convey the URL to the driver by means of a QR code or an email message. By hovering over the second link you will see how the issuance URL is percent-encoded in the body of the mailto URL.
Click the first link to go to a page the shows the credential issuance URL encoded as QR code, and as a clickable link below the QR code. Cliking the link would allow you to continue the demo using the laptop browser to simulate the phone, but we are not going to over that option here. Use your phone to scan the URL instead.
You are now playing the role of the driver and interacting with the edge server v5-ci on your phone, whereas before you were playing the role of administrator and interacting with the internal server v5-ci-admin on your laptop.
On your phone, the edge server asks you for consent to issue the credential. Give consent by clicking the Continue button.
On your phone, after you give consent, you are taken to a page that explains how a credential has been created and shows the full disclosure and the selective disclosure certificates. It also has a button for creating a replication passkey.
Clicking the passkey-creation button causes the frontend of v5-ci.pomcor.com to call navigator.credentials.create(), and the browser to display a modal dialog box that asks you where you want to create the passkey. Choose the GPM to enable cross-device syncing.
Then a second modal box asks you to confirm that you are trying to "create a passkey to sign-in to v5-ci.pomcor.com". That is not what the credential will be used for, because the demo uses replication passkeys, like service workers, for innovative purposes. But click the Create button anyway.
The call to navigator.credentials.create() takes as a parameter a "user" object with properties "id", "name" and "displayName". We use the retrieval token (encoded as a Uint8Array) as user.id, a timestamp as user.name, and the string "Credential replication passkey" as user.displayName.
After clicking the Create button you are prompted for the GPM PIN, and after entering the PIN you are told that the passkey has been created.
Now use your laptop browser, where there is no credential, to go to the home page of Bhutan's Rental Cars Agency at https://v5-rp-web.pomcor.com/home-page.html.
The page has a login form and a registration form, both with a username input. Choose a username, enter it in the registration form, and click the Register button. This causes the website to send a request to present the credential using the selective disclosure format of the certificate and disclosing five attributes: "document_number", "given_name", "family_name", "birth_date", and "resident_address".
Since there is no credential in the browser, there is also no service worker to intercept the request, and the request reaches the issuer. The frontend of the issuer calls navigator.credentials.get(), which causes the browser to display a modal dialog box that asks you to choose a passkey. The passkey that was created at step 7 in the phone browser has been synced to the laptop browser and its name should be the most recent entry in the dialog box. Since names are timestamps, select the entry with the highest numeric value.
Then the call to navigator.credentials.get() returns the retrieval token, which was entered at step 7 as the value of the user.id parameter, as the value of the userHandle property of the response. The issuer uses it to retrieve the driver record, and you are asked for consent to create a replica using the attributes in the record.
After providing consent to create the replica, you are asked for consent to present it and disclose the five attributes requested by the car rental agency.
After providing consent to present the replica, you are registered with the username chosen at step 12, the five attributes are placed in your profile, and you are logged in.
If you then log out you are taken to the home page and you can log in using the replica by entering the username that you supplied at registration. You are now asked for consent to disclose only one attribute, the document_number.
Traffic stop use case: email issuance to laptop, replication to phone
Email issuance can be implemented in many different ways, as discussed above in the section "Mailto protocol". Here we assume that gmail is configured on your laptop as your default mailto handler and your default email client and you will be using it in the demonstration when playing the role of administrator and when playing the role of driver.
Before demonstrating replication to the phone in this part of the demo, make sure that your phone does not already have a credential by going to v5-ci.pomcor.com on the phone's Chrome browser and clicking the cleanup link.
Playing the role of administrator, create a driver record as in the previous use case, setting your gmail address as the driver's email address. But in the "Driver recod created" page use the link to create a message to be sent to the driver instead of the link for generating a QR code. Clicking the link causes the message to be displayed in gmail, ready to be sent.
Playing the role of administrator, send the message.
Now playing the role of driver, use gmail to receive the message and click the credential issuance URL shown in the body of the message to request issuance of the credential to the laptop.
In the page that asks you for consent to issue the credential, click on "Continue".
In the page "Digital driver's license issued to your browser", click on the button to create the replication passkey. This causes the frontend of the issuer on the laptop to call navigator.credentials.create() using the retrieval token as the user.id parameter.
In the modal dialog box that asks you were to save the passkey, choose the GPM.
In the modal dialog box that asks "Create a passkey to sign-in to v5-ci.pomcor.com?" click Create after writing down or memorizing the last few digits of the timestamp used as the name of the passkey.
Enter the GPM PIN to create the passkey.
You are now done playing the role of driver and are instead managing the demo. Go to v5-rp-qr.pomcor.com and click the button to run the setup script for the traffic stop scenario, which creates five windows.
Delete the window that simulates the driver's phone, which you are not going to need.
Now playing the role of officer, enter a patrol ID, e.g. 1234, in the window that simulates the officer's home page and click the button to print the QR code.
Do NOT click the link in the window that simulates the printer. Instead, playing the role of driver, scan the QR code with your phone, where there is yet no credential and no service worker.
This causes the Chrome browser on your phone to send a GET request to the police department server supporting the fleet of patrol cars, which redirects it to the credential request endpoint of the issuer as a POST request containing a credential presentation challenge and a callback URL.
Since there is no service worker on the phone, the request reaches the issuer. The frontend of the issuer on the phone browser calls navigator.credentials.get(), which causes the browser to show a modal dialog box that asks you whether you want to use a saved passkey. Select the timestamp used as the name of the replication passkey that was created at steps 6-9 above on the laptop browser.
On your phone, enter the GPM PIN in the WebAuthn modal box that follows. This causes the call navigator.credentials.get() to return a response with a userHandle property whose value is the retrieval token that was used as the value of the user.id parameter then passkey was created on the laptop.
On your phone, the issuer uses the retrieval token to retrieve the credential attributes from the driver record, and asks for consent to create a credential replica with those attributes.
On your phone, after you provide consent create the replica, the issuer asks for consent to present it to the "Example City Police Department".
On the window that simulates the MDC of patrol car, configure the display by entering the same the patrol ID, e.g. 1234, that you entered at step 12 into into the officer's home page and is configured into the QR code. An entry for the credential that has been presented will then appear on the display of the MDC.
Getting the licenses of two drivers who are speeding together
An officer who sees two drivers speeding together must stop both of them to avoid a defense of selective prosecution. If both drivers are using mobile replicas of driver's license credentials, the officer can display their licenses on the MDC by asking them to scan the same static code printed on physical media.
You can verify this capability by continuing the above demonstration using the same phone with a replica of a different license, as follows.
Delete the credential that is now in the phone by going to v5-ci.pomcor.com on the phone's Chrome browser and clicking the cleanup link.
Repeat steps 2-9 above with different attributes to replace the license that is now in your laptop with a new license and create a new replication passkey for the new license.
Keeping the window that simulates the QR code printed on physical media as it is, scan the QR code with your phone.
When asked whether you want to use a saved passkey, choose the new passkey. The list may still have the name of the old passkey. Since the names are timestamps, the name of the new passkey has a higher numeric value.
As in steps 14-16 above, enter the GPM PIN, then consent to create a replica and present it to the police department.
If the window that simulates the MDC is still configured with the same patrol ID, it will now show both licenses.
Driving legally without a physical or digital driver's license
A benefit of a digital driver's license credential is that the driver does need to carry a physical license in a leather wallet while driving.
The ability to replicate a credential on demand from a laptop browser to a phone browser adds a further benefit. It means that the driver does not carry any driver's license at all, physical or digital. When stopped by a police officer and shown a QR code, the driver can cause a driver's license to appear on the MDC of the patrol car by scanning the QR code with a phone, even if there is no driver's license credential in the phone.
The police department server will send a credential request to the credential issuer through the phone browser, and the issuer will create and present a credential replica, if a passkey has been synced to the phone browser from a passkey that was set when the original credential was issued.
The original credential does not need to have been issued to a phone; it may have been issued by email to a laptop or a desktop. And the original credential may no longer exist, if it has been deleted from the device to which it was issued, or the device itself no longer exists.
