From 88514cff32c33a4ba89f856e6d35547f874b0989 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Tue, 8 Aug 2023 14:31:47 +0200 Subject: [PATCH] feat: temp cred sdjwt Signed-off-by: Stas D --- pkg/doc/vc/crypto/crypto.go | 39 +++- pkg/doc/vc/sdjwt.go | 13 +- pkg/doc/vc/signer.go | 1 + pkg/profile/api.go | 25 ++- pkg/restapi/v1/issuer/controller.go | 17 +- .../issuecredential_service.go | 3 +- pkg/service/oidc4ci/api.go | 1 + pkg/service/oidc4ci/oidc4ci_service.go | 4 +- test/bdd/features/oidc4vc_api.feature | 73 +++---- test/bdd/fixtures/profile/profiles.json | 187 ++++++++++++++++++ 10 files changed, 305 insertions(+), 58 deletions(-) diff --git a/pkg/doc/vc/crypto/crypto.go b/pkg/doc/vc/crypto/crypto.go index a6bd553fa..74c93f122 100644 --- a/pkg/doc/vc/crypto/crypto.go +++ b/pkg/doc/vc/crypto/crypto.go @@ -7,11 +7,12 @@ SPDX-License-Identifier: Apache-2.0 package crypto import ( - "crypto" "fmt" "strings" "time" + "github.com/piprate/json-gold/ld" + "github.com/hyperledger/aries-framework-go/pkg/doc/did" "github.com/hyperledger/aries-framework-go/pkg/doc/signature/jsonld" ariessigner "github.com/hyperledger/aries-framework-go/pkg/doc/signature/signer" @@ -23,7 +24,6 @@ import ( "github.com/hyperledger/aries-framework-go/pkg/doc/signature/suite/jsonwebsignature2020" "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" - "github.com/piprate/json-gold/ld" "github.com/trustbloc/vcs/pkg/doc/vc" "github.com/trustbloc/vcs/pkg/doc/vc/jws" @@ -92,6 +92,7 @@ type signingOpts struct { Created *time.Time Challenge string Domain string + SDJWTTemplateData *vc.SelectiveDisclosureTemplate } // SigningOpts is signing credential option. @@ -104,6 +105,12 @@ func WithVerificationMethod(verificationMethod string) SigningOpts { } } +func WithSDJWTTemplateData(template *vc.SelectiveDisclosureTemplate) SigningOpts { + return func(opts *signingOpts) { + opts.SDJWTTemplateData = template + } +} + // WithPurpose is an option to pass proof purpose option for signing. func WithPurpose(purpose string) SigningOpts { return func(opts *signingOpts) { @@ -198,7 +205,9 @@ func (c *Crypto) signCredentialLDP( // signCredentialJWT returns vc in JWT format including the signature section. func (c *Crypto) signCredentialJWT( - signerData *vc.Signer, credential *verifiable.Credential, opts ...SigningOpts) (*verifiable.Credential, error) { + signerData *vc.Signer, + credential *verifiable.Credential, + opts ...SigningOpts) (*verifiable.Credential, error) { signOpts := &signingOpts{} // apply opts for _, opt := range opts { @@ -238,7 +247,21 @@ func (c *Crypto) signCredentialJWT( } if signerData.SDJWT.Enable { - return c.getSDJWTSignedCredential(credential, s, jwsAlgo, signerData.SDJWT.HashAlg, method) + options := []verifiable.MakeSDJWTOption{ + verifiable.MakeSDJWTWithHash(signerData.SDJWT.HashAlg), + } + + if signOpts.SDJWTTemplateData != nil { + options = append(options, + verifiable.MakeSDJWTWithVersion(signOpts.SDJWTTemplateData.Version), + verifiable.MakeSDJWTWithRecursiveClaimsObjects(signOpts.SDJWTTemplateData.RecursiveClaims), + verifiable.MakeSDJWTWithAlwaysIncludeObjects(signOpts.SDJWTTemplateData.AlwaysInclude), + verifiable.MakeSDJWTWithNonSelectivelyDisclosableClaims( + signOpts.SDJWTTemplateData.NonSelectivelyDisclosable), + ) + } + + return c.getSDJWTSignedCredential(credential, s, jwsAlgo, method, options...) } return c.getJWTSignedCredential(credential, s, jwsAlgo, method) @@ -268,8 +291,9 @@ func (c *Crypto) getSDJWTSignedCredential( credential *verifiable.Credential, signer vc.SignerAlgorithm, jwsAlgo verifiable.JWSAlgorithm, - digestHashAlgo crypto.Hash, - signingKeyID string) (*verifiable.Credential, error) { + signingKeyID string, + options ...verifiable.MakeSDJWTOption, +) (*verifiable.Credential, error) { jwsAlgName, err := jwsAlgo.Name() if err != nil { return nil, fmt.Errorf("getting JWS algo name error: %w", err) @@ -277,7 +301,8 @@ func (c *Crypto) getSDJWTSignedCredential( joseSigner := jws.NewSigner(signingKeyID, jwsAlgName, signer) - sdjwt, err := credential.MakeSDJWT(joseSigner, signingKeyID, verifiable.MakeSDJWTWithHash(digestHashAlgo)) + // + sdjwt, err := credential.MakeSDJWT(joseSigner, signingKeyID, options...) if err != nil { return nil, fmt.Errorf("make SDJWT credential error: %w", err) } diff --git a/pkg/doc/vc/sdjwt.go b/pkg/doc/vc/sdjwt.go index 39d6245ee..60dcb8725 100644 --- a/pkg/doc/vc/sdjwt.go +++ b/pkg/doc/vc/sdjwt.go @@ -6,10 +6,21 @@ SPDX-License-Identifier: Apache-2.0 package vc -import "crypto" +import ( + "crypto" + + "github.com/hyperledger/aries-framework-go/component/models/sdjwt/common" +) // SDJWT represents the SD-JWT configuration. type SDJWT struct { Enable bool `json:"enable,omitempty"` HashAlg crypto.Hash `json:"hashAlg,omitempty"` } + +type SelectiveDisclosureTemplate struct { // todo + Version common.SDJWTVersion `json:"version"` + AlwaysInclude []string `json:"alwaysInclude"` + RecursiveClaims []string `json:"recursiveClaims"` + NonSelectivelyDisclosable []string `json:"nonSelectivelyDisclosable"` +} diff --git a/pkg/doc/vc/signer.go b/pkg/doc/vc/signer.go index 46535c77f..411115511 100644 --- a/pkg/doc/vc/signer.go +++ b/pkg/doc/vc/signer.go @@ -33,4 +33,5 @@ type Signer struct { KMS keyManager VCStatusListType StatusType // Type of VC status list SDJWT SDJWT + SDJWTemplateData SelectiveDisclosureTemplate } diff --git a/pkg/profile/api.go b/pkg/profile/api.go index 5e5dcbb6a..1b165bcb9 100644 --- a/pkg/profile/api.go +++ b/pkg/profile/api.go @@ -11,6 +11,8 @@ import ( "time" "github.com/hyperledger/aries-framework-go-ext/component/vdr/orb" + + "github.com/hyperledger/aries-framework-go/component/models/sdjwt/common" "github.com/hyperledger/aries-framework-go/pkg/doc/presexch" "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" "github.com/hyperledger/aries-framework-go/pkg/kms" @@ -24,7 +26,8 @@ import ( type ( ID = string // ID of the Profile. Version = string // Profile version. - Method string // DID method of the Profile. + + Method string // DID method of the Profile. ) const ( @@ -52,12 +55,20 @@ type Issuer struct { } type CredentialTemplate struct { - Contexts []string `json:"contexts"` - ID string `json:"id"` - Type string `json:"type"` - CredentialSubject json.RawMessage `json:"credentialSubject"` - CredentialDefaultExpirationDuration *time.Duration `json:"credentialDefaultExpirationDuration"` - Checks CredentialTemplateChecks `json:"checks"` + Contexts []string `json:"contexts"` + ID string `json:"id"` + Type string `json:"type"` + CredentialSubject json.RawMessage `json:"credentialSubject"` + CredentialDefaultExpirationDuration *time.Duration `json:"credentialDefaultExpirationDuration"` + Checks CredentialTemplateChecks `json:"checks"` + SdJWT *SelectiveDisclosureTemplate `json:"sdJWT"` +} + +type SelectiveDisclosureTemplate struct { + Version common.SDJWTVersion `json:"version"` + AlwaysInclude []string `json:"alwaysInclude"` + RecursiveClaims []string `json:"recursiveClaims"` + NonSelectivelyDisclosable []string `json:"nonSelectivelyDisclosable"` } type CredentialTemplateChecks struct { diff --git a/pkg/restapi/v1/issuer/controller.go b/pkg/restapi/v1/issuer/controller.go index 373dc346a..dfb41b451 100644 --- a/pkg/restapi/v1/issuer/controller.go +++ b/pkg/restapi/v1/issuer/controller.go @@ -20,15 +20,16 @@ import ( "time" "github.com/google/uuid" - "github.com/hyperledger/aries-framework-go/component/models/ld/validator" - "github.com/hyperledger/aries-framework-go/pkg/doc/jsonld" - util2 "github.com/hyperledger/aries-framework-go/pkg/doc/util" - "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" "github.com/labstack/echo/v4" "github.com/piprate/json-gold/ld" "github.com/samber/lo" "go.opentelemetry.io/otel/trace" + "github.com/hyperledger/aries-framework-go/component/models/ld/validator" + "github.com/hyperledger/aries-framework-go/pkg/doc/jsonld" + util2 "github.com/hyperledger/aries-framework-go/pkg/doc/util" + "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" + "github.com/trustbloc/vcs/pkg/doc/vc" "github.com/trustbloc/vcs/pkg/doc/vc/crypto" vcsverifiable "github.com/trustbloc/vcs/pkg/doc/verifiable" @@ -654,7 +655,13 @@ func (c *Controller) PrepareCredential(e echo.Context) error { return err } - signedCredential, err := c.signCredential(ctx, result.Credential, nil, profile) + var signOpts []crypto.SigningOpts + if result.CredentialTemplate != nil && result.CredentialTemplate.SdJWT != nil { + cast := vc.SelectiveDisclosureTemplate(*result.CredentialTemplate.SdJWT) + signOpts = append(signOpts, crypto.WithSDJWTTemplateData(&cast)) + } + + signedCredential, err := c.signCredential(ctx, result.Credential, signOpts, profile) if err != nil { return err } diff --git a/pkg/service/issuecredential/issuecredential_service.go b/pkg/service/issuecredential/issuecredential_service.go index 8a7f86cd1..fb15ab6cd 100644 --- a/pkg/service/issuecredential/issuecredential_service.go +++ b/pkg/service/issuecredential/issuecredential_service.go @@ -64,7 +64,8 @@ func (s *Service) IssueCredential( ctx context.Context, credential *verifiable.Credential, issuerSigningOpts []crypto.SigningOpts, - profile *profileapi.Issuer) (*verifiable.Credential, error) { + profile *profileapi.Issuer, +) (*verifiable.Credential, error) { kms, err := s.kmsRegistry.GetKeyManager(profile.KMSConfig) if err != nil { return nil, fmt.Errorf("get kms: %w", err) diff --git a/pkg/service/oidc4ci/api.go b/pkg/service/oidc4ci/api.go index 988c0efee..f756f77b5 100644 --- a/pkg/service/oidc4ci/api.go +++ b/pkg/service/oidc4ci/api.go @@ -165,6 +165,7 @@ type PrepareCredentialResult struct { Retry bool EnforceStrictValidation bool OidcFormat vcsverifiable.OIDCFormat + CredentialTemplate *profileapi.CredentialTemplate } type InsertOptions struct { diff --git a/pkg/service/oidc4ci/oidc4ci_service.go b/pkg/service/oidc4ci/oidc4ci_service.go index 89bdbd0e6..94b080ada 100644 --- a/pkg/service/oidc4ci/oidc4ci_service.go +++ b/pkg/service/oidc4ci/oidc4ci_service.go @@ -18,9 +18,10 @@ import ( "time" "github.com/google/uuid" + "github.com/trustbloc/logutil-go/pkg/log" + "github.com/hyperledger/aries-framework-go/pkg/doc/util" "github.com/hyperledger/aries-framework-go/pkg/doc/verifiable" - "github.com/trustbloc/logutil-go/pkg/log" "github.com/trustbloc/vcs/pkg/dataprotect" "github.com/trustbloc/vcs/pkg/event/spi" @@ -488,6 +489,7 @@ func (s *Service) PrepareCredential( OidcFormat: tx.OIDCCredentialFormat, Retry: false, EnforceStrictValidation: tx.CredentialTemplate.Checks.Strict, + CredentialTemplate: tx.CredentialTemplate, }, nil } diff --git a/test/bdd/features/oidc4vc_api.feature b/test/bdd/features/oidc4vc_api.feature index 6ff005fa1..a519a224b 100644 --- a/test/bdd/features/oidc4vc_api.feature +++ b/test/bdd/features/oidc4vc_api.feature @@ -31,29 +31,30 @@ Feature: OIDC4VC REST API ## LDP issuer, LDP verifier, no limit disclosure and schema match in PD query. # | i_myprofile_cmtr_p256_ldp/v1.0 | CrudeProductCredential | pre-registered | crudeProductCredentialTemplateID | v_myprofile_ldp/v1.0 | lp403pb9-schema-match | schema_id | # -# Scenario Outline: OIDC credential issuance and verification Pre Auth flow -# Given Organization "test_org" has been authorized with client id "f13d1va9lp403pb9lyj89vk55" and secret "ejqxi9jb1vew2jbdnogpjcgrz" -# And Issuer with id "" is authorized as a Profile user -# And User holds credential "" with templateID "" -# -# When User interacts with Wallet to initiate credential issuance using pre authorization code flow -# Then credential is issued -# Then User interacts with Verifier and initiate OIDC4VP interaction under "" profile for organization "test_org" with presentation definition ID "" and fields "" -# And Verifier from organization "test_org" retrieves interactions claims -# Then we wait 2 seconds -# And Verifier form organization "test_org" requests deleted interactions claims -# -# Examples: -# | issuerProfile | credentialType | credentialTemplate | verifierProfile | presentationDefinitionID | fields | -## SDJWT issuer, JWT verifier, no limit disclosure in PD query. + Scenario Outline: OIDC credential issuance and verification Pre Auth flow + Given Organization "test_org" has been authorized with client id "f13d1va9lp403pb9lyj89vk55" and secret "ejqxi9jb1vew2jbdnogpjcgrz" + And Issuer with id "" is authorized as a Profile user + And User holds credential "" with templateID "" + + When User interacts with Wallet to initiate credential issuance using pre authorization code flow + Then credential is issued + Then User interacts with Verifier and initiate OIDC4VP interaction under "" profile for organization "test_org" with presentation definition ID "" and fields "" + And Verifier from organization "test_org" retrieves interactions claims + Then we wait 2 seconds + And Verifier form organization "test_org" requests deleted interactions claims + + Examples: + | issuerProfile | credentialType | credentialTemplate | verifierProfile | presentationDefinitionID | fields | +# SDJWT issuer, JWT verifier, no limit disclosure in PD query. # | bank_issuer/v1.0 | UniversityDegreeCredential | universityDegreeTemplateID | v_myprofile_jwt/v1.0 | 32f54163-no-limit-disclosure-single-field | degree_type_id | -## SDJWT issuer, JWT verifier, limit disclosure and optional fields in PD query. -# | bank_issuer/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_jwt/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | +# SDJWT issuer, JWT verifier, limit disclosure and optional fields in PD query. +# | bank_issuer/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_jwt/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | + | bank_issuer_sdjwt_v5/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_jwt/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | ## JWT issuer, JWT verifier, no limit disclosure and optional fields in PD query. # | i_myprofile_ud_es256k_jwt/v1.0 | PermanentResidentCard | permanentResidentCardTemplateID | v_myprofile_jwt/v1.0 | 32f54163-no-limit-disclosure-optional-fields | lpr_category_id,commuter_classification,registration_city | ## LDP issuer, LDP verifier, no limit disclosure and schema match in PD query. # | i_myprofile_cmtr_p256_ldp/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_ldp/v1.0 | lp403pb9-schema-match | schema_id | -# + ## Error cases # Scenario: OIDC credential issuance and verification Pre Auth flow (Invalid Claims) # Given Organization "test_org" has been authorized with client id "f13d1va9lp403pb9lyj89vk55" and secret "ejqxi9jb1vew2jbdnogpjcgrz" @@ -97,25 +98,25 @@ Feature: OIDC4VC REST API # | i_myprofile_ud_es256k_jwt/v1.0 | PermanentResidentCard | permanentResidentCardTemplateID | v_myprofile_jwt/v1.0 | 32f54163-no-limit-disclosure-optional-fields | lpr_category_id,registration_city,commuter_classification | # | i_myprofile_cmtr_p256_ldp/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_ldp/v1.0 | lp403pb9-schema-match | schema_id | - Scenario Outline: OIDC credential issuance and verification Pre Auth flow (Limit Disclosures enabled for JWT and LDP VC) - Given Organization "test_org" has been authorized with client id "f13d1va9lp403pb9lyj89vk55" and secret "ejqxi9jb1vew2jbdnogpjcgrz" - And Issuer with id "" is authorized as a Profile user - And User holds credential "" with templateID "" - - When User interacts with Wallet to initiate credential issuance using pre authorization code flow - Then credential is issued - And User interacts with Verifier and initiate OIDC4VP interaction under "" profile for organization "test_org" with presentation definition ID "" and fields "" and receives "verifiable credential doesn't contains proof" error - Then we wait 15 seconds - And Verifier form organization "test_org" requests expired interactions claims - - Examples: - | issuerProfile | credentialType | credentialTemplate | verifierProfile | presentationDefinitionID | fields | -# JWT issuer, JWT verifier, limit disclosure enabled in PD query. - | i_myprofile_ud_es256k_jwt/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_jwt/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | -# LDP issuer, LDP verifier, limit disclosure enabled in PD query. - | i_myprofile_cmtr_p256_ldp/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_ldp/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | +# Scenario Outline: OIDC credential issuance and verification Pre Auth flow (Limit Disclosures enabled for JWT and LDP VC) +# Given Organization "test_org" has been authorized with client id "f13d1va9lp403pb9lyj89vk55" and secret "ejqxi9jb1vew2jbdnogpjcgrz" +# And Issuer with id "" is authorized as a Profile user +# And User holds credential "" with templateID "" +# +# When User interacts with Wallet to initiate credential issuance using pre authorization code flow +# Then credential is issued +# And User interacts with Verifier and initiate OIDC4VP interaction under "" profile for organization "test_org" with presentation definition ID "" and fields "" and receives "verifiable credential doesn't contains proof" error +# Then we wait 15 seconds +# And Verifier form organization "test_org" requests expired interactions claims # -# Scenario Outline: OIDC credential issuance and verification Pre Auth flow (OIDC4VP flow - unsupported vp_token format) +# Examples: +# | issuerProfile | credentialType | credentialTemplate | verifierProfile | presentationDefinitionID | fields | +## JWT issuer, JWT verifier, limit disclosure enabled in PD query. +# | i_myprofile_ud_es256k_jwt/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_jwt/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | +## LDP issuer, LDP verifier, limit disclosure enabled in PD query. +# | i_myprofile_cmtr_p256_ldp/v1.0 | CrudeProductCredential | crudeProductCredentialTemplateID | v_myprofile_ldp/v1.0 | 3c8b1d9a-limit-disclosure-optional-fields | unit_of_measure_barrel,api_gravity,category,supplier_address | +## +## Scenario Outline: OIDC credential issuance and verification Pre Auth flow (OIDC4VP flow - unsupported vp_token format) # Given Organization "test_org" has been authorized with client id "f13d1va9lp403pb9lyj89vk55" and secret "ejqxi9jb1vew2jbdnogpjcgrz" # And Issuer with id "" is authorized as a Profile user # And User holds credential "" with templateID "" diff --git a/test/bdd/fixtures/profile/profiles.json b/test/bdd/fixtures/profile/profiles.json index 8abc2e00c..1db59a3a2 100644 --- a/test/bdd/fixtures/profile/profiles.json +++ b/test/bdd/fixtures/profile/profiles.json @@ -834,6 +834,193 @@ "didDomain": "https://testnet.orb.local", "didServiceAuthToken": "tk1" }, + { + "issuer": { + "id": "bank_issuer_sdjwt_v5", + "version": "v1.0", + "groupID": "group_bank_issuer", + "name": "Bank Issuer", + "organizationID": "f13d1va9lp403pb9lyj89vk55", + "url": "http://vc-rest-echo.trustbloc.local:8075", + "active": true, + "vcConfig": { + "signingAlgorithm": "JsonWebSignature2020", + "signatureRepresentation": 0, + "keyType": "ECDSASecp256k1DER", + "format": "jwt", + "didMethod": "orb", + "status": { + "type": "StatusList2021Entry" + }, + "sdjwt": { + "enable": true, + "hashAlg": 6 + } + }, + "oidcConfig": { + "client_id": "7d4u50e7w6nfq8tfayhzplgjf", + "client_secret_handle": "282ks4fkuqfosus5k0x30abnv", + "issuer_well_known": "http://cognito-mock.trustbloc.local:9229/local_5a9GzRvB/.well-known/openid-configuration", + "scopes_supported": [ + "openid", + "profile" + ], + "grant_types_supported": [ + "authorization_code" + ], + "response_types_supported": [ + "code" + ], + "token_endpoint_auth_methods_supported": [ + "none" + ], + "enable_dynamic_client_registration": true, + "enable_discoverable_client_id_scheme": true, + "pre-authorized_grant_anonymous_access_supported": true, + "wallet_initiated_auth_flow_supported": true, + "claims_endpoint": "https://mock-login-consent.example.com:8099/claim-data?credentialType=UniversityDegreeCredential" + }, + "credentialTemplates": [ + { + "contexts": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "type": "UniversityDegreeCredential", + "id": "universityDegreeTemplateID", + "issuer": "did:orb:bank_issuer", + "checks": { + "strict": true + } + }, + { + "contexts": [ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1" + ], + "type": "VerifiedEmployee", + "id": "templateID", + "issuer": "did:orb:bank_issuer", + "checks": { + "strict": true + } + }, + { + "contexts": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/citizenship/v1" + ], + "type": "PermanentResidentCard", + "id": "permanentResidentCardTemplateID", + "issuer": "did:orb:bank_issuer", + "checks": { + "strict": true + } + }, + { + "contexts": [ + "https://www.w3.org/2018/credentials/v1", + "https://trustbloc.github.io/context/vc/examples-crude-product-v1.jsonld" + ], + "type": "CrudeProductCredential", + "id": "crudeProductCredentialTemplateID", + "issuer": "did:orb:bank_issuer", + "checks": { + "strict": true + }, + "sdJWT" : { + "version" : 5, + "recursiveClaims" : ["chemicalSpecs"], + "nonSelectivelyDisclosable" : ["address"] + } + } + ], + "credentialMetadata": { + "credentials_supported": [ + { + "format": "jwt_vc_json-ld", + "id": "VerifiedEmployee_JWT", + "types": [ + "VerifiableCredential", + "VerifiedEmployee" + ], + "display": [ + { + "name": "Verified Employee", + "locale": "en-US", + "logo": { + "url": "https://example.com/public/logo.png", + "alt_text": "a square logo of a employee verification" + }, + "background_color": "#12107c", + "text_color": "#FFFFFF" + } + ], + "credentialSubject": { + "displayName": { + "display": [ + { + "name": "Employee", + "locale": "en-US" + } + ] + }, + "givenName": { + "display": [ + { + "name": "Given Name", + "locale": "en-US" + } + ] + }, + "jobTitle": { + "display": [ + { + "name": "Job Title", + "locale": "en-US" + } + ] + }, + "surname": { + "display": [ + { + "name": "Surname", + "locale": "en-US" + } + ] + }, + "preferredLanguage": { + "display": [ + { + "name": "Preferred Language", + "locale": "en-US" + } + ] + }, + "mail": { + "display": [ + { + "name": "Mail", + "locale": "en-US" + } + ] + }, + "photo": { + "display": [ + { + "name": "Photo" + } + ] + } + } + } + ] + } + }, + "createDID": true, + "didDomain": "https://testnet.orb.local", + "didServiceAuthToken": "tk1" + }, { "issuer": { "id": "issuer_without_oidc",