diff --git a/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go b/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go index 9d083a15c..e864fb1f8 100644 --- a/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go +++ b/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go @@ -154,7 +154,7 @@ func (f *Flow) Run(ctx context.Context) error { HTTPClient: f.httpClient, }) - if err = trustRegistry.ValidateVerifier(trustRegistryURL, requestObject.ClientID, credentials); err != nil { + if err = trustRegistry.ValidateWalletPresentation(trustRegistryURL, requestObject.ClientID, credentials); err != nil { return fmt.Errorf("trust registry verifier validation: %w", err) } } diff --git a/component/wallet-cli/pkg/trustregistry/models.go b/component/wallet-cli/pkg/trustregistry/models.go index d5e16ced8..4d72f0d72 100644 --- a/component/wallet-cli/pkg/trustregistry/models.go +++ b/component/wallet-cli/pkg/trustregistry/models.go @@ -6,17 +6,27 @@ SPDX-License-Identifier: Apache-2.0 package trustregistry -type VerifierValidationConfig struct { +type WalletPresentationValidationConfig struct { VerifierDID string `json:"verifier_did"` - Metadata []*CredentialMetadata `json:"metadata"` + Metadata []*CredentialMetadata `json:"credential_metadata"` } +// CredentialMetadata defines model for CredentialMetadata. type CredentialMetadata struct { - CredentialID string `json:"credential_id"` - Types []string `json:"types"` - Issuer string `json:"issuer"` - Issued string `json:"issued"` - Expired string `json:"expired"` + // Credential ID + CredentialID string `json:"credential_id,omitempty"` + + // Credential Types + CredentialTypes []string `json:"credential_types,omitempty"` + + // Expiration date/time. + ExpirationDate string `json:"expiration_date,omitempty"` + + // Issuance date/time. + IssuanceDate string `json:"issuance_date,omitempty"` + + // Issuer ID + IssuerID string `json:"issuer_id,omitempty"` } type Response struct { diff --git a/component/wallet-cli/pkg/trustregistry/trustregistry.go b/component/wallet-cli/pkg/trustregistry/trustregistry.go index ad249ec44..2fcbbc583 100644 --- a/component/wallet-cli/pkg/trustregistry/trustregistry.go +++ b/component/wallet-cli/pkg/trustregistry/trustregistry.go @@ -34,12 +34,13 @@ func New(conf *Config) *Service { return &Service{httpClient: conf.HTTPClient} } -func (s *Service) ValidateVerifier( +// ValidateWalletPresentation validates wallet presentation using Trust Registry API. +func (s *Service) ValidateWalletPresentation( policyURL, verifierDID string, presentationCredentials []*verifiable.Credential, ) error { - logger.Debug("ValidateVerifier begin") - verifierValidationConfig := &VerifierValidationConfig{ + logger.Debug("ValidateWalletPresentation begin") + walletPresentationConfig := &WalletPresentationValidationConfig{ VerifierDID: verifierDID, Metadata: make([]*CredentialMetadata, len(presentationCredentials)), } @@ -47,10 +48,10 @@ func (s *Service) ValidateVerifier( for i, credential := range presentationCredentials { content := credential.Contents() - verifierValidationConfig.Metadata[i] = getTrustRegistryCredentialMetadata(content) + walletPresentationConfig.Metadata[i] = getTrustRegistryCredentialMetadata(content) } - reqPayload, err := json.Marshal(verifierValidationConfig) + reqPayload, err := json.Marshal(walletPresentationConfig) if err != nil { return fmt.Errorf("encode verifier config: %w", err) } @@ -64,7 +65,7 @@ func (s *Service) ValidateVerifier( return ErrInteractionRestricted } - logger.Debug("ValidateVerifier succeed") + logger.Debug("ValidateWalletPresentation succeed") return nil } @@ -108,10 +109,10 @@ func getTrustRegistryCredentialMetadata(content verifiable.CredentialContents) * } return &CredentialMetadata{ - CredentialID: content.ID, - Types: content.Types, - Issuer: content.Issuer.ID, - Issued: iss, - Expired: exp, + CredentialID: content.ID, + CredentialTypes: content.Types, + ExpirationDate: exp, + IssuanceDate: iss, + IssuerID: content.Issuer.ID, } } diff --git a/component/wallet-cli/pkg/trustregistry/trustregistry_test.go b/component/wallet-cli/pkg/trustregistry/trustregistry_test.go index c886a4c75..59d3d5150 100644 --- a/component/wallet-cli/pkg/trustregistry/trustregistry_test.go +++ b/component/wallet-cli/pkg/trustregistry/trustregistry_test.go @@ -16,7 +16,7 @@ const ( walletAttestationVCType = "WalletAttestationCredential" ) -func TestService_ValidateVerifier(t *testing.T) { +func TestService_ValidateWalletPresentation(t *testing.T) { now := time.Now() handler := echo.New() @@ -42,10 +42,10 @@ func TestService_ValidateVerifier(t *testing.T) { name: "Success", addTestCaseHandler: func(t *testing.T, e *echo.Echo) { e.Add(http.MethodPost, "/testcase1", func(c echo.Context) error { - var got *VerifierValidationConfig + var got *WalletPresentationValidationConfig assert.NoError(t, c.Bind(&got)) - expected := &VerifierValidationConfig{ + expected := &WalletPresentationValidationConfig{ VerifierDID: "did:oin:abc", Metadata: getDefaultMetadata(t, now), } @@ -137,9 +137,9 @@ func TestService_ValidateVerifier(t *testing.T) { httpClient: http.DefaultClient, } - err := s.ValidateVerifier(tt.fields.url, tt.args.verifierDID, tt.args.getPresentationCredentials(t, now)) + err := s.ValidateWalletPresentation(tt.fields.url, tt.args.verifierDID, tt.args.getPresentationCredentials(t, now)) if (err != nil) != tt.wantErr { - t.Errorf("ValidateVerifier() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("ValidateWalletPresentation() error = %v, wantErr %v", err, tt.wantErr) } if tt.wantErr { @@ -199,21 +199,21 @@ func getDefaultMetadata(t *testing.T, now time.Time) []*CredentialMetadata { return []*CredentialMetadata{ { CredentialID: "credentialID1", - Types: []string{ + CredentialTypes: []string{ "VerifiableCredential", }, - Issuer: "issuerID1", - Issued: now.Format(time.RFC3339Nano), - Expired: now.Add(time.Hour).Format(time.RFC3339Nano), + IssuerID: "issuerID1", + IssuanceDate: now.Format(time.RFC3339Nano), + ExpirationDate: now.Add(time.Hour).Format(time.RFC3339Nano), }, { CredentialID: "credentialID2", - Types: []string{ + CredentialTypes: []string{ walletAttestationVCType, }, - Issuer: "issuerID2", - Issued: now.Format(time.RFC3339Nano), - Expired: now.Add(time.Hour).Format(time.RFC3339Nano), + IssuerID: "issuerID2", + IssuanceDate: now.Format(time.RFC3339Nano), + ExpirationDate: now.Add(time.Hour).Format(time.RFC3339Nano), }, } } diff --git a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go index 0363f995a..312c69586 100644 --- a/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go +++ b/component/wallet-cli/pkg/walletrunner/wallet_runner_oidc4vp.go @@ -132,7 +132,7 @@ func (s *Service) RunOIDC4VPFlow(ctx context.Context, authorizationRequest strin credentials := s.vpFlowExecutor.requestPresentation[0].Credentials() - if err = trustRegistry.ValidateVerifier(trustRegistryURL, s.vpFlowExecutor.requestObject.ClientID, credentials); err != nil { + if err = trustRegistry.ValidateWalletPresentation(trustRegistryURL, s.vpFlowExecutor.requestObject.ClientID, credentials); err != nil { return fmt.Errorf("trust registry verifier validation: %w", err) } } diff --git a/pkg/service/clientattestation/client_attestation_service.go b/pkg/service/clientattestation/client_attestation_service.go index 187d73fb3..d089016ba 100644 --- a/pkg/service/clientattestation/client_attestation_service.go +++ b/pkg/service/clientattestation/client_attestation_service.go @@ -29,7 +29,8 @@ type vcStatusVerifier interface { ValidateVCStatus(ctx context.Context, vcStatus *verifiable.TypedID, issuer *verifiable.Issuer) error } -type TrustRegistryPayloadBuilder func(attestationVC *verifiable.Credential, vp *verifiable.Presentation) ([]byte, error) +type TrustRegistryPayloadBuilder func( + clientDID string, attestationVC *verifiable.Credential, vp *verifiable.Presentation) ([]byte, error) // Config defines configuration for Service. type Config struct { @@ -59,11 +60,20 @@ func NewService(config *Config) *Service { // ValidateAttestationJWTVP validates attestation VP in jwt_vp format. // +// Arguments: +// +// jwtVP - presentation contains attestation VC +// policyURL - Trust Registry policy URL +// clientDID - DID identifier. +// +// payloadBuilder - payload builder function. +// //nolint:revive func (s *Service) ValidateAttestationJWTVP( ctx context.Context, jwtVP string, policyURL string, + clientDID string, payloadBuilder TrustRegistryPayloadBuilder, ) error { vp, err := verifiable.ParsePresentation( @@ -116,7 +126,7 @@ func (s *Service) ValidateAttestationJWTVP( } var trustRegistryRequestBody []byte - trustRegistryRequestBody, err = payloadBuilder(attestationVC, vp) + trustRegistryRequestBody, err = payloadBuilder(clientDID, attestationVC, vp) if err != nil { return fmt.Errorf("payload builder: %w", err) } diff --git a/pkg/service/clientattestation/client_attestation_service_test.go b/pkg/service/clientattestation/client_attestation_service_test.go index a92547390..913f5d730 100644 --- a/pkg/service/clientattestation/client_attestation_service_test.go +++ b/pkg/service/clientattestation/client_attestation_service_test.go @@ -35,6 +35,7 @@ const ( attestationKeyID = "did:example:attestation-service#attestation-key-id" walletDID = "did:example:wallet" + verifierDID = "did:example:verifier" walletKeyID = "did:example:wallet#wallet-key-id" ) @@ -48,6 +49,7 @@ func TestService_ValidateClientAttestationJWTVP(t *testing.T) { vcStatusVerifier := NewMockVCStatusVerifier(gomock.NewController(t)) var jwtVP string + var clientDID string var payloadBuilder clientattestation.TrustRegistryPayloadBuilder proofCreators, defaultProofChecker := testsupport.NewKMSSignersAndVerifier(t, @@ -117,6 +119,8 @@ func TestService_ValidateClientAttestationJWTVP(t *testing.T) { name: "success OIDC4VP", url: srv.URL + "/success_oidc4vp", setup: func() { + clientDID = verifierDID + // create wallet attestation VC with wallet DID as subject and attestation DID as issuer attestationVC := createAttestationVC(t, attestationProofCreator, walletDID, now, false) @@ -133,15 +137,16 @@ func TestService_ValidateClientAttestationJWTVP(t *testing.T) { payloadBuilder = clientattestation.VerifierInteractionTrustRegistryPayloadBuilder handler.Add(http.MethodPost, "/success_oidc4vp", func(c echo.Context) error { - var got *clientattestation.VerifierInteractionValidationConfig + var got *clientattestation.VerifierPresentationValidationConfig assert.NoError(t, c.Bind(&got)) - attestationVCUniversalForm, err := attestationVC.ToUniversalForm() + attestationVCJWT, err := attestationVC.ToJWTString() assert.NoError(t, err) - expected := &clientattestation.VerifierInteractionValidationConfig{ - AttestationVC: attestationVCUniversalForm, - Metadata: []*clientattestation.CredentialMetadata{ + expected := &clientattestation.VerifierPresentationValidationConfig{ + AttestationVC: []string{attestationVCJWT}, + VerifierDID: verifierDID, + RequestedVCMetadata: []*clientattestation.CredentialMetadata{ getAttestationVCMetadata(t, now, false), getRequestedVCMetadata(t, now), }, @@ -241,7 +246,7 @@ func TestService_ValidateClientAttestationJWTVP(t *testing.T) { vcStatusVerifier.EXPECT().ValidateVCStatus(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) - payloadBuilder = func(_ *verifiable.Credential, _ *verifiable.Presentation) ([]byte, error) { + payloadBuilder = func(_ string, _ *verifiable.Credential, _ *verifiable.Presentation) ([]byte, error) { return nil, errors.New("some error") } }, @@ -310,7 +315,7 @@ func TestService_ValidateClientAttestationJWTVP(t *testing.T) { ProofChecker: proofChecker, VCStatusVerifier: vcStatusVerifier, }, - ).ValidateAttestationJWTVP(context.Background(), jwtVP, tt.url, payloadBuilder), + ).ValidateAttestationJWTVP(context.Background(), jwtVP, tt.url, clientDID, payloadBuilder), ) }) } @@ -440,9 +445,9 @@ func getAttestationVCMetadata(t *testing.T, now time.Time, expired bool) *client "VerifiableCredential", "WalletAttestationCredential", }, - Issuer: attestationDID, - Issued: now.Format(time.RFC3339), - Expired: exp, + IssuerID: attestationDID, + Issued: now.Format(time.RFC3339), + Expired: exp, } } @@ -454,8 +459,8 @@ func getRequestedVCMetadata(t *testing.T, now time.Time) *clientattestation.Cred Types: []string{ "VerifiableCredential", }, - Issuer: walletDID, - Issued: now.Round(time.Second).Format(time.RFC3339), - Expired: now.Round(time.Second).Add(-time.Hour).Format(time.RFC3339), + IssuerID: walletDID, + Issued: now.Round(time.Second).Format(time.RFC3339), + Expired: now.Round(time.Second).Add(-time.Hour).Format(time.RFC3339), } } diff --git a/pkg/service/clientattestation/models.go b/pkg/service/clientattestation/models.go index a00529b45..1b83b11d5 100644 --- a/pkg/service/clientattestation/models.go +++ b/pkg/service/clientattestation/models.go @@ -11,17 +11,27 @@ type IssuerInteractionValidationConfig struct { Metadata []*CredentialMetadata `json:"metadata"` } -type VerifierInteractionValidationConfig struct { - AttestationVC interface{} `json:"attestation_vc"` - Metadata []*CredentialMetadata `json:"metadata"` +// VerifierPresentationValidationConfig represents DTO for verifier presentation policy evaluation. +type VerifierPresentationValidationConfig struct { + // Attestation verifiable credential(s). + AttestationVC []string `json:"attestation_vc"` + // Verifier DID. + VerifierDID string `json:"verifier_did"` + // Credential metadata for Requested VCs only. + RequestedVCMetadata []*CredentialMetadata `json:"credential_metadata"` } type CredentialMetadata struct { - CredentialID string `json:"credential_id"` - Types []string `json:"types"` - Issuer string `json:"issuer"` - Issued string `json:"issued"` - Expired string `json:"expired"` + // Credential ID + CredentialID string `json:"credential_id"` + // Credential Types. + Types []string `json:"credential_types"` + // Issuer ID. + IssuerID string `json:"issuer_id"` + // Issuance date/time. + Issued string `json:"issuance_date"` + // Expiration date/time. + Expired string `json:"expiration_date"` } type TrustRegistryResponse struct { diff --git a/pkg/service/clientattestation/trustregistry.go b/pkg/service/clientattestation/trustregistry.go index ee21a5714..23de01f45 100644 --- a/pkg/service/clientattestation/trustregistry.go +++ b/pkg/service/clientattestation/trustregistry.go @@ -27,6 +27,7 @@ const ( // TODO: update payloads func IssuerInteractionTrustRegistryPayloadBuilder( + _ string, attestationVC *verifiable.Credential, presentation *verifiable.Presentation, ) ([]byte, error) { @@ -54,25 +55,28 @@ func IssuerInteractionTrustRegistryPayloadBuilder( return reqPayload, nil } -// TODO: update payloads +// VerifierInteractionTrustRegistryPayloadBuilder builds Trust Registry payload for Verifier interaction verification. func VerifierInteractionTrustRegistryPayloadBuilder( + verifierDID string, attestationVC *verifiable.Credential, presentation *verifiable.Presentation, ) ([]byte, error) { credentials := presentation.Credentials() - presentationValidationConfig := &VerifierInteractionValidationConfig{ - Metadata: make([]*CredentialMetadata, len(credentials)), + presentationValidationConfig := &VerifierPresentationValidationConfig{ + AttestationVC: make([]string, 1), + VerifierDID: verifierDID, + RequestedVCMetadata: make([]*CredentialMetadata, len(credentials)), } - if uf, err := attestationVC.ToUniversalForm(); err == nil { - presentationValidationConfig.AttestationVC = uf + if attestationVCJWT, err := attestationVC.ToJWTString(); err == nil { + presentationValidationConfig.AttestationVC[0] = attestationVCJWT } for i, credential := range credentials { content := credential.Contents() - presentationValidationConfig.Metadata[i] = getCredentialMetadata(content) + presentationValidationConfig.RequestedVCMetadata[i] = getCredentialMetadata(content) } reqPayload, err := json.Marshal(presentationValidationConfig) @@ -125,7 +129,7 @@ func getCredentialMetadata(content verifiable.CredentialContents) *CredentialMet return &CredentialMetadata{ CredentialID: content.ID, Types: content.Types, - Issuer: content.Issuer.ID, + IssuerID: content.Issuer.ID, Issued: iss, Expired: exp, } diff --git a/pkg/service/clientattestation/trustregistry_test.go b/pkg/service/clientattestation/trustregistry_test.go index 8b19dd117..c909ea60b 100644 --- a/pkg/service/clientattestation/trustregistry_test.go +++ b/pkg/service/clientattestation/trustregistry_test.go @@ -161,7 +161,7 @@ func Test_getCredentialMetadata(t *testing.T) { want: &CredentialMetadata{ CredentialID: "credentialID", Types: []string{verifiable.VCType, "WalletAttestationCredential"}, - Issuer: "someIssuerID", + IssuerID: "someIssuerID", Issued: "", Expired: "", }, @@ -184,7 +184,7 @@ func Test_getCredentialMetadata(t *testing.T) { want: &CredentialMetadata{ CredentialID: "credentialID", Types: []string{verifiable.VCType, "WalletAttestationCredential"}, - Issuer: "someIssuerID", + IssuerID: "someIssuerID", Issued: now.Format(time.RFC3339Nano), Expired: now.Add(time.Hour).Format(time.RFC3339Nano), }, diff --git a/pkg/service/oidc4ci/oidc4ci_service.go b/pkg/service/oidc4ci/oidc4ci_service.go index 135ca1e10..59821b3c3 100644 --- a/pkg/service/oidc4ci/oidc4ci_service.go +++ b/pkg/service/oidc4ci/oidc4ci_service.go @@ -124,6 +124,7 @@ type clientAttestationService interface { ctx context.Context, jwtVP string, policyURL string, + clientDID string, builder clientattestation.TrustRegistryPayloadBuilder) error } diff --git a/pkg/service/oidc4ci/oidc4ci_service_authenticate_client.go b/pkg/service/oidc4ci/oidc4ci_service_authenticate_client.go index 3e11fc5f8..2c32e2044 100644 --- a/pkg/service/oidc4ci/oidc4ci_service_authenticate_client.go +++ b/pkg/service/oidc4ci/oidc4ci_service_authenticate_client.go @@ -53,6 +53,7 @@ func (s *Service) AuthenticateClient( ctx, clientAssertion, profile.Policy.URL, + profile.SigningDID.DID, clientattestation.IssuerInteractionTrustRegistryPayloadBuilder); err != nil { return resterr.NewCustomError(resterr.OIDCClientAuthenticationFailed, err) } diff --git a/pkg/service/oidc4ci/oidc4ci_service_authenticate_client_test.go b/pkg/service/oidc4ci/oidc4ci_service_authenticate_client_test.go index dfe048b52..0f9f7a464 100644 --- a/pkg/service/oidc4ci/oidc4ci_service_authenticate_client_test.go +++ b/pkg/service/oidc4ci/oidc4ci_service_authenticate_client_test.go @@ -18,6 +18,10 @@ import ( "github.com/trustbloc/vcs/pkg/service/oidc4ci" ) +const ( + issuerDID = "did:oin:abc" +) + func TestService_AuthenticateClient(t *testing.T) { var ( clientAttestationService *MockClientAttestationService @@ -40,6 +44,7 @@ func TestService_AuthenticateClient(t *testing.T) { OIDCConfig: &profileapi.OIDCConfig{ TokenEndpointAuthMethodsSupported: []string{"attest_jwt_client_auth"}, }, + SigningDID: &profileapi.SigningDID{DID: issuerDID}, } clientID = "client-id" @@ -52,8 +57,9 @@ func TestService_AuthenticateClient(t *testing.T) { context.Background(), clientAssertion, "https://policy.example.com", + issuerDID, gomock.Any(), - ).Return(nil) + ).Times(1).Return(nil) }, check: func(t *testing.T, err error) { require.NoError(t, err) @@ -113,13 +119,6 @@ func TestService_AuthenticateClient(t *testing.T) { clientAssertion = "client-attestation-jwt-vp" clientAttestationService = NewMockClientAttestationService(gomock.NewController(t)) - - clientAttestationService.EXPECT().ValidateAttestationJWTVP( - context.Background(), - clientAssertion, // - "", - gomock.Any(), - ).Times(0) }, check: func(t *testing.T, err error) { require.ErrorContains(t, err, "client_id is required") @@ -140,13 +139,6 @@ func TestService_AuthenticateClient(t *testing.T) { clientAssertion = "client-attestation-jwt-vp" clientAttestationService = NewMockClientAttestationService(gomock.NewController(t)) - - clientAttestationService.EXPECT().ValidateAttestationJWTVP( - context.Background(), - clientAssertion, // - "", - gomock.Any(), - ).Times(0) }, check: func(t *testing.T, err error) { require.ErrorContains(t, err, "only supported client assertion type is attest_jwt_client_auth") @@ -167,13 +159,6 @@ func TestService_AuthenticateClient(t *testing.T) { clientAssertion = "" clientAttestationService = NewMockClientAttestationService(gomock.NewController(t)) - - clientAttestationService.EXPECT().ValidateAttestationJWTVP( - context.Background(), - clientAssertion, // - "", - gomock.Any(), - ).Times(0) }, check: func(t *testing.T, err error) { require.ErrorContains(t, err, "client_assertion is required") @@ -183,7 +168,8 @@ func TestService_AuthenticateClient(t *testing.T) { name: "fail to validate client attestation jwt", setup: func() { profile = &profileapi.Issuer{ - Policy: profileapi.Policy{URL: "https://policy.example.com"}, + SigningDID: &profileapi.SigningDID{DID: issuerDID}, + Policy: profileapi.Policy{URL: "https://policy.example.com"}, OIDCConfig: &profileapi.OIDCConfig{ TokenEndpointAuthMethodsSupported: []string{"attest_jwt_client_auth"}, }, @@ -199,6 +185,7 @@ func TestService_AuthenticateClient(t *testing.T) { context.Background(), clientAssertion, // "https://policy.example.com", + issuerDID, gomock.Any(), ).Return(errors.New("validate error")) }, diff --git a/pkg/service/verifypresentation/verifypresentation_service.go b/pkg/service/verifypresentation/verifypresentation_service.go index ed6eae343..6eed0a054 100644 --- a/pkg/service/verifypresentation/verifypresentation_service.go +++ b/pkg/service/verifypresentation/verifypresentation_service.go @@ -45,6 +45,7 @@ type clientAttestationService interface { ctx context.Context, jwtVP string, policyURL string, + clientDID string, payloadBuilder clientattestation.TrustRegistryPayloadBuilder) error } @@ -101,7 +102,11 @@ func (s *Service) VerifyPresentation( //nolint:funlen,gocognit // Attestation VC validation. err := s.clientAttestationService.ValidateAttestationJWTVP( - ctx, presentation.JWT, profile.Policy.URL, clientattestation.VerifierInteractionTrustRegistryPayloadBuilder) + ctx, presentation.JWT, + profile.Policy.URL, + profile.SigningDID.DID, + clientattestation.VerifierInteractionTrustRegistryPayloadBuilder, + ) if err != nil { result = append(result, PresentationVerificationCheckResult{ Check: "clientAttestation", diff --git a/pkg/service/verifypresentation/verifypresentation_service_test.go b/pkg/service/verifypresentation/verifypresentation_service_test.go index 51bd76af0..6ba9bae58 100644 --- a/pkg/service/verifypresentation/verifypresentation_service_test.go +++ b/pkg/service/verifypresentation/verifypresentation_service_test.go @@ -36,6 +36,10 @@ var ( clientAttestationVP []byte ) +const ( + verifierDID = "did:key:abc" +) + func TestNew(t *testing.T) { ctrl := gomock.NewController(t) @@ -128,6 +132,7 @@ func TestService_VerifyPresentation(t *testing.T) { context.Background(), gomock.Any(), "https://trustregistry.example.com", + verifierDID, gomock.Any(), ).Return(nil) @@ -140,7 +145,7 @@ func TestService_VerifyPresentation(t *testing.T) { }, profile: &profileapi.Verifier{ Policy: profileapi.Policy{URL: "https://trustregistry.example.com"}, - SigningDID: &profileapi.SigningDID{DID: "did:key:abc"}, + SigningDID: &profileapi.SigningDID{DID: verifierDID}, Checks: &profileapi.VerificationChecks{ Presentation: &profileapi.PresentationChecks{ Proof: true, @@ -168,7 +173,7 @@ func TestService_VerifyPresentation(t *testing.T) { wantErr: false, }, { - name: "OK with Trust registry disabled enabled and client attestation VC included in VP", + name: "OK with Trust registry validation disabled and client attestation VC included in VP", fields: fields{ getVDR: func() vdrapi.Registry { return signedClientAttestationVP.VDR @@ -200,7 +205,7 @@ func TestService_VerifyPresentation(t *testing.T) { return signedClientAttestationVP.Presentation }, profile: &profileapi.Verifier{ - SigningDID: &profileapi.SigningDID{DID: "did:key:abc"}, + SigningDID: &profileapi.SigningDID{DID: verifierDID}, Checks: &profileapi.VerificationChecks{ Presentation: &profileapi.PresentationChecks{ Proof: true, @@ -260,7 +265,7 @@ func TestService_VerifyPresentation(t *testing.T) { return signedRequestedCredentialsVP.Presentation }, profile: &profileapi.Verifier{ - SigningDID: &profileapi.SigningDID{DID: "did:key:abc"}, + SigningDID: &profileapi.SigningDID{DID: verifierDID}, Checks: &profileapi.VerificationChecks{ Presentation: &profileapi.PresentationChecks{ Proof: true, @@ -362,6 +367,7 @@ func TestService_VerifyPresentation(t *testing.T) { context.Background(), gomock.Any(), "https://trustregistry.example.com", + verifierDID, gomock.Any(), ).Return(errors.New("some error")) @@ -374,7 +380,7 @@ func TestService_VerifyPresentation(t *testing.T) { }, profile: &profileapi.Verifier{ Policy: profileapi.Policy{URL: "https://trustregistry.example.com"}, - SigningDID: &profileapi.SigningDID{DID: "did:key:abc"}, + SigningDID: &profileapi.SigningDID{DID: verifierDID}, Checks: &profileapi.VerificationChecks{ Presentation: &profileapi.PresentationChecks{ Proof: false, diff --git a/test/bdd/fixtures/profile/profiles.json b/test/bdd/fixtures/profile/profiles.json index bc581b450..4fc380982 100644 --- a/test/bdd/fixtures/profile/profiles.json +++ b/test/bdd/fixtures/profile/profiles.json @@ -1830,7 +1830,7 @@ "active": true, "webHook": "http://vcs.webhook.example.com:8180", "policy": { - "url": "https://mock-trustregistry.trustbloc.local:8098/policies/evaluate" + "url": "https://mock-trustregistry.trustbloc.local:8098/verifier/policies/policyID/policyVersion/interactions/presentation" }, "checks": { "credential": { diff --git a/test/bdd/pkg/v1/oidc4vc/oidc4ci.go b/test/bdd/pkg/v1/oidc4vc/oidc4ci.go index 2d0a62dc5..d7b318130 100644 --- a/test/bdd/pkg/v1/oidc4vc/oidc4ci.go +++ b/test/bdd/pkg/v1/oidc4vc/oidc4ci.go @@ -42,7 +42,7 @@ const ( oidcProviderURL = "http://cognito-auth.local:8094/cognito" loginPageURL = "https://localhost:8099/login" claimDataURL = "https://mock-login-consent.example.com:8099/claim-data" - trustRegistryURL = "https://mock-trustregistry.trustbloc.local:8098/policies/evaluate" + trustRegistryURL = "https://mock-trustregistry.trustbloc.local:8098/wallet/interactions/presentation" ) func (s *Steps) authorizeIssuerProfileUser(profileVersionedID, username, password string) error { diff --git a/test/bdd/trustregistry/models.go b/test/bdd/trustregistry/models.go new file mode 100644 index 000000000..fde6d79fb --- /dev/null +++ b/test/bdd/trustregistry/models.go @@ -0,0 +1,35 @@ +/* +Copyright Avast Software. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package main + +// VerifierPresentationValidationConfig represents DTO for verifier presentation policy evaluation. +type VerifierPresentationValidationConfig struct { + // Attestation verifiable credential(s). + AttestationVC []string `json:"attestation_vc"` + // Verifier DID. + VerifierDID string `json:"verifier_did"` + // Credential metadata for Requested VCs only. + RequestedVCMetadata []*CredentialMetadata `json:"credential_metadata"` +} + +type WalletPresentationValidationConfig struct { + VerifierDID string `json:"verifier_did"` + RequestedVCMetadata []*CredentialMetadata `json:"credential_metadata"` +} + +type CredentialMetadata struct { + // Credential ID + CredentialID string `json:"credential_id"` + // Credential Types. + Types []string `json:"credential_types"` + // Issuer ID. + IssuerID string `json:"issuer_id"` + // Issuance date/time. + Issued string `json:"issuance_date"` + // Expiration date/time. + Expired string `json:"expiration_date"` +} diff --git a/test/bdd/trustregistry/server.go b/test/bdd/trustregistry/server.go index 19488e908..6a0be6c06 100644 --- a/test/bdd/trustregistry/server.go +++ b/test/bdd/trustregistry/server.go @@ -8,9 +8,11 @@ package main import ( "encoding/json" - "github.com/gorilla/mux" + "fmt" "log" "net/http" + + "github.com/gorilla/mux" ) type server struct { @@ -24,7 +26,8 @@ func newServer() *server { router: router, } - router.HandleFunc("/policies/evaluate", srv.evaluatePolicies).Methods(http.MethodPost) + router.HandleFunc("/wallet/interactions/presentation", srv.evaluateWalletPresentation).Methods(http.MethodPost) + router.HandleFunc("/verifier/policies/policyID/policyVersion/interactions/presentation", srv.evaluateVerifierPresentation).Methods(http.MethodPost) return srv } @@ -33,12 +36,27 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { s.router.ServeHTTP(w, r) } -func (s *server) evaluatePolicies(w http.ResponseWriter, r *http.Request) { - var request map[string]interface{} +func (s *server) evaluateVerifierPresentation(w http.ResponseWriter, r *http.Request) { + var request VerifierPresentationValidationConfig err := json.NewDecoder(r.Body).Decode(&request) if err != nil { - log.Printf("failed to decode evaluate request: %s", err.Error()) + s.writeResponse( + w, http.StatusBadRequest, fmt.Sprintf("failed to decode evaluate request: %s", err.Error())) + + return + } + + if len(request.AttestationVC) < 1 { + s.writeResponse( + w, http.StatusBadRequest, "at least one attestation vc should be supplied") + + return + } + + if len(request.RequestedVCMetadata) < 1 { + s.writeResponse( + w, http.StatusBadRequest, "at least one requested vc metadata should be supplied") return } @@ -57,3 +75,56 @@ func (s *server) evaluatePolicies(w http.ResponseWriter, r *http.Request) { log.Printf("failed to write response: %s", err.Error()) } } + +func (s *server) evaluateWalletPresentation(w http.ResponseWriter, r *http.Request) { + var request WalletPresentationValidationConfig + + err := json.NewDecoder(r.Body).Decode(&request) + if err != nil { + s.writeResponse( + w, http.StatusBadRequest, fmt.Sprintf("failed to decode evaluate request: %s", err.Error())) + + return + } + + if len(request.VerifierDID) < 1 { + s.writeResponse( + w, http.StatusBadRequest, "verifier did is not supplied") + + return + } + + if len(request.RequestedVCMetadata) < 1 { + s.writeResponse( + w, http.StatusBadRequest, "at least one requested vc metadata should be supplied") + + return + } + + log.Printf("handling request: %s with payload %v", r.URL.String(), request) + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + + claims := map[string]interface{}{ + "allowed": true, + } + + err = json.NewEncoder(w).Encode(claims) + if err != nil { + log.Printf("failed to write response: %s", err.Error()) + } +} + +// writeResponse writes interface value to response +func (s *server) writeResponse( + rw http.ResponseWriter, + status int, + msg string, +) { + log.Printf("[%d] %s", status, msg) + + rw.WriteHeader(status) + + _, _ = rw.Write([]byte(msg)) +}