diff --git a/component/wallet-cli/README.md b/component/wallet-cli/README.md index 00071222b..0c2b91081 100644 --- a/component/wallet-cli/README.md +++ b/component/wallet-cli/README.md @@ -67,6 +67,7 @@ with the key type ED25519 (EdDSA signature type). To add attestation VC to the Wallet, use the `attest` command. The following CLI arguments are supported: ```bash --attestation-url string attestation url, i.e. https:///vcs/wallet/attestation + --attestation-type string attestation type, i.e. urn:attestation:application:my_wallet --context-provider-url string json-ld context provider url -h, --help help for attest --leveldb-path string leveldb path @@ -76,7 +77,7 @@ To add attestation VC to the Wallet, use the `attest` command. The following CLI Example: ```bash -./wallet-cli attest --leveldb-path "/mnt/wallet.db" --attestation-url "https:///vcs/wallet/attestation" +./wallet-cli attest --leveldb-path "/mnt/wallet.db" --attestation-url "https:///vcs/wallet/attestation" --attestation-type "urn:attestation:application:my_wallet" ``` ### Receiving Verifiable Credential using OIDC4VCI exchange protocol diff --git a/component/wallet-cli/cmd/attest_wallet_cmd.go b/component/wallet-cli/cmd/attest_wallet_cmd.go index 9c882af88..d0b8f0fe8 100644 --- a/component/wallet-cli/cmd/attest_wallet_cmd.go +++ b/component/wallet-cli/cmd/attest_wallet_cmd.go @@ -21,9 +21,10 @@ import ( ) type attestCommandFlags struct { - walletFlags *walletFlags - walletDIDIndex int - attestationURL string + walletFlags *walletFlags + walletDIDIndex int + attestationURL string + attestationType string } func NewAttestWalletCommand() *cobra.Command { @@ -44,6 +45,10 @@ func NewAttestWalletCommand() *cobra.Command { return fmt.Errorf("attestation-url is required") } + if flags.attestationType == "" { + return fmt.Errorf("attestation-type is required") + } + httpClient := &http.Client{ Transport: &http.Transport{ TLSClientConfig: svc.TLSConfig(), @@ -65,7 +70,9 @@ func NewAttestWalletCommand() *cobra.Command { return fmt.Errorf("create attestation service: %w", err) } - if _, err = attestationService.GetAttestation(context.Background(), "", ""); err != nil { + if _, err = attestationService.GetAttestation(context.Background(), attestation.GetAttestationRequest{ + AttestationType: flags.attestationType, + }); err != nil { return fmt.Errorf("get attestation: %w", err) } @@ -77,6 +84,7 @@ func NewAttestWalletCommand() *cobra.Command { cmd.Flags().StringVar(&flags.walletFlags.mongoDBConnectionString, "mongodb-connection-string", "", "mongodb connection string") cmd.Flags().StringVar(&flags.walletFlags.contextProviderURL, "context-provider-url", "", "json-ld context provider url") cmd.Flags().StringVar(&flags.attestationURL, "attestation-url", "", "attestation url, i.e. https:///vcs/wallet/attestation") + cmd.Flags().StringVar(&flags.attestationType, "attestation-type", "", "attestation-type, i.e. urn:attestation:application:my_wallet") cmd.Flags().IntVar(&flags.walletDIDIndex, "wallet-did-index", -1, "index of wallet did, if not set the most recently created DID is used") return cmd diff --git a/component/wallet-cli/pkg/attestation/attestation_service.go b/component/wallet-cli/pkg/attestation/attestation_service.go index 53fbb67b6..f29020283 100644 --- a/component/wallet-cli/pkg/attestation/attestation_service.go +++ b/component/wallet-cli/pkg/attestation/attestation_service.go @@ -102,11 +102,11 @@ func NewService( }, nil } -func (s *Service) GetAttestation(ctx context.Context, audience, nonce string) (string, error) { +func (s *Service) GetAttestation(ctx context.Context, req GetAttestationRequest) (string, error) { b, err := s.store.Get(attestationVCKey) if err != nil { if errors.Is(err, storageapi.ErrDataNotFound) { - b, err = s.requestAttestationVC(ctx) + b, err = s.requestAttestationVC(ctx, req) if err != nil { return "", fmt.Errorf("request attestation vc: %w", err) } @@ -135,16 +135,16 @@ func (s *Service) GetAttestation(ctx context.Context, audience, nonce string) (s attestationVP.ID = uuid.New().String() - if nonce != "" { + if req.Nonce != "" { attestationVP.CustomFields = map[string]interface{}{ - "nonce": nonce, + "nonce": req.Nonce, } } var aud []string - if audience != "" { - aud = []string{audience} + if req.Audience != "" { + aud = []string{req.Audience} } claims, err := attestationVP.JWTClaims(aud, false) @@ -169,8 +169,8 @@ func (s *Service) GetAttestation(ctx context.Context, audience, nonce string) (s return jws, nil } -func (s *Service) requestAttestationVC(ctx context.Context) ([]byte, error) { - initResponse, err := s.attestationInit(ctx) +func (s *Service) requestAttestationVC(ctx context.Context, req GetAttestationRequest) ([]byte, error) { + initResponse, err := s.attestationInit(ctx, req) if err != nil { return nil, fmt.Errorf("attestation init: %w", err) } @@ -183,11 +183,15 @@ func (s *Service) requestAttestationVC(ctx context.Context) ([]byte, error) { return []byte(completeResponse.WalletAttestationVC), nil } -func (s *Service) attestationInit(ctx context.Context) (*AttestWalletInitResponse, error) { +func (s *Service) attestationInit( + ctx context.Context, + attestReq GetAttestationRequest, +) (*AttestWalletInitResponse, error) { logger.Debug("attestation init started", zap.String("walletDID", s.walletDID)) req := &AttestWalletInitRequest{ Payload: map[string]interface{}{ + "type": attestReq.AttestationType, "application": map[string]interface{}{ "type": s.wallet.WalletType(), "name": s.wallet.Name(), diff --git a/component/wallet-cli/pkg/attestation/models.go b/component/wallet-cli/pkg/attestation/models.go index f6aa7eb6a..b5f8048e5 100644 --- a/component/wallet-cli/pkg/attestation/models.go +++ b/component/wallet-cli/pkg/attestation/models.go @@ -37,3 +37,9 @@ type JwtProofClaims struct { type AttestWalletCompleteResponse struct { WalletAttestationVC string `json:"wallet_attestation_vc"` } + +type GetAttestationRequest struct { + Audience string + Nonce string + AttestationType string +} diff --git a/component/wallet-cli/pkg/oidc4vci/oidc4vci_flow.go b/component/wallet-cli/pkg/oidc4vci/oidc4vci_flow.go index 202faa271..a06694b6a 100644 --- a/component/wallet-cli/pkg/oidc4vci/oidc4vci_flow.go +++ b/component/wallet-cli/pkg/oidc4vci/oidc4vci_flow.go @@ -37,6 +37,7 @@ import ( "github.com/trustbloc/vc-go/verifiable" "golang.org/x/oauth2" + "github.com/trustbloc/vcs/component/wallet-cli/pkg/attestation" "github.com/trustbloc/vcs/component/wallet-cli/pkg/consent" "github.com/trustbloc/vcs/component/wallet-cli/pkg/credentialoffer" jwssigner "github.com/trustbloc/vcs/component/wallet-cli/pkg/signer" @@ -68,7 +69,7 @@ const ( ) type AttestationService interface { - GetAttestation(ctx context.Context, audience, nonce string) (string, error) + GetAttestation(ctx context.Context, request attestation.GetAttestationRequest) (string, error) } type TrustRegistry interface { @@ -379,7 +380,10 @@ func (f *Flow) Run(ctx context.Context) ([]*verifiable.Credential, error) { if attestationRequired { var jwtVP string - jwtVP, err = f.attestationService.GetAttestation(ctx, issuerDID, preAuthorizationGrant.PreAuthorizedCode) + jwtVP, err = f.attestationService.GetAttestation(ctx, attestation.GetAttestationRequest{ + Audience: issuerDID, + Nonce: preAuthorizationGrant.PreAuthorizedCode, + }) if err != nil { return nil, fmt.Errorf("get attestation: %w", err) } diff --git a/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go b/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go index c007b01a6..5edd4fd70 100644 --- a/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go +++ b/component/wallet-cli/pkg/oidc4vp/oidc4vp_flow.go @@ -34,6 +34,7 @@ import ( "github.com/trustbloc/vc-go/verifiable" "github.com/trustbloc/vc-go/vermethod" + "github.com/trustbloc/vcs/component/wallet-cli/pkg/attestation" jwssigner "github.com/trustbloc/vcs/component/wallet-cli/pkg/signer" "github.com/trustbloc/vcs/component/wallet-cli/pkg/wallet" "github.com/trustbloc/vcs/pkg/doc/vc" @@ -54,7 +55,7 @@ const ( ) type AttestationService interface { - GetAttestation(ctx context.Context, audience, nonce string) (string, error) + GetAttestation(ctx context.Context, req attestation.GetAttestationRequest) (string, error) } type TrustRegistry interface { @@ -620,7 +621,7 @@ func (f *Flow) createIDToken( if attestationRequired { var jwtVP string - jwtVP, err = f.attestationService.GetAttestation(ctx, "", "") + jwtVP, err = f.attestationService.GetAttestation(ctx, attestation.GetAttestationRequest{}) if err != nil { return "", fmt.Errorf("get attestation: %w", err) }