Documentation
¶
Index ¶
- Constants
- Variables
- type Constraints
- type Field
- type Filter
- type Format
- type Holder
- type InputDescriptor
- type InputDescriptorMapping
- type JwtType
- type LdpType
- type MatchOption
- type MatchOptions
- type MatchedInputDescriptor
- type MatchedSubmissionRequirement
- type Preference
- type PresentationDefinition
- func (pd *PresentationDefinition) CreateVP(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, ...) (*verifiable.Presentation, error)
- func (pd *PresentationDefinition) Match(vp *verifiable.Presentation, contextLoader ld.DocumentLoader, ...) (map[string]*verifiable.Credential, error)
- func (pd *PresentationDefinition) MatchSubmissionRequirement(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, ...) ([]*MatchedSubmissionRequirement, error)
- func (pd *PresentationDefinition) ValidateSchema() error
- type PresentationSubmission
- type Schema
- type Selection
- type StrOrInt
- type SubmissionRequirement
Examples ¶
- PresentationDefinition.CreateVP (MultipleMatches)
- PresentationDefinition.CreateVP (MultipleMatchesDisclosure)
- PresentationDefinition.CreateVP (SubmissionRequirements)
- PresentationDefinition.CreateVP (SubmissionRequirementsLimitDisclosure)
- PresentationDefinition.CreateVP (V1)
- PresentationDefinition.CreateVP (V1_With_LDPVC_FormatAndProof)
- PresentationDefinition.CreateVP (V1_With_LDP_FormatAndProof)
- PresentationDefinition.CreateVP (V2)
- PresentationDefinition.CreateVP (WithFormatInInputDescriptor)
- PresentationDefinition.CreateVP (WithFrame)
- PresentationDefinition.CreateVP (With_LdpVC_Format)
- PresentationDefinition.CreateVP (With_Ldp_Format)
- PresentationDefinition.Match
Constants ¶
const ( // PresentationSubmissionJSONLDContextIRI is the JSONLD context of presentation submissions. PresentationSubmissionJSONLDContextIRI = "https://identity.foundation/presentation-exchange/submission/v1" // CredentialApplicationJSONLDContextIRI is the JSONLD context of credential application // which also contains presentation submission details. CredentialApplicationJSONLDContextIRI = "https://identity.foundation/credential-manifest/application/v1" // PresentationSubmissionJSONLDType is the JSONLD type of presentation submissions. PresentationSubmissionJSONLDType = "PresentationSubmission" // CredentialApplicationJSONLDType is the JSONLD type of credential application. CredentialApplicationJSONLDType = "CredentialApplication" )
const ( // All rule`s value. All Selection = "all" // Pick rule`s value. Pick Selection = "pick" // Required predicate`s value. Required Preference = "required" // Preferred predicate`s value. Preferred Preference = "preferred" // FormatJWT presentation exchange format. FormatJWT = "jwt" // FormatJWTVC presentation exchange format. FormatJWTVC = "jwt_vc" // FormatJWTVP presentation exchange format. FormatJWTVP = "jwt_vp" // FormatLDP presentation exchange format. FormatLDP = "ldp" // FormatLDPVC presentation exchange format. FormatLDPVC = "ldp_vc" // FormatLDPVP presentation exchange format. FormatLDPVP = "ldp_vp" )
const DefinitionJSONSchemaV1 = `` /* 13163-byte string literal not displayed */
DefinitionJSONSchemaV1 is the JSONSchema definition for PresentationDefinition. nolint:lll https://github.com/decentralized-identity/presentation-exchange/blob/9a6abc6d2b0f08b6339c9116132fa94c4c834418/test/presentation-definition/schema.json
const DefinitionJSONSchemaV2 = `` /* 7512-byte string literal not displayed */
DefinitionJSONSchemaV2 is the JSONSchema definition for PresentationDefinition. nolint:lll
Variables ¶
var ErrNoCredentials = errors.New("credentials do not satisfy requirements")
ErrNoCredentials when any credentials do not satisfy requirements.
Functions ¶
This section is empty.
Types ¶
type Constraints ¶ added in v0.1.6
type Constraints struct {
LimitDisclosure *Preference `json:"limit_disclosure,omitempty"`
SubjectIsIssuer *Preference `json:"subject_is_issuer,omitempty"`
IsHolder []*Holder `json:"is_holder,omitempty"`
Fields []*Field `json:"fields,omitempty"`
}
Constraints describes InputDescriptor`s Constraints field.
type Field ¶ added in v0.1.6
type Field struct {
Path []string `json:"path,omitempty"`
ID string `json:"id,omitempty"`
Purpose string `json:"purpose,omitempty"`
Filter *Filter `json:"filter,omitempty"`
Predicate *Preference `json:"predicate,omitempty"`
IntentToRetain bool `json:"intent_to_retain,omitempty"`
}
Field describes Constraints`s Fields field.
type Filter ¶ added in v0.1.6
type Filter struct {
Type *string `json:"type,omitempty"`
Format string `json:"format,omitempty"`
Pattern string `json:"pattern,omitempty"`
Minimum StrOrInt `json:"minimum,omitempty"`
Maximum StrOrInt `json:"maximum,omitempty"`
MinLength int `json:"minLength,omitempty"`
MaxLength int `json:"maxLength,omitempty"`
ExclusiveMinimum StrOrInt `json:"exclusiveMinimum,omitempty"`
ExclusiveMaximum StrOrInt `json:"exclusiveMaximum,omitempty"`
Const StrOrInt `json:"const,omitempty"`
Enum []StrOrInt `json:"enum,omitempty"`
Not map[string]interface{} `json:"not,omitempty"`
Contains map[string]interface{} `json:"contains,omitempty"`
}
Filter describes filter.
type Format ¶ added in v0.1.6
type Format struct {
Jwt *JwtType `json:"jwt,omitempty"`
JwtVC *JwtType `json:"jwt_vc,omitempty"`
JwtVP *JwtType `json:"jwt_vp,omitempty"`
Ldp *LdpType `json:"ldp,omitempty"`
LdpVC *LdpType `json:"ldp_vc,omitempty"`
LdpVP *LdpType `json:"ldp_vp,omitempty"`
}
Format describes PresentationDefinition`s Format field.
type Holder ¶ added in v0.1.6
type Holder struct {
FieldID []string `json:"field_id,omitempty"`
Directive *Preference `json:"directive,omitempty"`
}
Holder describes Constraints`s holder object.
type InputDescriptor ¶
type InputDescriptor struct {
ID string `json:"id,omitempty"`
Group []string `json:"group,omitempty"`
Name string `json:"name,omitempty"`
Purpose string `json:"purpose,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
Schema []*Schema `json:"schema,omitempty"`
Constraints *Constraints `json:"constraints,omitempty"`
Format *Format `json:"format,omitempty"`
}
InputDescriptor input descriptors.
type InputDescriptorMapping ¶
type InputDescriptorMapping struct {
ID string `json:"id,omitempty"`
Format string `json:"format,omitempty"`
Path string `json:"path,omitempty"`
PathNested *InputDescriptorMapping `json:"path_nested,omitempty"`
}
InputDescriptorMapping maps an InputDescriptor to a verifiable credential pointed to by the JSONPath in `Path`.
type JwtType ¶ added in v0.1.6
type JwtType struct {
Alg []string `json:"alg,omitempty"`
}
JwtType contains alg.
type LdpType ¶ added in v0.1.6
type LdpType struct {
ProofType []string `json:"proof_type,omitempty"`
}
LdpType contains proof_type.
type MatchOption ¶
type MatchOption func(*MatchOptions)
MatchOption is an option that sets an option for when matching.
func WithCredentialOptions ¶ added in v0.1.7
func WithCredentialOptions(options ...verifiable.CredentialOpt) MatchOption
WithCredentialOptions used when parsing the embedded credentials.
func WithDisableSchemaValidation ¶ added in v0.1.9
func WithDisableSchemaValidation() MatchOption
WithDisableSchemaValidation used to disable schema validation.
type MatchOptions ¶
type MatchOptions struct {
CredentialOptions []verifiable.CredentialOpt
DisableSchemaValidation bool
}
MatchOptions is a holder of options that can set when matching a submission against definitions.
type MatchedInputDescriptor ¶ added in v0.1.9
type MatchedInputDescriptor struct {
ID string
Name string
Purpose string
MatchedVCs []*verifiable.Credential
}
MatchedInputDescriptor contains information about VCs that matched an input descriptor of presentation definition.
type MatchedSubmissionRequirement ¶ added in v0.1.9
type MatchedSubmissionRequirement struct {
Name string
Purpose string
Rule Selection
Count int
Min int
Max int
Descriptors []*MatchedInputDescriptor
Nested []*MatchedSubmissionRequirement
}
MatchedSubmissionRequirement contains information about VCs that matched a presentation definition.
type Preference ¶ added in v0.1.6
type Preference string
Preference can be "required" or "preferred".
type PresentationDefinition ¶ added in v0.1.6
type PresentationDefinition struct {
// ID unique resource identifier.
ID string `json:"id,omitempty"`
// Name human-friendly name that describes what the Presentation Definition pertains to.
Name string `json:"name,omitempty"`
// Purpose describes the purpose for which the Presentation Definition’s inputs are being requested.
Purpose string `json:"purpose,omitempty"`
Locale string `json:"locale,omitempty"`
// Format is an object with one or more properties matching the registered Claim Format Designations
// (jwt, jwt_vc, jwt_vp, etc.) to inform the Holder of the claim format configurations the Verifier can process.
Format *Format `json:"format,omitempty"`
// Frame is used for JSON-LD document framing.
Frame map[string]interface{} `json:"frame,omitempty"`
// SubmissionRequirements must conform to the Submission Requirement Format.
// If not present, all inputs listed in the InputDescriptors array are required for submission.
SubmissionRequirements []*SubmissionRequirement `json:"submission_requirements,omitempty"`
InputDescriptors []*InputDescriptor `json:"input_descriptors,omitempty"`
}
PresentationDefinition presentation definitions (https://identity.foundation/presentation-exchange/).
func (*PresentationDefinition) CreateVP ¶ added in v0.1.6
func (pd *PresentationDefinition) CreateVP(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, opts ...verifiable.CredentialOpt) (*verifiable.Presentation, error)
CreateVP creates verifiable presentation.
Example (MultipleMatches) ¶
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.age"},
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}, {
ID: "first_name_descriptor",
Purpose: "First name must be either Andrew or Jesse",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.first_name"},
Filter: &Filter{
Type: &strFilterType,
Pattern: "Andrew|Jesse",
},
}},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:777",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:777",
CustomFields: map[string]interface{}{
"first_name": "Andrew",
"last_name": "Hanks",
"age": 25,
},
},
{
ID: "http://example.edu/credentials/888",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:888",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:888",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": "did:example:777", "first_name": "Andrew", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": "did:example:888", "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "type": "VerifiableCredential" } ] }
Example (MultipleMatchesDisclosure) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.age"},
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}, {
ID: "first_name_descriptor",
Purpose: "First name must be either Andrew or Jesse",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{{
Path: []string{"$.first_name"},
Filter: &Filter{
Type: &strFilterType,
Pattern: "Andrew|Jesse",
},
}},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:777",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:777",
CustomFields: map[string]interface{}{
"first_name": "Andrew",
"last_name": "Hanks",
"age": 25,
},
},
{
ID: "http://example.edu/credentials/888",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:888",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:888",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[2]" } }, { "id": "first_name_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "first_name_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[3]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": "did:example:777", "first_name": "Andrew", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": "did:example:888", "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:777", "first_name": "Andrew", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:888", "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "type": "VerifiableCredential" } ] }
Example (SubmissionRequirements) ¶
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
SubmissionRequirements: []*SubmissionRequirement{
{
Rule: "all",
From: "A",
},
{
Rule: "pick",
Purpose: "We need your photo to identify you.",
Count: 1,
FromNested: []*SubmissionRequirement{
{
Rule: "all",
From: "drivers_license_image",
},
{
Rule: "all",
From: "passport_image",
},
},
},
},
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Group: []string{"A"},
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.age"},
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}, {
ID: "drivers_license_image_descriptor",
Group: []string{"drivers_license_image"},
Purpose: "We need your photo to identify you",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.photo"},
Filter: &Filter{
Type: &strFilterType,
Format: "uri",
},
}},
},
}, {
ID: "passport_image_descriptor",
Group: []string{"passport_image"},
Purpose: "We need your image to identify you",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.image"},
Filter: &Filter{
Type: &strFilterType,
Format: "uri",
},
}},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:777",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:777",
CustomFields: map[string]interface{}{
"first_name": "Andrew",
"last_name": "Hanks",
"image": "http://image.com/user777",
"age": 25,
},
},
{
ID: "http://example.edu/credentials/888",
Context: []string{"https://www.w3.org/2018/credentials/v1"},
Types: []string{"VerifiableCredential"},
Issuer: verifiable.Issuer{
ID: "did:example:888",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:888",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"photo": "http://image.com/user777",
"age": 21,
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "drivers_license_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "drivers_license_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "passport_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "passport_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": "did:example:777", "first_name": "Andrew", "id": "http://example.edu/credentials/777", "image": "http://image.com/user777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": "did:example:888", "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "photo": "http://image.com/user777", "type": "VerifiableCredential" } ] }
Example (SubmissionRequirementsLimitDisclosure) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
SubmissionRequirements: []*SubmissionRequirement{
{
Rule: "all",
From: "A",
},
{
Rule: "pick",
Purpose: "We need your photo to identify you",
Count: 1,
FromNested: []*SubmissionRequirement{
{
Rule: "all",
From: "drivers_license_image",
},
{
Rule: "all",
From: "passport_image",
},
},
},
},
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Group: []string{"A"},
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
Fields: []*Field{{
Path: []string{"$.age"},
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}, {
ID: "drivers_license_image_descriptor",
Group: []string{"drivers_license_image"},
Purpose: "We need your photo to identify you",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{{
Path: []string{"$.photo"},
Filter: &Filter{
Type: &strFilterType,
Format: "uri",
},
}},
},
}, {
ID: "passport_image_descriptor",
Group: []string{"passport_image"},
Purpose: "We need your image to identify you",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{{
Path: []string{"$.image"},
Filter: &Filter{
Type: &strFilterType,
Format: "uri",
},
}},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:777",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:777",
CustomFields: map[string]interface{}{
"first_name": "Andrew",
"last_name": "Hanks",
"image": "http://image.com/user777",
"age": 25,
},
},
{
ID: "http://example.edu/credentials/888",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:888",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:888",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"photo": "http://image.com/user777",
"age": 21,
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } }, { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[1]" } }, { "id": "drivers_license_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "drivers_license_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[2]" } }, { "id": "passport_image_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "passport_image_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[3]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 25, "credentialSubject": "did:example:777", "first_name": "Andrew", "id": "http://example.edu/credentials/777", "image": "http://image.com/user777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "last_name": "Hanks", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": 21, "credentialSubject": "did:example:888", "first_name": "Jesse", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "last_name": "Pinkman", "photo": "http://image.com/user777", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:888", "id": "http://example.edu/credentials/888", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:888", "photo": "http://image.com/user777", "type": "VerifiableCredential" }, { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": "did:example:777", "id": "http://example.edu/credentials/777", "image": "http://image.com/user777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:777", "type": "VerifiableCredential" } ] }
Example (V1) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{{
Path: []string{"$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": true, "credentialSubject": "did:example:76e12ec712ebc6f1c221ebfeb1f", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (V1_With_LDPVC_FormatAndProof) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{{
Path: []string{"$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}},
Format: &Format{
LdpVC: &LdpType{ProofType: []string{"JsonWebSignature2020"}},
},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vc", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": true, "credentialSubject": "did:example:76e12ec712ebc6f1c221ebfeb1f", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (V1_With_LDP_FormatAndProof) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Schema: []*Schema{{
URI: fmt.Sprintf("%s#%s", verifiable.ContextID, verifiable.VCType),
}},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{{
Path: []string{"$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
}},
},
}},
Format: &Format{
Ldp: &LdpType{ProofType: []string{"JsonWebSignature2020"}},
},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Subject: "did:example:76e12ec712ebc6f1c221ebfeb1f",
CustomFields: map[string]interface{}{
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
Proofs: []verifiable.Proof{{"type": "JsonWebSignature2020"}},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "age": true, "credentialSubject": "did:example:76e12ec712ebc6f1c221ebfeb1f", "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (V2) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{
{
Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
},
{
Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
Filter: &Filter{
Type: &strFilterType,
Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
},
},
},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Schemas: []verifiable.TypedID{{
ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
Type: "JsonSchemaValidator2018",
}},
Subject: map[string]interface{}{
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "first_name": "Jesse", "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "last_name": "Pinkman" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (WithFormatInInputDescriptor) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Format: &Format{
LdpVP: &LdpType{
ProofType: []string{"Ed25519Signature2018"},
},
},
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{
{
Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
},
{
Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
Filter: &Filter{
Type: &strFilterType,
Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
},
},
},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Schemas: []verifiable.TypedID{{
ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
Type: "JsonSchemaValidator2018",
}},
Subject: map[string]interface{}{
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
Proofs: []verifiable.Proof{
{"type": "Ed25519Signature2018"},
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "first_name": "Jesse", "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "last_name": "Pinkman" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (WithFrame) ¶
vcJSON := `
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/citizenship/v1",
"https://w3id.org/security/bbs/v1"
],
"id": "https://issuer.oidp.uscis.gov/credentials/83627465",
"type": [
"VerifiableCredential",
"PermanentResidentCard"
],
"issuer": "did:example:489398593",
"identifier": "83627465",
"name": "Permanent Resident Card",
"description": "Government of Example Permanent Resident Card.",
"issuanceDate": "2019-12-03T12:19:52Z",
"expirationDate": "2029-12-03T12:19:52Z",
"credentialSubject": {
"id": "did:example:b34ca6cd37bbf23",
"type": [
"PermanentResident",
"Person"
],
"givenName": "JOHN",
"familyName": "SMITH",
"gender": "Male",
"image": "data:image/png;base64,iVBORw0KGgokJggg==",
"residentSince": "2015-01-01",
"lprCategory": "C09",
"lprNumber": "999-999-999",
"commuterClassification": "C1",
"birthCountry": "Bahamas",
"birthDate": "1958-07-17"
}
}
`
frameJSONWithMissingIssuer := `
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/citizenship/v1",
"https://w3id.org/security/bbs/v1"
],
"type": ["VerifiableCredential", "PermanentResidentCard"],
"@explicit": true,
"identifier": {},
"issuer": {},
"issuanceDate": {},
"credentialSubject": {
"@explicit": true,
"type": ["PermanentResident", "Person"],
"givenName": {},
"familyName": {},
"gender": {},
"birthCountry": {}
}
}
`
frameDoc, err := jsonutil.ToMap(frameJSONWithMissingIssuer)
if err != nil {
panic(err)
}
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Frame: frameDoc,
InputDescriptors: []*InputDescriptor{{
ID: "country_descriptor",
Constraints: &Constraints{
Fields: []*Field{
{
Path: []string{"$.credentialSubject.birthCountry", "$.vc.credentialSubject.birthCountry"},
Predicate: &required,
Filter: &Filter{
Type: &strFilterType,
Const: "Bahamas",
},
},
},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vc, err := verifiable.ParseCredential([]byte(vcJSON), verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
pubKey, privKey, err := bbs12381g2pub.GenerateKeyPair(sha256.New, nil)
if err != nil {
panic(err)
}
pubKeyBytes, err := pubKey.Marshal()
if err != nil {
panic(err)
}
signVCWithBBS(privKey, vc, loader)
vp, err := pd.CreateVP([]*verifiable.Credential{vc}, loader, verifiable.WithJSONLDDocumentLoader(loader), verifiable.WithPublicKeyFetcher(
verifiable.SingleKey(pubKeyBytes, "Bls12381G2Key2020")))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vp.Credentials()[0].(*verifiable.Credential).Proofs[0]["created"] = dummy
vp.Credentials()[0].(*verifiable.Credential).Proofs[0]["proofValue"] = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "country_descriptor", "format": "ldp_vp", "path": "$", "path_nested": { "id": "country_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://w3id.org/citizenship/v1", "https://w3id.org/security/bbs/v1" ], "credentialSubject": { "birthCountry": true, "familyName": "SMITH", "gender": "Male", "givenName": "JOHN", "id": "did:example:b34ca6cd37bbf23", "type": [ "Person", "PermanentResident" ] }, "id": "https://issuer.oidp.uscis.gov/credentials/83627465", "identifier": "83627465", "issuanceDate": "2019-12-03T12:19:52Z", "issuer": "did:example:489398593", "proof": { "created": "DUMMY", "nonce": "", "proofPurpose": "assertionMethod", "proofValue": "DUMMY", "type": "BbsBlsSignatureProof2020", "verificationMethod": "did:example:123456#key1" }, "type": [ "PermanentResidentCard", "VerifiableCredential" ] } ] }
Example (With_LdpVC_Format) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
Format: &Format{
LdpVC: &LdpType{
ProofType: []string{"Ed25519Signature2018"},
},
},
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{
{
Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
},
{
Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
Filter: &Filter{
Type: &strFilterType,
Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
},
},
},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Schemas: []verifiable.TypedID{{
ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
Type: "JsonSchemaValidator2018",
}},
Subject: map[string]interface{}{
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
Proofs: []verifiable.Proof{
{"type": "Ed25519Signature2018"},
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp_vc", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "first_name": "Jesse", "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "last_name": "Pinkman" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
Example (With_Ldp_Format) ¶
required := Required
pd := &PresentationDefinition{
ID: "c1b88ce1-8460-4baf-8f16-4759a2f055fd",
Purpose: "To sell you a drink we need to know that you are an adult.",
Format: &Format{
Ldp: &LdpType{
ProofType: []string{"Ed25519Signature2018"},
},
},
InputDescriptors: []*InputDescriptor{{
ID: "age_descriptor",
Purpose: "Your age should be greater or equal to 18.",
Constraints: &Constraints{
LimitDisclosure: &required,
Fields: []*Field{
{
Path: []string{"$.credentialSubject.age", "$.vc.credentialSubject.age", "$.age"},
Predicate: &required,
Filter: &Filter{
Type: &intFilterType,
Minimum: 18,
},
},
{
Path: []string{"$.credentialSchema[0].id", "$.credentialSchema.id", "$.vc.credentialSchema.id"},
Filter: &Filter{
Type: &strFilterType,
Const: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
},
},
},
},
}},
}
loader, err := ldtestutil.DocumentLoader()
if err != nil {
panic(err)
}
vp, err := pd.CreateVP([]*verifiable.Credential{
{
ID: "http://example.edu/credentials/777",
Context: []string{verifiable.ContextURI},
Types: []string{verifiable.VCType},
Issuer: verifiable.Issuer{
ID: "did:example:76e12ec712ebc6f1c221ebfeb1f",
},
Issued: &util.TimeWrapper{
Time: time.Time{},
},
Schemas: []verifiable.TypedID{{
ID: "hub://did:foo:123/Collections/schema.us.gov/passport.json",
Type: "JsonSchemaValidator2018",
}},
Subject: map[string]interface{}{
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
"first_name": "Jesse",
"last_name": "Pinkman",
"age": 21,
},
Proofs: []verifiable.Proof{
{"type": "Ed25519Signature2018"},
},
},
}, loader, verifiable.WithJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
vp.CustomFields["presentation_submission"].(*PresentationSubmission).ID = dummy
vpBytes, err := json.MarshalIndent(vp, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(vpBytes))
Output: { "@context": [ "https://www.w3.org/2018/credentials/v1", "https://identity.foundation/presentation-exchange/submission/v1" ], "presentation_submission": { "id": "DUMMY", "definition_id": "c1b88ce1-8460-4baf-8f16-4759a2f055fd", "descriptor_map": [ { "id": "age_descriptor", "format": "ldp", "path": "$", "path_nested": { "id": "age_descriptor", "format": "ldp_vc", "path": "$.verifiableCredential[0]" } } ] }, "type": [ "VerifiablePresentation", "PresentationSubmission" ], "verifiableCredential": [ { "@context": [ "https://www.w3.org/2018/credentials/v1" ], "credentialSubject": { "age": true, "first_name": "Jesse", "id": "did:example:ebfeb1f712ebc6f1c276e12ec21", "last_name": "Pinkman" }, "id": "http://example.edu/credentials/777", "issuanceDate": "0001-01-01T00:00:00Z", "issuer": "did:example:76e12ec712ebc6f1c221ebfeb1f", "type": "VerifiableCredential" } ] }
func (*PresentationDefinition) Match ¶ added in v0.1.6
func (pd *PresentationDefinition) Match(vp *verifiable.Presentation, contextLoader ld.DocumentLoader, options ...MatchOption) (map[string]*verifiable.Credential, error)
Match returns the credentials matched against the InputDescriptors ids.
Example ¶
Example of a Verifier verifying the presentation submission of a Holder.
// verifier sends their presentation definitions to the holder
verifierDefinitions := &PresentationDefinition{
InputDescriptors: []*InputDescriptor{
{
ID: "banking",
Schema: []*Schema{{
URI: "https://example.org/examples#Customer",
}},
},
{
ID: "residence",
Schema: []*Schema{{
URI: "https://example.org/examples#Street",
}},
},
},
}
// holder fetches their credentials
accountCredential := fetchVC([]string{"https://example.context.jsonld/account"}, []string{"Customer"})
addressCredential := fetchVC([]string{"https://example.context.jsonld/address"}, []string{"Street"})
// holder builds their presentation submission against the verifier's definitions
vp, err := newPresentationSubmission(
&PresentationSubmission{DescriptorMap: []*InputDescriptorMapping{
{
ID: "banking",
Path: "$.verifiableCredential[0]",
},
{
ID: "residence",
Path: "$.verifiableCredential[1]",
},
}},
accountCredential, addressCredential,
)
if err != nil {
panic(err)
}
// holder sends VP over the wire to the verifier
vpBytes, err := json.Marshal(vp)
if err != nil {
panic(err)
}
// load json-ld context
loader, err := ldtestutil.DocumentLoader(
ldcontext.Document{
URL: "https://example.context.jsonld/account",
Content: []byte(exampleJSONLDContext),
},
ldcontext.Document{
URL: "https://example.context.jsonld/address",
Content: []byte(exampleJSONLDContext),
},
)
if err != nil {
panic(err)
}
// verifier parses the vp
// note: parsing this VP without verifying the proof just for example purposes.
// Always verify proofs in production!
receivedVP, err := verifiable.ParsePresentation(vpBytes,
verifiable.WithPresDisabledProofCheck(),
verifiable.WithPresJSONLDDocumentLoader(loader))
if err != nil {
panic(err)
}
// verifier matches the received VP against their definitions
matched, err := verifierDefinitions.Match(
receivedVP, loader,
WithCredentialOptions(verifiable.WithJSONLDDocumentLoader(loader)),
)
if err != nil {
panic(fmt.Errorf("presentation submission did not match definitions: %w", err))
}
for _, descriptor := range verifierDefinitions.InputDescriptors {
receivedCred := matched[descriptor.ID]
fmt.Printf(
"verifier received the '%s' credential for the input descriptor id '%s'\n",
receivedCred.Context[1], descriptor.ID)
}
Output: verifier received the 'https://example.context.jsonld/account' credential for the input descriptor id 'banking' verifier received the 'https://example.context.jsonld/address' credential for the input descriptor id 'residence'
func (*PresentationDefinition) MatchSubmissionRequirement ¶ added in v0.1.9
func (pd *PresentationDefinition) MatchSubmissionRequirement(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, opts ...verifiable.CredentialOpt) ([]*MatchedSubmissionRequirement, error)
MatchSubmissionRequirement return information about matching VCs.
func (*PresentationDefinition) ValidateSchema ¶ added in v0.1.6
func (pd *PresentationDefinition) ValidateSchema() error
ValidateSchema validates presentation definition.
type PresentationSubmission ¶
type PresentationSubmission struct {
// ID unique resource identifier.
ID string `json:"id,omitempty"`
Locale string `json:"locale,omitempty"`
// DefinitionID links the submission to its definition and must be the id value of a valid Presentation Definition.
DefinitionID string `json:"definition_id,omitempty"`
DescriptorMap []*InputDescriptorMapping `json:"descriptor_map"`
}
PresentationSubmission is the container for the descriptor_map: https://identity.foundation/presentation-exchange/#presentation-submission.
type StrOrInt ¶ added in v0.1.6
type StrOrInt interface{}
StrOrInt type that defines string or integer.
type SubmissionRequirement ¶ added in v0.1.6
type SubmissionRequirement struct {
Name string `json:"name,omitempty"`
Purpose string `json:"purpose,omitempty"`
Rule Selection `json:"rule,omitempty"`
Count int `json:"count,omitempty"`
Min int `json:"min,omitempty"`
Max int `json:"max,omitempty"`
From string `json:"from,omitempty"`
FromNested []*SubmissionRequirement `json:"from_nested,omitempty"`
}
SubmissionRequirement describes input that must be submitted via a Presentation Submission to satisfy Verifier demands.