Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Credential Status API - update vc status #890

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cmd/vc-rest/startcmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ func buildEchoHandler(conf *Configuration, cmd *cobra.Command) (*echo.Echo, erro
verifierv1.RegisterHandlers(e, verifierController)

didConfigSvc := didconfiguration.New(&didconfiguration.Config{
VerifierProfileService: verifierProfileSvc,
IssuerProfileService: issuerProfileSvc,
IssuerCredentialService: issueCredentialSvc,
KmsRegistry: kmsRegistry,
VerifierProfileService: verifierProfileSvc,
IssuerProfileService: issuerProfileSvc,
Crypto: vcCrypto,
KmsRegistry: kmsRegistry,
})

if conf.StartupParameters.devMode {
Expand Down
20 changes: 16 additions & 4 deletions pkg/doc/vc/crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,20 @@ type Crypto struct {
documentLoader ld.DocumentLoader
}

// SignCredentialLDP adds verifiable.LinkedDataProofContext to the vc.
func (c *Crypto) SignCredentialLDP(
func (c *Crypto) SignCredential(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created a generic method instead of SignCredentialLDP and SignCredentialJWT

signerData *vc.Signer, vc *verifiable.Credential, opts ...SigningOpts) (*verifiable.Credential, error) {
switch signerData.Format {
case vcsverifiable.Jwt:
return c.signCredentialJWT(signerData, vc, opts...)
case vcsverifiable.Ldp:
return c.signCredentialLDP(signerData, vc, opts...)
default:
return nil, fmt.Errorf("unknown signature format %s", signerData.Format)
}
}

// signCredentialLDP adds verifiable.LinkedDataProofContext to the VC.
func (c *Crypto) signCredentialLDP(
signerData *vc.Signer, vc *verifiable.Credential, opts ...SigningOpts) (*verifiable.Credential, error) {
signOpts := &signingOpts{}
// apply opts
Expand All @@ -178,8 +190,8 @@ func (c *Crypto) SignCredentialLDP(
return vc, nil
}

// SignCredentialJWT returns vc in JWT format including the signature section.
func (c *Crypto) SignCredentialJWT(
// signCredentialJWT returns vc in JWT format including the signature section.
func (c *Crypto) signCredentialJWT(
signerData *vc.Signer, vc *verifiable.Credential, opts ...SigningOpts) (*verifiable.Credential, error) {
signOpts := &signingOpts{}
// apply opts
Expand Down
18 changes: 9 additions & 9 deletions pkg/doc/vc/crypto/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit
testutil.DocumentLoader(t),
)

signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
getTestSigner(), &verifiable.Credential{ID: "http://example.edu/credentials/1872"})
require.NoError(t, err)
require.Equal(t, 1, len(signedVC.Proofs))
Expand Down Expand Up @@ -181,7 +181,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit
vcSigner = tc.vcSigner
}

signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
vcSigner, &verifiable.Credential{ID: "http://example.edu/credentials/1872"},
tc.signingOpts...)

Expand Down Expand Up @@ -227,7 +227,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit
)
p := getTestSigner()
p.Creator = "wrongValue"
signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"})
require.Error(t, err)
require.Contains(t, err.Error(), "verificationMethod value wrongValue should be in did#keyID format")
Expand All @@ -239,7 +239,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit
&vdrmock.MockVDRegistry{ResolveValue: createDIDDoc("did:trustbloc:abc")},
testutil.DocumentLoader(t),
)
signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
getTestSignerWithCrypto(
&cryptomock.Crypto{SignErr: fmt.Errorf("failed to sign")}),
&verifiable.Credential{ID: "http://example.edu/credentials/1872"})
Expand All @@ -254,7 +254,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit

p := getTestSigner()

signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"},
WithPurpose("invalid"))
require.Error(t, err)
Expand All @@ -268,7 +268,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit

p := getTestSigner()

signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"},
WithPurpose(CapabilityInvocation))
require.NoError(t, err)
Expand All @@ -281,7 +281,7 @@ func TestCrypto_SignCredentialLDP(t *testing.T) { //nolint:gocognit

p := getTestSigner()

signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
p, &verifiable.Credential{ID: "http://example.edu/credentials/1872"},
WithPurpose(CapabilityInvocation))
require.NoError(t, err)
Expand All @@ -296,7 +296,7 @@ func TestCrypto_SignCredentialBBS(t *testing.T) {
testutil.DocumentLoader(t),
)

signedVC, err := c.SignCredentialLDP(
signedVC, err := c.signCredentialLDP(
&vc.Signer{
DID: "did:trustbloc:abc",
SignatureType: "BbsBlsSignature2020",
Expand Down Expand Up @@ -683,7 +683,7 @@ func TestCrypto_SignCredentialJWT(t *testing.T) {
vdr: tt.fields.getVDR(),
documentLoader: testutil.DocumentLoader(t),
}
got, err := c.SignCredentialJWT(tt.args.signerData, tt.args.getVC(), tt.args.opts...)
got, err := c.signCredentialJWT(tt.args.signerData, tt.args.getVC(), tt.args.opts...)
if (err != nil) != tt.wantErr {
t.Errorf("SignCredentialJWT() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
1 change: 1 addition & 0 deletions pkg/doc/vc/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Signer struct {
Creator string
SignatureType vcsverifiable.SignatureType
KeyType kms.KeyType
Format vcsverifiable.Format // VC format - LDP/JWT.
SignatureRepresentation verifiable.SignatureRepresentation // For LDP only.
KMS keyManager
}
52 changes: 52 additions & 0 deletions pkg/restapi/v1/issuer/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"time"

Expand Down Expand Up @@ -69,6 +70,7 @@ type oidc4VCService interface {
type vcStatusManager interface {
GetRevocationListVC(id string) (*verifiable.Credential, error)
GetCredentialStatusURL(issuerProfileURL, issuerProfileID, statusID string) (string, error)
UpdateVCStatus(signer *vc.Signer, profileName, CredentialID, status string) error
}

type Config struct {
Expand Down Expand Up @@ -324,5 +326,55 @@ func (c *Controller) GetCredentialsStatus(ctx echo.Context, profileID string, st
// PostCredentialsStatus updates credential status.
// POST /issuer/profiles/{profileID}/credentials/status.
func (c *Controller) PostCredentialsStatus(ctx echo.Context, profileID string) error {
var body UpdateCredentialStatusRequest

if err := util.ReadBody(ctx, &body); err != nil {
return err
}

if err := c.updateCredentialStatus(ctx, &body, profileID); err != nil {
return err
}

return ctx.NoContent(http.StatusOK)
}

func (c *Controller) updateCredentialStatus(ctx echo.Context, body *UpdateCredentialStatusRequest,
profileID string) error {
oidcOrgID, err := util.GetOrgIDFromOIDC(ctx)
if err != nil {
return err
}

profile, err := c.accessOIDCProfile(profileID, oidcOrgID)
if err != nil {
return err
}

keyManager, err := c.kmsRegistry.GetKeyManager(profile.KMSConfig)
if err != nil {
return fmt.Errorf("failed to get kms: %w", err)
}

if body.CredentialStatus.Type != credentialstatus.StatusList2021Entry {
return resterr.NewValidationError(resterr.InvalidValue, "CredentialStatus.Type",
fmt.Errorf("credential status %s not supported", body.CredentialStatus.Type))
}

signer := &vc.Signer{
Format: profile.VCConfig.Format,
DID: profile.SigningDID.DID,
Creator: profile.SigningDID.Creator,
SignatureType: profile.VCConfig.SigningAlgorithm,
KeyType: profile.VCConfig.KeyType,
KMS: keyManager,
SignatureRepresentation: profile.VCConfig.SignatureRepresentation,
}

err = c.vcStatusManager.UpdateVCStatus(signer, profile.Name, body.CredentialID, body.CredentialStatus.Status)
if err != nil {
return resterr.NewSystemError("VCStatusManager", "UpdateVCStatus", err)
}

return nil
}
Loading