hyperledger-labs / business-partner-agent

The Business Partner Agent is a SSI wallet and controller based on aries cloud agent python.
https://labs.hyperledger.org/business-partner-agent/
Apache License 2.0
56 stars 48 forks source link

Allow self attested attributes when answering a presentation request #801

Open etschelp opened 1 year ago

etschelp commented 1 year ago

See also: https://github.com/hyperledger-labs/business-partner-agent/issues/650

In case the presentation request has no restrictions on the issuer, or issuer is holder, the request can also be answered with self attested attributes. This could be a very nice feature if we make it document based, as this avoids connecting the agent to itself to get the wallet credential.

Dif:

Either now restrictions or subject_is_issuer set.

etschelp commented 1 year ago

AnonCreds

Answering a anoncred presentation request with self attested attributes only works if two conditions are met:

  1. the request has no restrictions
  2. the request uses the name key instead of names. As names always requires restrictions to be set, both options are mutual exclusive.

Example presentation request:

{
    "connection_id": "f7c80500-8e17-4c36-bae5-7177dedc080c",
    "proof_request": {
        "name": "test self attested attributes",
        "version": "0.1",
        "requested_attributes": {
            "some_iban": {
                "name": "iban",
                "restrictions": []
            }
        },
        "requested_predicates": {}
    }
}

Example response:

{
    "requested_attributes": {},
    "requested_predicates": {},
    "self_attested_attributes": {
        "some_iban": "1234"
    }
}

The proof template only works with names and hence has at least a restriction on the schema. So creating a template that supports self attested attributes requires reworking the proof template as well. Answering a presentation request that matches above conditions only requires minimal changes in the front and backend.

etschelp commented 1 year ago

As discussed there are three places that need to be refactored here:

  1. Proof Template. Two possible ways here: a. explicit, add a switch "allow self attested", and if true hide all restrictions and predicates. Backend uses a different render path in that case. b. implicit, if there are no predicates or restrictions render the template so that it allows self attestation e.g. name instead of names for all respective groups - this is more difficult as it requires more adjustments to the template renderer.
  2. Loading of matching credentials. Todo's:
    • Unify display of labels, probably in that order: schema-name, credential-label, default-attribute.
    • "Paging" when loading the matches
  3. Send the presentation needs more information in the request class, probably something that maps attribute group name to referent or self attestation.

Json request:

{
  "group0_match_from_wallet": {
    "referent": "3b2f38db-6a6f-4188-96a2-b56909a1a16d",
  },
  "group1_self_attested": {
    "selfAttestedValue": "something"
  }  
}

Matching request class:

@Data
@Introspected
@NoArgsConstructor
public class SendPresentationRequest {

    @NotEmpty
    private Map<String, SelectedReferent> selectedReferents;

    public Map<UUID, Boolean> findReferents() {
        return selectedReferents.values().stream()
                .filter(Objects::nonNull)
                .map(ref -> Map.entry(ref.getReferent(), ref.getRevealed()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    public Map<String, String> findSelfAttested() {
        return selectedReferents.entrySet().stream()
                .filter(e -> e.getValue().getReferent() == null)
                .filter(e -> StringUtils.isNotEmpty(e.getValue().getSelfAttestedValue()))
                .map(e -> Map.entry(e.getKey(), e.getValue().getSelfAttestedValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    @Data
    @NoArgsConstructor
    public static class SelectedReferent {
        private UUID referent;
        private Boolean revealed;
        private String selfAttestedValue;
    }

Plug it into the helper:

SendPresentationRequestHelper.acceptAll(presentationRequest, approve.findReferents(), approve.findSelfAttested());
etschelp commented 1 year ago

Current state of implementation: