openwallet-foundation / acapy

ACA-Py is a foundation for building decentralized identity applications and services running in non-mobile environments.
https://aca-py.org
Apache License 2.0
421 stars 515 forks source link

Change webhook state once connection is created ? #1343

Closed milossolaja closed 2 years ago

milossolaja commented 3 years ago

Currently I am using agent together with Webhooks. What I have noticed is that "state" that is part of the JSON that is sent to the Webhook URL is not changed once new connection is created. It is done only after I use that Connection_id to, for example, Issue credential, send Proof Request or something similar. I tried to create connection using lissi, trinsic, esatus wallets but it is always the same.

For example, once create QR code that contains invitation URL, I get following JSON on my Webhook server:

{ connection_id: 'cdee131d-362a-4431-b186-67b0a4c302e0',
  invitation_mode: 'once',
  their_role: 'invitee',
  rfc23_state: 'invitation-sent',
  routing_state: 'none',
  state: 'invitation',
  created_at: '2021-08-05 06:10:06.398445Z',
  accept: 'auto',
  invitation_key: 'Ehke6YZB4bVuCw3NDteSs7b8yJZrzBUas1tNW71LQTLw',
  updated_at: '2021-08-05 06:10:06.398445Z' }

and state remains 'invitation' until I do something with this Connection_id.

My idea is to use this Webhook posts as a trigger for next POST proof request. That way I can automate the process of establishing connection and sending proof request. Basically what I need is state = active and after that the agent will send Proof Request. Is there a way to do that? Am I missing something?

Thanks!

swcurran commented 3 years ago

The issue is you get the state of the webhook at the time the webhook is fired, and so it is active. Unfortunately, the connection protocol (RFC 0160) that is used by AIP 1.0 and the web wallets are talking about, and it does not automatically move the state to active until it is used. This rectified in the did-exchange protocols (RFC 0023) (which is basically connections V2), but that doesn't help you.

Are you using --auto-accept ? If so, you might want to not use that, then have the controller send the "response" message (after the request), so you at least know the user has accepted the invitation. You will then be at "response-sent" state, and you can immediately or after a short delay send the proof request -- based on the assumption that the response will be processed.

milossolaja commented 3 years ago

Hi @swcurran , I am using --auto-accept. I can try without it but I am not sure that I understand your idea completely. Want is meant with "then have the controller send the "response" message (after the request), so you at least know the user has accepted the invitation" because in my case I have Wallet and Agent with a controller? Do you mean that I show QR code with invitation url, scan it with my wallet and by accepting it (from my wallet), the response message is automatically sent? Or I didn't understand it right?

Is there something else that can be used as a trigger for sending Proof request? In my case I have Android App with an UI that shows QR code but I want to avoid establishing background service that will constantly send GET requests just to find out whether my connection is established or not and use that as trigger for sending Proof Request.

swcurran commented 3 years ago

The problem you are having is that there is no event/webhook at the inviter side to say "the connection is active".

This is a problem in the protocol defined in RFC 0160 that unfortunately cannot be changed. So since you are stuck with RFC 0160 (and you are -- it's what the mobile agents are using until AIP 2.0 gets deployed), you get no events on the inviter side after the inviter sends the "response" message.

What I think is happening... If you have "--auto..." set, then you get NO events to the controller related to the protocol. The definition of "--auto..." is that you get a response at the end of the protocol, and since the inviter doesn't know if the protocol is done (if the invitee processed the last message), it doesn't send a message.

If you turn off auto, your controller will get an webhook on each event, including when the "request" message from the invitee is received. Your controller will then trigger the sending of the "response" message and know that it has been sent. It can use that to do whatever you want next.

We don't recommend using "--auto..." in production apps (it's a "debugging" option), so we've not had to work around it.

Hope that makes sense.

milossolaja commented 3 years ago

Hi @swcurran,

Sorry for late response. I tried to use agent without "--auto...". Here is an example how I usually start my agent:

PORTS="8020 11000" ./scripts/run_docker start --label Alice --inbound-transport http 0.0.0.0 8020 --outbound-transport http --admin 0.0.0.0 11000 --admin-insecure-mode --genesis-url http://dev.greenlight.bcovrin.vonx.io/genesis --seed Alice000000000000000000000000001 --endpoint http://192.168.56.133:8020/ --debug-connections --auto-provision --wallet-type indy --wallet-name Alice --wallet-key secret --webhook-url http://9vbn32189da7.ngrok.io

However, I still don't get web hooks on each event. For testing purposes, I built short .js server that listens to the web hooks and prints them out. Url path components that I used can be found here. Once I send an invitation I get web hook at /topic/connections but after accepting the invitation, there are no new events. At least not at any of the url paths that are listed in the link above. Am I making some other mistake?

swcurran commented 3 years ago

I think I know what is going on. The Alice Faber demo in the Alice Faber API demo cover this. Specifically, look at this step as part of the Establish connection flow. When not using "--auto", Alice has to both receive and accept the invitation, and then wait for Faber (the other party) to respond. The accept should send the RFC 0160 Connections "request" message, which Faber will receive and send back a RFC 0160 Connections "response" message.

Does that make sense?

milossolaja commented 3 years ago

That makes sense but unfortunately doesn't help me a lot. In Faber-Alice demo there are two Agents that communicate but in my case there is an Agent and digital Wallet on my cellphone so I am not able to implement all the steps like in demo. For example Alice has to both receive and accept the invitation, and then wait for Faber to respond. This process is not available when there is a wallet on one side. Am I right? That's why I think Webhooks won't help me a lot.

Could you recommend me some other solution how this whole process of creating connection and sending proof request right after that can be automated? I need something that can easily be used as a trigger for an Agent to send proof request once connection is established. Polling could be an option but I would like to avoid that if it is possible.

swcurran commented 3 years ago

I guess I'm not really understanding the issue. I thought the problem was with the non-mobile agent -- the one you do control. The digital wallet will do whatever the protocol states, and your ACA-Py instance should notify your controller via webhooks as events occur during the connection protocol. I'm not certain what events aren't being triggered in your deployment, but this is a common pattern.

Are you able to share your code?

milossolaja commented 3 years ago

Hi @swcurran ,

Unfortunately I am still not allowed to share my code.

Currently I am working on an Android app that includes Login and that is where, besides standard approaches, I want to implement credentials as another Login option.

Right now, the whole process works this way: I have a button that sends POST request /connections/create-invitation. After I get invitation url, it is presented as a QR code that can be scanned with digital wallet on my smartphone. After that, to get credentials for login, I need proof request. For that purpose there is a second button that needs to be manually pressed right after QR code is scanned. This button sends post request “present-proof”. However, these steps are for me somehow too complicated so I would like to automate them. That means, there will be only one button that, once clicked, shows QR code. My app should automatically, right after the connection is established, send proof request. That’s why I need some kind of a trigger for that, my agent needs to know when my connection is established and active. My idea was to use web hooks but because of the protocol RFC 0160 I think that won’t be possible. After I accept connection on my cellphone I don’t get notified, the status is not changed to “active” until I do something with it (like issue credential). When there are two agents like in Faber-Alice demo, it should work. In my case right now I don’t see any solution how this could be solved. That’s why I would appreciate your help. Since you are definitely more experienced with an agent, could you recommend me some other solution how to do this?

Thanks a lot for your time, really appreciate that!

ianco commented 3 years ago

Hi @srbms23

You can try out the aca-py agent communicating with a mobile agent (we usually test with Trinsic or esatus) using this demo: https://github.com/hyperledger/aries-cloudagent-python/blob/main/demo/AliceGetsAPhone.md

If you run the faber agent using the --events option then it will display the webhooks received by the faber agent during each protocol.

For the connection protocol, the sequence is:

At this point the mobile can optionally send an "ack" which will put faber's connection into active state, but as @swcurran mentions this is not implemented in any of the mobile agents, so at this point faber's connection is stuck in response-sent state.

We get around this by treating response-sent as active - you can use this connection to send credentials, ask for proofs, etc, and any operation will push the connection into active state.

I suggest you try out this flow with the faber demo and either Trinsic or esatus, and if that works then you can try with your app, or compare your code with the faber demo code to see any potential differences.

milossolaja commented 3 years ago

Hi @ianco,

Thanks for your time and help. I tried to start the demo and see how it works before digging into the code but with these commands TAILS_NETWORK=docker_tails-server LEDGER_URL=http://test.bcovrin.vonx.io ./run_demo faber --aip 10 --revocation --events I get the following error:

Preparing agent image...
sha256:308c41d3b9cba3d2fc86a3a9cef2b14423ed27643868184e5c0b3ba4f118015d

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
Trying to detect ngrok service endpoint
Detected ngrok agent endpoint [https://64f2-129-187-166-158.ngrok.io]
192.168.65.3
ngrok tails service name [ngrok-tails-server]
Fetching endpoint from ngrok service
Fetched ngrok tails server endpoint [https://3ad8-129-187-166-158.ngrok.io]
Starting [faber] agent with args [--port 8020 --aip 10 --revocation]
usage: faber.py [-h] [--no-auto] [-p <port>] [--did-exchange] [--revocation]
                [--tails-server-base-url <tails-server-base-url>] [--timing]
                [--multitenant] [--mediation] [--wallet-type <wallet-type>]
                [--arg-file <arg-file>]
**faber.py: error: unrecognized arguments: --aip 10**

I followed each step as in link above. Is there something else I should do/try?

ianco commented 3 years ago

Hi @srbms23 , check the aca-py/demo version you are running, I just tested your command on the latest version of code from main and it runs fine.

swcurran commented 2 years ago

Closing.