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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 LdpType ¶
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 ¶
func WithCredentialOptions(options ...verifiable.CredentialOpt) MatchOption
WithCredentialOptions used when parsing the embedded credentials.
func WithDisableSchemaValidation ¶
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 ¶
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 ¶
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 PresentationDefinition ¶
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 ¶
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 ¶
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 ¶
func (pd *PresentationDefinition) MatchSubmissionRequirement(credentials []*verifiable.Credential, documentLoader ld.DocumentLoader, opts ...verifiable.CredentialOpt) ([]*MatchedSubmissionRequirement, error)
MatchSubmissionRequirement return information about matching VCs.
func (*PresentationDefinition) ValidateSchema ¶
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 SubmissionRequirement ¶
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.