issuecredential

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: May 2, 2023 License: Apache-2.0 Imports: 6 Imported by: 15

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.AcceptProposalV2(piid, &OfferCredentialV2{})
        // 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.AcceptOfferV2(piid)
        // If Holder wants to counter an offer they received with a proposal.
        client.NegotiateProposalV2(piid, &ProposeCredentialV2{})
        // 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.AcceptRequestV2(piid, &IssueCredentialV2{})
        // 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.SendOfferV2(&OfferCredentialV2{}, 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.SendProposalV2(&ProposeCredentialV2{}, myDID, theirDID)
  2. Holder can begin with a request. client.SendRequestV2(&RequestCredentialV2{}, 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 added in v0.1.5

func WithRequestCredential(msg *RequestCredential) issuecredential.Opt

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

Types

type AcceptCredentialOptions added in v0.1.8

type AcceptCredentialOptions func(opts *acceptCredentialOpts)

AcceptCredentialOptions is custom option for accepting credential in holder.

func AcceptByFriendlyNames added in v0.1.8

func AcceptByFriendlyNames(names ...string) AcceptCredentialOptions

AcceptByFriendlyNames option to provide optional friendly names for accepting credentials.

func AcceptBySkippingStorage added in v0.1.8

func AcceptBySkippingStorage() AcceptCredentialOptions

AcceptBySkippingStorage skips storing incoming credential to storage.

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, options ...AcceptCredentialOptions) 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, msg *RequestCredential) error

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

func (*Client) AcceptProblemReport added in v0.1.4

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, options ...IssuerDeclineOptions) 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, options ...IssuerDeclineOptions) 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, conn *connection.Record) (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), &RequestCredential{})
		}

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

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

_, err = clientAlice.SendOffer(&OfferCredential{}, &connection.Record{MyDID: Alice, TheirDID: 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, conn *connection.Record) (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.ProposeCredentialMsgTypeV2 {
			acceptErr = clientAlice.AcceptProposal(piid, &OfferCredential{})
		}

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

		if e.Message.Type() == issuecredential.OfferCredentialMsgTypeV2 {
			acceptErr = clientBob.AcceptOffer(piid, &RequestCredential{})
		}

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

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

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

_, err = clientBob.SendProposal(&ProposeCredential{}, &connection.Record{MyDID: Bob, TheirDID: 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, conn *connection.Record) (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{}, &connection.Record{MyDID: Bob, TheirDID: 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.IssueCredentialParams

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

type IssueCredentialV2 added in v0.1.8

type IssueCredentialV2 issuecredential.IssueCredentialV2 //nolint: golint

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

type IssueCredentialV3 added in v0.1.8

type IssueCredentialV3 issuecredential.IssueCredentialV3 //nolint: golint

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

type IssuerDeclineOptions added in v0.1.8

type IssuerDeclineOptions func(opts *redirectOpts)

IssuerDeclineOptions is custom option for sending web redirect options to holder. https://github.com/hyperledger/aries-rfcs/tree/main/concepts/0700-oob-through-redirect

func RequestRedirect added in v0.1.8

func RequestRedirect(url string) IssuerDeclineOptions

RequestRedirect option to provide optional redirect URL requesting holder to redirect.

type OfferCredential

type OfferCredential = issuecredential.OfferCredentialParams

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 OfferCredentialV2 added in v0.1.8

type OfferCredentialV2 issuecredential.OfferCredentialV2

OfferCredentialV2 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 OfferCredentialV3 added in v0.1.8

type OfferCredentialV3 issuecredential.OfferCredentialV3

OfferCredentialV3 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.ProposeCredentialParams

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 ProposeCredentialV2 added in v0.1.8

type ProposeCredentialV2 issuecredential.ProposeCredentialV2

ProposeCredentialV2 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 ProposeCredentialV3 added in v0.1.8

type ProposeCredentialV3 issuecredential.ProposeCredentialV3

ProposeCredentialV3 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, opt ...issuecredential.Opt) 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.RequestCredentialParams

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.

type RequestCredentialV2 added in v0.1.8

type RequestCredentialV2 issuecredential.RequestCredentialV2

RequestCredentialV2 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.

type RequestCredentialV3 added in v0.1.8

type RequestCredentialV3 issuecredential.RequestCredentialV3

RequestCredentialV3 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.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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