Chrome Extension, as its name suggests, extends the capabilities of Agent Details Web Page in the Chrome web browser. It enables issuer/verifier web applications to interact with a user's Cloud-Agent by acting as a middle man. While transactions requiring security still happens directly between your cloud agent and the issuer/verifier agent, when the web app would like to connect to your agent for the first time or wants to ask you to store or retrieve information, the request is made through the browser extension. This capability reduces the number of times you need to navigate to your Agent Details Web Page to accept/share credentials with the interested parties and provides an enhanced desktop user experience.

Once the extension is installed, it allows you to interact with issuer/verifier web pages without leaving that page. The extension will show necessary popup windows when a request requires you to accept or reject it.

The extension also allows you to easily change which of your agents it is managing and issuer/verifier web pages will interact with the currently selected agent only. This allows you to easily manage multiple identities to interact with multiple issuer/verifiers.


A web browser extension allows Holders to store and present credentials. The browser extension is an edge agent that is bound to a cloud agent associated with your IBM Verify Credentials Agency Account.

Browser Extension Installer
brave Currently Unavailable
chrome Chrome Extension
edge Currently Unavailable
firefox Currently Unavailable
safari Currently Unavailable


Currently the Chrome Extension comes pre-configured and does not require any configuration steps after installment. It does, however, require you to be logged into your IBM Verify Credentials Agency Account in order to function.


Interacting with the extension is done by clicking on the extension icon typically located as shown in the figure below.


There are two possible popup user interfaces that will be shown by the extension. First one is when no valid IBM Verify Credentials Agency Account session is detected. After the user clicks on the extension and there isn't any valid IBM id session (which allows the user to log in to IBM Verify Credentials Agency Account), the following popup screen is shown. You will also see that the extension icon is now gray. This indicates the lack of aforementioned IBM id session.

To begin such a session, click on the Sign in with IBM id button to create a session with IBM Verify Credentials Agency Account. This button opens a new tab for you to enter your IBM id and password as shown below.

IBM ID signin panel

Upon creating a valid IBM id session, if you click on the extension icon again, your list of agents associated with this IBM ID will be displayed similar to the image below. The currently active agent will have a blue radio button next to it. You can switch to another agent by clicking the corresponding radio button. Issuer/verifier websites will send and receive credentials only from the currently active agent.

agent list

Lastly but not the least, you will see IBM Verify Credentials on top left corner. Clicking on IBM Verify Credentials will take the user to her IBM Cloud Agent dashboard.

The extension itself does not store any credential. Your credentials are stored in your IBM Cloud Agent. What the extension does do is display to you a prompt to retrieve a yes/no answer for connection requests and credential issuance requests from issuers and upon a yes answer, forwards that request to the selected IBM Cloud Agent to process.

In the following picture you will see a connection offer prompt. This will let you know there is a connection request as well as show to you the agent url of the requester. Accepting this connection offer will establish a connection between your IBM Cloud Agent and the issuer's cloud agent.

connection offer dialog

Next is the credential offer request which comes from an issuer. This prompt will show who is the issuer and what the claims are that they are offering. The number of attributes in a credential can be numerous, that is why that section of the prompt is scrollable. Once the user accepts the credential offer, the offered credential will be stored in your IBM Cloud Agent wallet.

credential offer dialog

Providing a proof

You'll notice similar flows when providing a proof. When a verifier requests a proof, the extension is aware of the proof response that the cloud agent generates for this proof request and displays it to you. If you wish to share this proof response, the extension will forward it to your IBM Cloud Agent to process.

You can see in the prompt window below that the name of the verifier is displayed on the top line and the middle section contains the generated proof. This proof contains the attribute names and values to be shared with the verifier. If you choose to share these attributes and answer Yes to this prompt, the extension forwards this request to your IBM Cloud Agent which will then exchange the actual data across the secure connection between your agent and the verifier's agent.

proof response dialog

Please be aware that all of the aforementioned prompts will be closed after 60 seconds if you do not take an action during this time.

Delete extension

In order to delete the extension, you need to go to the browser's extension management page. Here, there will be the list of extensions which are currently installed. Inside each extension box, there is a Remove button. This will delete the extension from your browser. Removing your browser extension will not affect the connections and credentials you have already acquired with your cloud agent.

extension box


In this section we give a very high level overview of how the extension works with issuer/verifier web apps and how developers can enable their services to support the extension.

Extension v. Mobile App for Developers

For the vast majority of use cases, the process flows that issuers and verifiers use when managing credentials and proofs aren't affected by a holder using a mobile app. Because the issuers and verifiers are making requests such as connection requests, credential requests and proof requests directly through their agents, and those requests are communicated to the Holder's agent through an agent to agent communication layer, the Issuers and verifiers don't need to know if their customer is using mobile devices or not. A holder's mobile app will get the appropriate notifications from their associated agent and will respond again through their own agent back to the issuer/verifier agent.

With mobile devices, though, the user of the issuer or verifier web application will have to respond to prompts on their mobile device and potentially also prompts from the web application to achieve their goals. When an issuer or verifier decides to support the Chrome extension they will allow their users to work completely in the context of their web browser and within the flow of the web application without shifting their focus to a mobile device. And in most cases users can use the issuer or verifier web application without using the mobile application at all. However, this requires the issuer and verifier web applications to add support for the browser extension.

One fundamental difference that issuer/verifier web page developers need to account for is that mobile application users get notifications from their agents on their device and they respond to the notifications at their leisure. With the browser extension, any request can be immediately passed to the extension which will in turn pass it to the user's cloud agent which can then prompt the user. This keeps the user engaged with the web application as confirmations required by the cloud agent can be answered by the user in real time. These user actions include accepting or rejecting connection offers, credential offers, and proof requests. This direct communication between web pages and the extension makes an automated web-based notification system in the cloud agent unnecessary.

Detecting Chrome Extension

The IBM Verify Credentials Extension works by injecting a script into web pages as they load in the browser. This injection process takes a few milliseconds so the functionality of the extension is available after this small delay. In order to determine that the user has installed the browser extension and that the injection process has successfully completed, the developer needs to listen for "contentHolder_injected" custom event.

document.addEventListener("contentHolder_injected", function(){
    //Extension is detected

Communication Layout

In this section we explain the communication pattern of the extension which will be used by the developers. The window.verifyCreds API (the arrow marked as 1 in the figure below) is the only communication interface the developers need to use.


When content.js is injected, it attaches an asyc verifyCreds function to the window object of the issuer/verifier web page. window.verifyCreds embeds an iframe with its source set to the selected cloud-agent of the holder who is currently browsing this web page. In essence, arrow 1 represents the communication between the cloud-agent ui and the issuer/web page (not the extension!) as the extension functions only as a messenger once its injection of window.verifyCreds into the web page is complete.


Here we explain how to call window.verifyCreds APIs and what the return values are. We would like to note that in many cases the returned error types mentioned in this documentation are limited in number and generalized in content even though more specific error types can be detected. The goal was to keep the development expreience as similar as possible whether the end user is a mobile application user or an extension user.


The extension is enabled in every web page a holder navigates to by default. This is due to the following permission the extension is asking for in its manifest:

"content_scripts" : [
        "matches" : [ "https://*/*"],
        "js": ["content.js"],
        "all_frames": true

This means the content.js file of the extension will be injected into every web page whose url starts with https. That being said, in order to begin exploiting the extension's capabilities, the web page needs to send an initialization command. This initialize signal has been added to make sure only the web pages which are interested in using the extension will be able to trigger it.

To initialize, call: window.verifyCreds({operation: 'init'}).

This operation embeds an iframe containing the cloud-agent of the holder inside the web page. Example usage:

try {
    var initialized = await window.verifyCreds({operation: 'init'});
    /* Some operation*/
catch (err) {
    console.log("Caught init error: " + JSON.stringify(err));

In order to succesfully embed the cloud agent iframe, the holder needs to have a valid IBM Verify Credentials Agency Account session. If so, the init operation returns "True". However, there are some circumstances which might prevent the extension from being initialized. In case of an error, an exception is thrown with an error code and message. Here is the list of exceptions that could be thrown while initializing.

  • {code: "NO_AGENCY_SESSION", message: "Holder does not have a valid IBM Id session. Needs to log in to her IBM Agency Account."}
  • {code: "NO_AGENT", message: "Holder does not have any agent. Needs to create one by logging in to her IBM Agency Account."}
  • {code: "AGENT_NOT_READY", message: "Holder's agent is being created. Needs to try again in 5 minutes."}
  • {code: "AGENT_TIMEOUT", message: "Requests to holder's agent is timing out. Should be retried."}
  • {code: "POPUP_DISABLED", message: "User disabled extension popups. Needs to enable it."}

These error messages are directed to the developers that need to handle them and not really meant for the end user to see.

Fetch holder DID

The DID of the currently selected holder's agent can be fetched via await window.verifyCreds({operation: 'info'}). The reason why it is called info is because it will eventually return more info about the holder, such as holder's agent url, in the upcoming versions of the extension as needed.

This example code shows how to fetch the holder's DID:

try {
    var holderDID = await window.verifyCreds({operation: 'info'});
catch(err) {
    console.log("Caught info error: " + JSON.stringify(err));

On success, the DID of the agent is returned. Possible error codes are the following:

  • {code: "NO_INFO", message: "Holder's DID could not be fetched."}
  • {code: "NO_ACTION",message: "No value is returned from cloud-agent iframe. Holder either did not take any action or the offer could not be displayed."}

Here "NO_ACTION" means that the request was sent to the cloud-agent iframe but no response was returned after waiting for one minute. If this is returned during initialization, the error is most likely because requests to the cloud-agent are timing out. There is no action that the user needs to take. The best strategy is to retry the request in this case.

Extend a connection offer

Issuer/verifier web pages can request the extension to extend a connection offer to the holder and ask them to respond. This can be accomplished via:

try {
    var connectionResponse = await window.verifyCreds(
        operation: 'respondToConnectionOffer',
        connectionOffer: connectionOffer
catch(err) {
    debug("Caught error in credential offer: " + JSON.stringify(err));

This operation will trigger a popup window inside the issuer/verifier web page (see extension documentation for end user) to let the holder accept or reject a connection offer. Upon acceptance, there will be an agent to agent communication established between the issuer/verifier's agent and holder's currently selected agent.

The connectionOffer object in this call needs to be the whole connection offer object returned by the isser/verifier agent. If the connection type is in-band, then the extension will only use the connection id part of the object to set the state of the connection offer to accepted or rejectedbased on how the holder responds to the connection offer. If the connection type is out-of-band, then the whole connection offer object is given to the holder's agent to initiate an agent to agent connection.

If the operation succeeds then the following object is returned: {message: "Successfully displayed connection offer"}. The decision that the user had made will not be returned. The issuer/verifier web page needs to fetch the state of the connection from their own agent just like it does for the mobile app path.

In case of an error, the following codes are returned:

  • {code:"NO_DISPLAY", message: "Was unable to ask for holder action."}
  • {code: "NO_ACTION",message: "No value is returned from cloud-agent iframe. Holder either did not take any action or the offer could not be displayed."}

We have already discussed NO_ACTION previously. However, in this case, it is also possible that the user did not accept or reject the connection offer. NO_DISPLAY means there was a problem and the holder was not shown the popup window to accept/reject the connection offer.

Extend a credential offer

Issuer web pages can request the extension to extend a credential offer to the holder and ask them to respond. This can be accomplished via:

try {
    var credential = await window.verifyCreds(
        operation: 'respondToCredentialOffer',
        credentialOfferId: credentialOffer.id
catch(err) {
    debug("Caught error in credential offer: " + JSON.stringify(err));

This operation will trigger a popup window inside the issuer web page (see extension documentation for end user) to let holder accept or reject the credential offer. Upon acceptance, the proposed credential will be stored in holder's currently selected agent.

credentialOfferId is the id field of the credential to be offered. The state of the credential has to be inbound_offer in holder's agent and outbound_offer in issuer's agent for this operation to succeed. Upon accepting the credential offer, the state of the credential will be changed to accepted in both agents.

Success message is {message: "Successfully displayed credential offer."}.

In case of an error, the following codes are returned:

  • {code:"NO_DISPLAY", message: "Was unable to ask for holder action."}
  • {code: "NO_ACTION",message: "No value is returned from cloud-agent iframe. Holder either did not take any action or the offer could not be displayed."}
Extend a proof request

Verifier web pages can request the extension to extend a proof request to the holder and ask them to respond. This can be accomplished via:

try {
    var proof = await window.verifyCreds(
        operation: 'respondToProofRequest',
        proofRequestId: proofRequest.id
catch(err) {
    console.log("Caught error in proof request: " + JSON.stringify(err))

This operation will trigger a popup window inside the verifier web page (see extension documentation for end user). The prover will be presented with a constructed list of claim values from credentials they hold that can satisfy the proof request. The prover can choose accept to share the proffered proof response or reject to reject the proof request. Upon accepting, the proof response will be generated in the holder's currently selected agent and shared with the verifier's agent.

In the code snippet above, proofRequestId is being set to the id field of the proof request which was built in the verifier's agent and sent to the prover's agent prior to triggering this operation. The state of the proof needs to be outbound_proof_request on verifier's agent and inbound_proof_request in prover's agent before this operation is triggered.

Success message is {message: "Succesfully displayed proof request."}.

In case of an error, the following codes are returned:

  • {code:"NO_DISPLAY", message: "Was unable to ask for holder action."}
  • {code: "NO_ACTION",message: "No value is returned from cloud-agent iframe. Holder either did not take any action or the offer could not be displayed."}


Content Security Policy Violation

Error Message

Refused to display 'https://idaas.iam.ibm.com/idaas/*' in a frame because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' https://www.ibm.com/".


This error indicates that extension tried to load the IBM IDaaS URL as an iframe which is not permitted by IDaaS CSP. The extension is programmed to not do this explicitly. However, it is possible to be redirected to IBM IDaaS url if you try to navigate to your cloud-agent and your cloud-agent thinks you do not have a valid session. Once again the extension makes sure you have a valid session before it tries to embed the cloud-agent url as an iframe. So why might this still be happening? The answer is your browser is set to "Block third party cookies".

When "Block third party cookies" is enabled, your login request to your cloud-agent will be missing the CA_ACCOUNT and CA_AGENT cookies in its request header.


In order to be sure that you have a valid session with your cloud-agent, you can try to navigate to your cloud-agent url in a new browser tab and see if you can login.

If you have a valid cloud-agent session and are experiencing the aforementioned error, this is most likely because of the "Block third party cookies" setting. To turn this off:

  • From the Chrome menu in the top right corner of the browser, select Settings/Preferences.
  • At the bottom of the preferences page, click Advanced
  • Under Privacy and Security, select Site Settings
  • Under Permissions, select Cookies
  • Turn off the Block third party cookies setting

Failure to Display Popup


The popup window which asks for user action is not showing OR after accepting a request the demo fails


You may experience that the extension window, which asks for user actions such as choosing yes/no to a request, does not pop up. Even if it does pop up and you click yes, the demo fails. Most of the time this happens when the GET/PATCH/DELETE/POST http request to your agent times out. In other words, the extension sends the request but no response is received. In this case, you should first click on the extension icon and make sure you see your agent and then retry the demo.