Documentation ¶
Overview ¶
Package holder enables the Holder: an entity that receives SD-JWTs from the Issuer and has control over them.
Index ¶
- func CreateHolderVerification(info *BindingInfo) (string, error)
- func CreatePresentation(combinedFormatForIssuance string, claimsToDisclose []string, opts ...Option) (string, error)
- type BindingInfo
- type BindingPayload
- type Claim
- type NoopSignatureVerifier
- type Option
- type ParseOpt
- func WithExpectedTypHeader(typ string) ParseOpt
- func WithIssuerSigningAlgorithms(algorithms []string) ParseOpt
- func WithJWTDetachedPayload(payload []byte) ParseOpt
- func WithLeewayForClaimsValidation(duration time.Duration) ParseOpt
- func WithSDJWTV5Validation(flag bool) ParseOpt
- func WithSignatureVerifier(signatureVerifier afgjwt.ProofChecker) ParseOpt
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateHolderVerification ¶
func CreateHolderVerification(info *BindingInfo) (string, error)
CreateHolderVerification will create holder verification from binding info.
func CreatePresentation ¶
func CreatePresentation(combinedFormatForIssuance string, claimsToDisclose []string, opts ...Option) (string, error)
CreatePresentation is a convenience method to assemble combined format for presentation using selected disclosures (claimsToDisclose) and optional holder verification. This call assumes that combinedFormatForIssuance has already been parsed and verified using Parse() function.
For presentation to a Verifier, the Holder MUST perform the following (or equivalent) steps:
- Decide which Disclosures to release to the Verifier, obtaining proper End-User consent if necessary.
- If Holder Binding is required, create a Holder Binding JWT.
- Create the Combined Format for Presentation from selected Disclosures and Holder Verification JWT(if applicable).
- Send the Presentation to the Verifier.
Example ¶
signer, signatureVerifier, err := setUp() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } holderSigner, holderJWK, err := setUpHolderBinding() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } claims := map[string]interface{}{ "given_name": "Albert", "last_name": "Smith", } // Issuer will issue SD-JWT for specified claims and holder public key. token, err := issuer.New(testIssuer, claims, nil, signer, issuer.WithHolderPublicKey(holderJWK)) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } combinedFormatForIssuance, err := token.Serialize(false) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } // Holder will parse combined format for issuance and hold on to that // combined format for issuance and the claims that can be selected. holderClaims, err := Parse(combinedFormatForIssuance, WithSignatureVerifier(signatureVerifier)) if err != nil { fmt.Println("holder failed to parse SD-JWT: %w", err.Error()) } // The Holder will only select given_name selectedDisclosures := getDisclosuresFromClaimNames([]string{"given_name"}, holderClaims) // Holder will disclose only sub-set of claims to verifier and create holder binding for the verifier. combinedFormatForPresentation, err := CreatePresentation(combinedFormatForIssuance, selectedDisclosures, WithHolderVerification(&BindingInfo{ Payload: BindingPayload{ Nonce: "nonce", Audience: "https://test.com/verifier", IssuedAt: jwt.NewNumericDate(time.Now()), }, Signer: holderSigner, })) if err != nil { fmt.Println("holder failed to create presentation: %w", err.Error()) } cfp := common.ParseCombinedFormatForPresentation(combinedFormatForPresentation) fmt.Println(cfp.HolderVerification != "")
Output: true
Types ¶
type BindingInfo ¶
type BindingInfo struct { Payload BindingPayload Signer jose.Signer Headers jose.Headers }
BindingInfo defines holder verification payload and signer.
type BindingPayload ¶
type BindingPayload struct { Nonce string `json:"nonce,omitempty"` Audience string `json:"aud,omitempty"` IssuedAt *jwt.NumericDate `json:"iat,omitempty"` }
BindingPayload represents holder verification payload.
type Claim ¶
Claim defines claim.
func Parse ¶
Parse parses issuer SD-JWT and returns claims that can be selected. The Holder MUST perform the following (or equivalent) steps when receiving a Combined Format for Issuance:
Separate the SD-JWT and the Disclosures in the Combined Format for Issuance.
Hash all the Disclosures separately.
Find the places in the SD-JWT where the digests of the Disclosures are included.
If any of the digests cannot be found in the SD-JWT, the Holder MUST reject the SD-JWT.
Decode Disclosures and obtain plaintext of the claim values.
It is up to the Holder how to maintain the mapping between the Disclosures and the plaintext claim values to be able to display them to the End-User when needed.
Example ¶
signer, signatureVerifier, err := setUp() if err != nil { fmt.Println("failed to set-up test: %w", err.Error()) } claims := map[string]interface{}{ "given_name": "Albert", "last_name": "Smith", } // Issuer will issue SD-JWT for specified claims. Salt function is only provided to keep example outcome the same. token, err := issuer.New(testIssuer, claims, nil, signer, issuer.WithSaltFnc(func() (string, error) { return "3jqcb67z9wks08zwiK7EyQ", nil })) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } combinedFormatForIssuance, err := token.Serialize(false) if err != nil { fmt.Println("failed to issue SD-JWT: %w", err.Error()) } // Holder will parse combined format for issuance and hold on to that // combined format for issuance and the claims that can be selected. holderClaims, err := Parse(combinedFormatForIssuance, WithSignatureVerifier(signatureVerifier)) if err != nil { fmt.Println("holder failed to parse SD-JWT: %w", err.Error()) } // Sort by claim name, keeping original order or equal elements. sort.SliceStable(holderClaims, func(i, j int) bool { return holderClaims[i].Name < holderClaims[j].Name }) holderClaimsJSON, err := marshalObj(holderClaims) if err != nil { fmt.Println("verifier failed to marshal holder claims: %w", err.Error()) } fmt.Println(holderClaimsJSON)
Output: [ { "Disclosure": "WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwiZ2l2ZW5fbmFtZSIsIkFsYmVydCJd", "Name": "given_name", "Value": "Albert" }, { "Disclosure": "WyIzanFjYjY3ejl3a3MwOHp3aUs3RXlRIiwibGFzdF9uYW1lIiwiU21pdGgiXQ", "Name": "last_name", "Value": "Smith" } ]
type NoopSignatureVerifier ¶
type NoopSignatureVerifier struct { }
NoopSignatureVerifier is no-op signature verifier (signature will not get checked).
func (*NoopSignatureVerifier) CheckJWTProof ¶
func (sv *NoopSignatureVerifier) CheckJWTProof(joseHeaders jose.Headers, expectedProofIssuer string, signingInput, signature []byte) error
CheckJWTProof implements signature verification.
type Option ¶
type Option func(opts *options)
Option is a holder option.
func WithHolderBinding ¶
func WithHolderBinding(info *BindingInfo) Option
WithHolderBinding option to set optional holder binding. Deprecated. Use WithHolderVerification instead.
func WithHolderVerification ¶
func WithHolderVerification(info *BindingInfo) Option
WithHolderVerification option to set optional holder verification.
type ParseOpt ¶
type ParseOpt func(opts *parseOpts)
ParseOpt is the SD-JWT Parser option.
func WithExpectedTypHeader ¶
WithExpectedTypHeader is an option for JWT typ header validation. Might be relevant for SDJWT V5 VC validation. Spec: https://vcstuff.github.io/draft-terbu-sd-jwt-vc/draft-terbu-oauth-sd-jwt-vc.html#name-header-parameters
func WithIssuerSigningAlgorithms ¶
WithIssuerSigningAlgorithms option is for defining secure signing algorithms (for holder verification).
func WithJWTDetachedPayload ¶
WithJWTDetachedPayload option is for definition of JWT detached payload.
func WithLeewayForClaimsValidation ¶
WithLeewayForClaimsValidation is an option for claims time(s) validation.
func WithSDJWTV5Validation ¶
WithSDJWTV5Validation option is for defining additional holder verification defined in SDJWT V5 spec. Section: https://www.ietf.org/archive/id/draft-ietf-oauth-selective-disclosure-jwt-05.html#section-6.1-3
func WithSignatureVerifier ¶
func WithSignatureVerifier(signatureVerifier afgjwt.ProofChecker) ParseOpt
WithSignatureVerifier option is for definition of JWT detached payload.