issuecredential

package
v0.1.6-0...-5c25bcb Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2021 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package issuecredential provides support for the Issue Credential Protocol 2.0: https://github.com/hyperledger/aries-rfcs/blob/master/features/0453-issue-credential-v2/README.md.

Formalizes messages used to issue a credential. The protocol is responsible for orchestrating the message flow according to the RFC.

1. Create your client:

client, err := issuecredential.New(ctx)
if err != nil {
 panic(err)
}

2. Register an action event channel.

actions := make(chan service.DIDCommAction)
client.RegisterActionEvent(actions)

3. Handle incoming actions.

for {
  select {
    case event := <-actions:
      piid := e.Properties.All()["piid"].(string)

      if event.Message.Type() == presentproof.ProposeCredentialMsgType {
        // If Issuer is willing to accept the proposal.
        client.AcceptProposal(piid, &OfferCredential{})
        // If Issuer is not willing to accept the proposal.
        client.DeclineProposal(piid, reason)
      }

      if event.Message.Type() == presentproof.OfferCredentialMsgType {
        // If Holder is willing to accept the offer.
        client.AcceptOffer(piid)
        // If Holder wants to counter an offer they received with a proposal.
        client.NegotiateProposal(piid, &ProposeCredential{})
        // If Holder is not willing to accept the offer.
        client.DeclineOffer(piid, reason)
      }

      if event.Message.Type() == presentproof.RequestCredentialMsgType {
        // If Issuer is willing to accept the request.
        client.AcceptRequest(piid, &IssueCredential{})
        // If Issuer is not willing to accept the request.
        client.DeclineRequest(piid, reason)
      }
      if event.Message.Type() == presentproof.IssueCredentialMsgType {
        // If Holder is willing to accept the credentials.
        client.AcceptCredential(piid, names)
        // If Holder is not willing to accept the credentials.
        client.DeclineCredential(piid, reason)
      }

      if event.Message.Type() == presentproof.ProblemReportMsgType {
        // Problem report message is triggered to notify client about the error.
        // In that case, there is only one option - accept it.
        client.AcceptProblemReport(piid)
      }
  }
}

How to initiate the protocol? The protocol can be initiated by the Issuer or by the Holder. Issuer initiates the protocol.

client.SendOffer(&OfferCredential{}, myDID, theirDID)

Holder initiates the protocol. There are two options of how to initiate the protocol.

  1. The Holder can begin with a proposal. client.SendProposal(&ProposeCredential{}, myDID, theirDID)
  2. Holder can begin with a request. client.SendRequest(&RequestCredential{}, myDID, theirDID)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func WithFriendlyNames

func WithFriendlyNames(names ...string) issuecredential.Opt

WithFriendlyNames allows providing names for the credentials. USAGE: This function should be used when the Holder receives IssueCredential message.

func WithIssueCredential

func WithIssueCredential(msg *IssueCredential) issuecredential.Opt

WithIssueCredential allows providing IssueCredential message USAGE: This message should be provided after receiving a RequestCredential message.

func WithOfferCredential

func WithOfferCredential(msg *OfferCredential) issuecredential.Opt

WithOfferCredential allows providing OfferCredential message USAGE: This message should be provided after receiving a ProposeCredential message.

func WithProposeCredential

func WithProposeCredential(msg *ProposeCredential) issuecredential.Opt

WithProposeCredential allows providing ProposeCredential message USAGE: This message should be provided after receiving an OfferCredential message.

func WithRequestCredential

func WithRequestCredential(msg *RequestCredential) issuecredential.Opt

WithRequestCredential allows providing RequestCredential message USAGE: This message should be provided after receiving an OfferCredential message.

Types

type Action

type Action issuecredential.Action

Action contains helpful information about action.

type Client

type Client struct {
	service.Event
	// contains filtered or unexported fields
}

Client enable access to issuecredential API.

func New

func New(ctx Provider) (*Client, error)

New return new instance of the issuecredential client.

func (*Client) AcceptCredential

func (c *Client) AcceptCredential(piID string, names ...string) error

AcceptCredential is used when the Holder is willing to accept the IssueCredential. NOTE: For async usage.

func (*Client) AcceptOffer

func (c *Client) AcceptOffer(piID string) error

AcceptOffer is used when the Holder is willing to accept the offer.

func (*Client) AcceptProblemReport

func (c *Client) AcceptProblemReport(piID string) error

AcceptProblemReport accepts problem report action.

func (*Client) AcceptProposal

func (c *Client) AcceptProposal(piID string, msg *OfferCredential) error

AcceptProposal is used when the Issuer is willing to accept the proposal. NOTE: For async usage.

func (*Client) AcceptRequest

func (c *Client) AcceptRequest(piID string, msg *IssueCredential) error

AcceptRequest is used when the Issuer is willing to accept the request. NOTE: For async usage.

func (*Client) Actions

func (c *Client) Actions() ([]Action, error)

Actions returns unfinished actions for the async usage.

func (*Client) DeclineCredential

func (c *Client) DeclineCredential(piID, reason string) error

DeclineCredential is used when the Holder does not want to accept the IssueCredential. NOTE: For async usage.

func (*Client) DeclineOffer

func (c *Client) DeclineOffer(piID, reason string) error

DeclineOffer is used when the Holder does not want to accept the offer. NOTE: For async usage.

func (*Client) DeclineProposal

func (c *Client) DeclineProposal(piID, reason string) error

DeclineProposal is used when the Issuer does not want to accept the proposal. NOTE: For async usage.

func (*Client) DeclineRequest

func (c *Client) DeclineRequest(piID, reason string) error

DeclineRequest is used when the Issuer does not want to accept the request. NOTE: For async usage.

func (*Client) NegotiateProposal

func (c *Client) NegotiateProposal(piID string, msg *ProposeCredential) error

NegotiateProposal is used when the Holder wants to negotiate about an offer he received. NOTE: For async usage. This function can be used only after receiving OfferCredential.

func (*Client) SendOffer

func (c *Client) SendOffer(offer *OfferCredential, myDID, theirDID string) (string, error)

SendOffer is used by the Issuer to send an offer.

Example
transport := map[string]chan payload{
	Alice: make(chan payload),
	Bob:   make(chan payload),
}

// Alice creates client
clientAlice, err := New(mockContext(Alice, transport))
if err != nil {
	panic(err)
}

// Alice registers channel for actions.
actionsAlice := make(chan service.DIDCommAction)

err = clientAlice.RegisterActionEvent(actionsAlice)
if err != nil {
	panic(err)
}

// Bob creates client.
clientBob, err := New(mockContext(Bob, transport))
if err != nil {
	panic(err)
}

// Bob registers channel for actions.
actionsBob := make(chan service.DIDCommAction)

err = clientBob.RegisterActionEvent(actionsBob)
if err != nil {
	panic(err)
}

go func() {
	for {
		var acceptErr error

		select {
		case e := <-actionsAlice:
			acceptErr = clientAlice.AcceptRequest(e.Properties.All()["piid"].(string), &IssueCredential{})
		case e := <-actionsBob:
			acceptErr = clientBob.AcceptOffer(e.Properties.All()["piid"].(string))
		}

		if acceptErr != nil {
			fmt.Println(acceptErr)
		}
	}
}()

// Alice.
waitForAlice := waitForFn(clientAlice)
// Bob.
waitForBob := waitForFn(clientBob)

_, err = clientAlice.SendOffer(&OfferCredential{}, Alice, Bob)
if err != nil {
	fmt.Println(err)
}

waitForAlice()
waitForBob()
Output:

Bob received https://didcomm.org/issue-credential/2.0/offer-credential from Alice
Alice received https://didcomm.org/issue-credential/2.0/request-credential from Bob
Bob received https://didcomm.org/issue-credential/2.0/issue-credential from Alice
Alice received https://didcomm.org/issue-credential/2.0/ack from Bob

func (*Client) SendProposal

func (c *Client) SendProposal(proposal *ProposeCredential, myDID, theirDID string) (string, error)

SendProposal is used by the Holder to send a proposal.

Example

nolint: gocyclo

transport := map[string]chan payload{
	Alice: make(chan payload),
	Bob:   make(chan payload),
}

// Alice creates client.
clientAlice, err := New(mockContext(Alice, transport))
if err != nil {
	panic(err)
}

// Alice registers channel for actions.
actionsAlice := make(chan service.DIDCommAction)

err = clientAlice.RegisterActionEvent(actionsAlice)
if err != nil {
	panic(err)
}

// Bob creates client.
clientBob, err := New(mockContext(Bob, transport))
if err != nil {
	panic(err)
}

// Bob registers channel for actions.
actionsBob := make(chan service.DIDCommAction)

err = clientBob.RegisterActionEvent(actionsBob)
if err != nil {
	panic(err)
}

go func() {
	for {
		var acceptErr error

		var e service.DIDCommAction

		select {
		case e = <-actionsAlice:
		case e = <-actionsBob:
		}

		piid, ok := e.Properties.All()["piid"].(string)
		if !ok {
			fmt.Println("empty piid")
		}

		if e.Message.Type() == issuecredential.ProposeCredentialMsgType {
			acceptErr = clientAlice.AcceptProposal(piid, &OfferCredential{})
		}

		if e.Message.Type() == issuecredential.RequestCredentialMsgType {
			acceptErr = clientAlice.AcceptRequest(piid, &IssueCredential{})
		}

		if e.Message.Type() == issuecredential.OfferCredentialMsgType {
			acceptErr = clientBob.AcceptOffer(piid)
		}

		if e.Message.Type() == issuecredential.IssueCredentialMsgType {
			acceptErr = clientBob.AcceptCredential(piid)
		}

		if acceptErr != nil {
			fmt.Println(acceptErr)
		}
	}
}()

// Alice.
waitForAlice := waitForFn(clientAlice)
// Bob.
waitForBob := waitForFn(clientBob)

_, err = clientBob.SendProposal(&ProposeCredential{}, Bob, Alice)
if err != nil {
	fmt.Println(err)
}

waitForAlice()
waitForBob()
Output:

Alice received https://didcomm.org/issue-credential/2.0/propose-credential from Bob
Bob received https://didcomm.org/issue-credential/2.0/offer-credential from Alice
Alice received https://didcomm.org/issue-credential/2.0/request-credential from Bob
Bob received https://didcomm.org/issue-credential/2.0/issue-credential from Alice
Alice received https://didcomm.org/issue-credential/2.0/ack from Bob

func (*Client) SendRequest

func (c *Client) SendRequest(request *RequestCredential, myDID, theirDID string) (string, error)

SendRequest is used by the Holder to send a request.

Example
transport := map[string]chan payload{
	Alice: make(chan payload),
	Bob:   make(chan payload),
}

// Alice creates client.
clientAlice, err := New(mockContext(Alice, transport))
if err != nil {
	panic(err)
}

// Alice registers channel for actions.
actionsAlice := make(chan service.DIDCommAction)

err = clientAlice.RegisterActionEvent(actionsAlice)
if err != nil {
	panic(err)
}

// Bob creates client.
clientBob, err := New(mockContext(Bob, transport))
if err != nil {
	panic(err)
}

// Bob registers channel for actions.
actionsBob := make(chan service.DIDCommAction)

err = clientBob.RegisterActionEvent(actionsBob)
if err != nil {
	panic(err)
}

go func() {
	for {
		var acceptErr error

		select {
		case e := <-actionsAlice:
			acceptErr = clientAlice.AcceptRequest(e.Properties.All()["piid"].(string), &IssueCredential{})
		case e := <-actionsBob:
			acceptErr = clientBob.AcceptCredential(e.Properties.All()["piid"].(string))
		}

		if acceptErr != nil {
			fmt.Println(acceptErr)
		}
	}
}()

// Alice.
waitForAlice := waitForFn(clientAlice)
// Bob.
waitForBob := waitForFn(clientBob)

_, err = clientBob.SendRequest(&RequestCredential{}, Bob, Alice)
if err != nil {
	fmt.Println(err)
}

waitForAlice()
waitForBob()
Output:

Alice received https://didcomm.org/issue-credential/2.0/request-credential from Bob
Bob received https://didcomm.org/issue-credential/2.0/issue-credential from Alice
Alice received https://didcomm.org/issue-credential/2.0/ack from Bob

type IssueCredential

type IssueCredential issuecredential.IssueCredential

IssueCredential contains as attached payload the credentials being issued and is sent in response to a valid Request Credential message.

type OfferCredential

type OfferCredential issuecredential.OfferCredential

OfferCredential is a message sent by the Issuer to the potential Holder, describing the credential they intend to offer and possibly the price they expect to be paid.

type ProposeCredential

type ProposeCredential issuecredential.ProposeCredential

ProposeCredential is an optional message sent by the potential Holder to the Issuer to initiate the protocol or in response to a offer-credential message when the Holder wants some adjustments made to the credential data offered by Issuer.

type ProtocolService

type ProtocolService interface {
	service.DIDComm
	Actions() ([]issuecredential.Action, error)
	ActionContinue(piID string, opt issuecredential.Opt) error
	ActionStop(piID string, err error) error
}

ProtocolService defines the issuecredential service.

type Provider

type Provider interface {
	Service(id string) (interface{}, error)
}

Provider contains dependencies for the issuecredential protocol and is typically created by using aries.Context().

type RequestCredential

type RequestCredential issuecredential.RequestCredential

RequestCredential is a message sent by the potential Holder to the Issuer, to request the issuance of a credential. Where circumstances do not require a preceding Offer Credential message (e.g., there is no cost to issuance that the Issuer needs to explain in advance, and there is no need for cryptographic negotiation), this message initiates the protocol.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL