messageHandler function

Future<void> messageHandler(
  1. String jwe,
  2. String mnemonic,
  3. String did,
  4. InfraDIDCommAgent agent,
  5. bool didAuthCallback(
    1. String peerDID
    )?,
  6. dynamic didConnectedCallback(
    1. String peerDID
    )?,
  7. dynamic didAuthFailedCallback(
    1. String peerDID
    )?,
  8. Future<Map<String, dynamic>> vpRequestCallback(
    1. List<RequestVC> requestVCs,
    2. String challenge
    )?,
  9. bool vpVerifyCallback(
    1. Map<String, dynamic> vp
    )?,
  10. dynamic vpSubmitResCallback(
    1. SubmitVPResponseMessage message
    )?,
  11. dynamic vpSubmitLaterResCallback(
    1. SubmitVPLaterResponseMessage message
    )?,
  12. dynamic vpRejectCallback(
    1. RejectRequestVPMessage message
    )?,
)

Handles incoming messages and performs necessary actions based on the message type.

The messageHandler function takes in the following parameters:

  • jwe: The JWE (JSON Web Encryption) string representing the incoming message.
  • mnemonic: The mnemonic string used for key generation.
  • did: The DID (Decentralized Identifier) string.
  • agent: An instance of the InfraDIDCommAgent class representing the agent.
  • didAuthCallback: An optional callback function that is called when a DID Auth message is received.
  • didConnectedCallback: An optional callback function that is called when a DID Connected message is received.
  • didAuthFailedCallback: An optional callback function that is called when a DID Auth Failed message is received.

The messageHandler function handles different types of messages based on the algorithm specified in the JWE header. If the algorithm is "ECDH-ES", it handles the DIDAuthInit message and sends a DID Auth message if successful. If the algorithm is "dir", it handles both DIDAuth and DIDConnected messages.

Throws an exception if an error occurs during message handling.

Implementation

Future<void> messageHandler(
  String jwe,
  String mnemonic,
  String did,
  InfraDIDCommAgent agent,
  bool Function(String peerDID)? didAuthCallback,
  Function(String peerDID)? didConnectedCallback,
  Function(String peerDID)? didAuthFailedCallback,
  Future<Map<String, dynamic>> Function(
    List<RequestVC> requestVCs,
    String challenge,
  )? vpRequestCallback,
  bool Function(Map<String, dynamic> vp)? vpVerifyCallback,
  Function(SubmitVPResponseMessage message)? vpSubmitResCallback,
  Function(SubmitVPLaterResponseMessage message)? vpSubmitLaterResCallback,
  Function(RejectRequestVPMessage message)? vpRejectCallback,
) async {
  try {
    Map<String, dynamic> header = extractJWEHeader(jwe);
    String alg = header["alg"];
    if (alg == "ECDH-ES") {
      // Handle DIDAuthInit Message
      Map<String, dynamic> epk = header["epk"];
      List<int> privatekey = await privateKeyFromUri(mnemonic);
      Map<String, dynamic> x25519JwkPrivateKey =
          await x25519JwkFromEd25519PrivateKey(privatekey);
      List<int> sharedKey = await makeSharedKey(
        privateKeyfromX25519Jwk(x25519JwkPrivateKey),
        publicKeyfromX25519Jwk(epk),
      );
      String jwsFromJwe = await decryptJWE(jwe, jwkFromSharedKey(sharedKey));
      var payload = decodeJWS(jwsFromJwe);
      String fromDID = payload["from"];
      String fromAddress = fromDID.split(":").last;
      List<int> fromPublicKey = publicKeyFromAddress(fromAddress);
      Map<String, dynamic> jwsPayload =
          verifyJWS(jwsFromJwe, hex.encode(fromPublicKey));
      agent.peerInfo = {
        "did": jwsPayload["from"],
        "socketId": jwsPayload["body"]["socketId"],
      };
      agent.isReceivedDIDAuthInit = true;
      // If Success, Send DID Auth Message
      if (didAuthCallback != null) didAuthCallback(fromDID);
      sendDIDAuthMessage(mnemonic, jwsPayload, agent);
    }
    if (alg == "dir") {
      // Handle DIDAuth && DIDConnected Message
      List<int> privatekey = await privateKeyFromUri(mnemonic);
      Map<String, dynamic> x25519JwkPrivateKey =
          await x25519JwkFromEd25519PrivateKey(privatekey);
      if (agent.peerInfo.containsKey("did")) {
        String? fromDID = agent.peerInfo["did"];
        String fromAddress = fromDID!.split(":").last;
        List<int> fromPublicKey = publicKeyFromAddress(fromAddress);
        Map<String, dynamic> x25519JwkPublicKey =
            x25519JwkFromEd25519PublicKey(fromPublicKey);

        List<int> sharedKey = await makeSharedKey(
          privateKeyfromX25519Jwk(x25519JwkPrivateKey),
          publicKeyfromX25519Jwk(x25519JwkPublicKey),
        );
        String jwsFromJwe = await decryptJWE(jwe, jwkFromSharedKey(sharedKey));
        Map<String, dynamic> jwsPayload =
            verifyJWS(jwsFromJwe, hex.encode(fromPublicKey));

        if (jwsPayload["type"] == "DIDAuth") {
          // If Success, Send DID Connected Message
          if (didAuthCallback != null) didAuthCallback(fromDID);
          sendDIDConnectedMessage(
            mnemonic,
            jwsPayload,
            agent,
          );
          if (agent.role == "VERIFIER") {
            agent.isDIDConnected = true;
          }
        }
        if (jwsPayload["type"] == "DIDConnected") {
          print("DIDConnected Message Received");
          if (didConnectedCallback != null) didConnectedCallback(fromDID);
          agent.isDIDConnected = true;
          if (agent.role == "VERIFIER") {
            sendDIDConnectedMessage(
              mnemonic,
              jwsPayload,
              agent,
            );
          }
        }
        if (jwsPayload["type"] == "DIDAuthFailed") {
          if (didAuthFailedCallback != null) didAuthFailedCallback(fromDID);
          print("DIDAuthFailed Message Received");
          agent.disconnect();
        }
        if (jwsPayload["type"] == "VPReq") {
          print("VPRequestMessage Message Received");
          if (vpRequestCallback != null) {
            Map<String, dynamic> result = await vpRequestCallback(
              (jwsPayload["body"]["vcRequirements"] as List<dynamic>)
                  .map<RequestVC>((vc) => RequestVC.fromJson(vc))
                  .toList(),
              jwsPayload["body"]["challenge"],
            );
            var status = result["status"] as String;
            if (status == VPRequestResponseType.submit.name) {
              var vp = result["vp"] as String;
              await sendSubmitVPMessage(
                mnemonic,
                did,
                agent,
                VPRequestMessage.fromJson(jwsPayload),
                vp,
              );
            } else if (status == VPRequestResponseType.reject.name) {
              var reason = result.containsKey("reason")
                  ? result["reason"] as String
                  : "Rejected";

              await sendRejectRequestVPMessage(
                mnemonic,
                did,
                agent,
                VPRequestMessage.fromJson(jwsPayload),
                reason,
              );
            } else if (status == VPRequestResponseType.submitLater.name) {
              await sendSubmitVPLaterMessage(
                mnemonic,
                did,
                agent,
                VPRequestMessage.fromJson(jwsPayload),
              );
            }
          }
        }
        if (jwsPayload["type"] == "VPSubmit") {
          bool isVerified = await verifyVP(
            jwsPayload["body"]["vp"],
            agent.vpChallenge,
          );

          if (vpVerifyCallback != null) {
            String jsonStringVP =
                utf8.decode(base64Url.decode(jwsPayload["body"]["vp"]));
            Map<String, dynamic> vp = json.decode(jsonStringVP);

            bool customVerification = vpVerifyCallback(vp);
            if (!customVerification) {
              isVerified = false;
            }
          }

          await sendSubmitVPResponseMessage(
            mnemonic,
            did,
            agent,
            SubmitVPMessage.fromJson(jwsPayload),
            isVerified,
          );
        }
        if (jwsPayload["type"] == "VPSubmitRes") {
          print("SubmitVPRes Message Received");
          if (vpSubmitResCallback != null) {
            vpSubmitResCallback(SubmitVPResponseMessage.fromJson(jwsPayload));
          }
        }
        if (jwsPayload["type"] == "VPReqReject") {
          if (vpRejectCallback != null) {
            vpRejectCallback(
              RejectRequestVPMessage.fromJson(jwsPayload),
            );
          }
          await sendRejectRequestVPResponseMessage(
            mnemonic,
            did,
            agent,
            RejectRequestVPMessage.fromJson(jwsPayload),
          );
        }
        if (jwsPayload["type"] == "VPReqRejectRes") {
          print("RejectReqVPRes Message Received");
        }
        if (jwsPayload["type"] == "VPSubmitLater") {
          await sendSubmitVPLaterResponseMessage(
            mnemonic,
            did,
            agent,
            SubmitVPLaterMessage.fromJson(jwsPayload),
            agent.vpLaterCallbackEndpoint,
          );
        }
        if (jwsPayload["type"] == "VPSubmitLaterRes") {
          print("SubmitVPLaterRes Message Received");
          if (vpSubmitLaterResCallback != null) {
            vpSubmitLaterResCallback(
              SubmitVPLaterResponseMessage.fromJson(jwsPayload),
            );
          }
        }
      }
    }
  } catch (e) {
    sendDIDAuthFailedMessage(mnemonic, did, agent);
    agent.disconnect();
    throw Exception("Error in message handling: $e");
  }
}