Messaging
Last updated
Last updated
in , we have covered the mediator basics and the different ways of communication it supports. But how does Decentrl messaging work?
Decentrl messaging could be compared to an event-driven microservice design, where each client (identity) acts as a service in a big network where mediators act as message brokers responsible for delivering messages to identities.
To start interacting with a mediator, identity first has to establish websocket connection.
Communication with the mediator is made of two different types of messages
Commands
Events
Commands are a type of message that instructs the mediator to do an action. Below are a few examples of possible commands
Request challenge
Authenticate with challenge
Forward Instructs Mediator to forward a specific message to identity
Command payload should be a with a type
property describing the command type. Below is an example of how the command payload could look before being encrypted.
Before the command is sent to the mediator, it should be encrypted using the routing public key, which can be found inside the mediators DID document.
Events are a type of message that notifies the identity of what has happened. Below are a few examples of possible events
Challenge generated
Authentication completed
Authentication failed
Message forwarded
The event payload should look something like this
Once a web socket connection with Mediator is established, authentication has to be performed regardless if you are registered on that mediator or not. Authentication is done so the mediator knows which web socket connection belongs to which identity.
Mediators should support two types of authentication
Authentication with challenge
Authentication with token
When authenticating with a challenge, identity first has to request the challenge from the mediator using the REQUEST_CHALLENGE command. This command has no payload.
The mediator will respond with a CHALLENGE_GENERATED event, which should include the challenge in the payload. Challenge is a JWT with an expiration time of 2 minutes.
Once the challenge is retrieved, it can be packed into the AUTHENTICATE_WITH_CHALLENGE command, encrypted, and sent to the mediator.
Once the mediator receives the AUTHENTICATE_WITH_CHALLENGE command, it first decrypts it and verifies the sender's identity. Once the verification is done, the mediator verifies the signed challenge. If all verifications pass authentication is completed and the mediator sends AUTHENTICATION_COMPLETED event to the identity. The event payload should look like this
If authentication fails AUTHENTICATION_FAILED event will be sent to the identity.
If the identity has a valid token (that was returned by the challenge authentication method) they can authenticate by skipping the challenge-generating part. To authenticate with the token, an AUTHENTICATE_WITH_TOKEN command should be sent to the mediator, with the following body
Depending on the validity of the token, the mediator will respond with AUTHENTICATION_COMPLETED or AUTHENTICATION_FAILED events respectively.
Having covered the types of communication mediators support, and the communication with the mediator itself, we can talk about how communication between identities should look like.
In the previous example, the Decentrl protocol was compared to an event-driven microservice architecture where each identity is a service and the mediator is a message broker.
The messaging between two clients (identities) should be event-based as it would be in such a system. That means that each client builds its own state locally by aggregating the events received from others.
This example will describe how you could implement basic chat between two identities using Decentrl.
As mentioned before, clients (identities) should not rely on mediators to build their state, but rather build it locally. By doing that, the privacy aspect is increased as the mediators don't have to know anything about the message that's being exchanged by clients. This not only increases privacy but also enables developers to develop any kind of application on top of Decentrl, as long as message transfer is supported by the mediator. One of the applications that could be easily developed is E2EE chat between two identities.
For this application two-way private communication will be used to transfer messages between two identities.
Let's say we have two different actors, Bob and Alice. Each one of them has its own DID. In order to send Alice a message, Bob first needs to know her DID. He can either get her DID by some other communication channel or by searching one of the public namespaces.
Bob first has to resolve Alices' DID to get a list of her mediators. Once the DID document is fetched, Bob has to connect and authenticate on Alices' mediators. Note: Bob does not have to connect to all mediators but to at least one. Connecting and sending messages to multiple mediators is preferred as it will increase the message delivery rate.
With a mediator connection established, Bob can send the message to Alice. The message should be in a form of an event that reflects the change that happened to Bobs' local client. Once Bob clicks to send a message, his local client updates the local state and adds the message to the store. This local-state change produces an event that can be forwarded to Alice, so she can also update her local state accordingly. The event should be in the format of a DIDComm message and should look something like this:
The message is transported to Alice using a two-way private communication mediator feature, meaning that the message is first encrypted using Alices' public key. The encrypted text is then inserted into a mediator command payload, encrypted with the mediators' public key, and sent to it.
In order for Alice to retrieve the events she first has to connect to all her mediator nodes to collect the messages. If Alices' connection to mediators was established at the time when Bob sent his message, mediators would automatically push the message to Alice. If the connection was not established, Alice has to ask the mediator to send her all messages that came in while she was offline via the message search command.
Once the mediator returns the message from Bob, Alice first has to decrypt it using her private key and Bobs' public key. This operation is also called Authcrypt as it verifies that the message was sent from Bob by requiring his public key to decrypt it. Once the message is decrypted, Alice can update her local state to reflect the change that Bob has made on his end, in this case, sending a new message.
Alice received and read the message, but she did not have time to reply. She decided to react to the message instead. The message reaction is first reflected in her local state and after that, the event describing that change is emitted to Bobs' mediators, so Bob can update his local state. The event would look something like this
This type of communication enables features such as chat. When identity registers on a mediator and picks this as one of the communication channels they wish to use, they will open a channel through which others who know their DID will be able to send them messages.
The two-way private communication feature implements two commands on the mediator.
Forward command - instructs mediator to forward a specific encrypted message to an identity that's registered on that mediator
Search messages command - adds the ability for identity to fetch messages from their mediators.
Instructs mediator to forward a specific encrypted message to an identity that's registered on that mediator. The forward command extends DIDComm and should look like this
The command type should be FORWARD
The body should contain a property called next
which should have the recipient identity DID as the value
The encrypted message that is to be forwarded to the identity needs to be added to the command as an attachment
After the mediator receives a command such as this, it should first check if the recipient identity has an active web socket connection. In the case it does, it should forward the message directly. If not, the identity will have to fetch the message from the mediator using the search messages command.
When forwarding a message to a mediator, identity can choose to add additional metadata that could optimize the user experience as well as message searching.
If we refer to Example 1, Alice could attach a message ID metadata to her reaction message. The forward command would look something like this
With the metadata sent to the mediator, Bob could now filter message search results by metadata values. In this case, Bob could only fetch all events related to his original message by filtering by "metadata.messageId": "2a2e5f12-1b4c-42be-ac43-152b2156cfab".
Adds the ability for identity to fetch messages from their mediators. The commnd should look something like that
The command type should be SEARCH_MESSAGES
The body should have properties as described above. All of these properties are optional.
After receiving a command such as this, the mediator will query its database and pull out all messages that match the following filters, and send it back to the requester using the MESSAGE_SEARCH_RESULT event. The event should look something like this
This type of communication enables features such as status updates. When identity registers on a mediator and picks this as one of the communication channels they wish to use, they will open a channel through which others who know their DID will be able to read their public messages but won't be able to react or send a message back to the original sender.
The one-way public communication feature implements two commands on the mediator.
Post command - instruct the mediator to save a message that can be fetched by anyone
Search posts command - adds the ability for anyone who knows Identities DID to query their public posts.
Instruct the mediator to save a message that can be fetched by anyone. The post command extends DIDComm and should look like this
The command type should be PUBLIC_POST
The command body should include a JSON web signature of a DIDComm extended message
Metadata can be attached to the command the same way as on two-way private communication.
Adds the ability for anyone who knows Identities DID to query their public posts. The search command should look something like this
The command type should be SEARCH_PUBLIC_POSTS.
The body should have properties as described above. All properties except authorDid are optional.
After receiving a command such as this, the mediator will query its database and pull out all messages that match the following filters and send it back to the requester using the PUBLIC_POST_SEARCH_RESULT event. The event should look something like this
This example will describe how you could implement basic social network client, that displays identities public posts.
For this application one-way public communication will be used for publishing and reading posts.
Let's say we have two different actors. Bob, who is a famous entrepreneur and Alice who is a follower of her work.
Bob: Create a public-facing identity
Bob is a public figure and he wants his followers to know what he's up to, but he doesn't want to be messaged back by his followers as it would most likely result in a lot of spam. That's why Bob decides to create a new DID, which purpose is to be a public-facing identity with no way of being contacted. To do that, he registers his DID on mediators with only a one-way public communication feature enabled. This way, other DIDs will be able to query his public posts but will not be able to send him a message as he doesn't have a two-way private communication feature enabled.
Bob: Post a public message
Bob has just released a new product and he wants to share it with the world. He first creates a message informing others about his new product. The message would look something like this
After the message is made, Bob signs it using his public signing key and posts it to his mediators using the PUBLIC_POST command.
Once the command is sent to the mediators, they save it to their database, and the message is now avaiable to be fetched by anyone who knows Bob's DID.
Alice: Read Bob's public message
Alice decides to see what Bob's been up to, so she connects to Bob's public DIDs mediators and sends the SEARCH_PUBLIC_POSTS command.
After the command executes on the mediator, Alice receives the array of Bobs status updates where she sees that he just released a new product! At first she's skeptical about the authenticity of the messages and integrity of the mediators but after she verifies the message signatures, she is sure that Bob indeed released a new product!
Because DIDs are randomly generated, it is very unlikely for an attacker to someone's DID and start spamming them unless that identity is registered on some public namespace, where the DID is open to public.