diff --git a/pkg/service/oidc4ci/composer.go b/pkg/service/oidc4ci/composer.go index 9c0d697de..835c0b1cb 100644 --- a/pkg/service/oidc4ci/composer.go +++ b/pkg/service/oidc4ci/composer.go @@ -12,6 +12,7 @@ import ( "text/template" "github.com/google/uuid" + util "github.com/trustbloc/did-go/doc/util/time" "github.com/trustbloc/vc-go/verifiable" ) @@ -34,7 +35,10 @@ func (c *CredentialComposer) Compose( } if idTemplate := txCredentialConfiguration.CredentialComposeConfiguration.IDTemplate; idTemplate != "" { - id, err := c.renderRaw(idTemplate, c.baseParams(tx)) + params := c.baseParams(tx) + params["CredentialID"] = credential.Contents().ID + + id, err := c.renderRaw(idTemplate, params) if err != nil { return nil, err } @@ -43,7 +47,14 @@ func (c *CredentialComposer) Compose( } if txCredentialConfiguration.CredentialComposeConfiguration.OverrideIssuer { - credential = credential.WithModifiedIssuer(&verifiable.Issuer{ID: tx.DID}) + issuer := credential.Contents().Issuer + if issuer == nil { + issuer = &verifiable.Issuer{} + } + + issuer.ID = tx.DID + + credential = credential.WithModifiedIssuer(issuer) } if txCredentialConfiguration.CredentialComposeConfiguration.OverrideSubjectDID { @@ -57,6 +68,10 @@ func (c *CredentialComposer) Compose( credential = credential.WithModifiedSubject(newSubjects) } + if credential.Contents().Expired == nil && txCredentialConfiguration.CredentialExpiresAt != nil { + credential.SetCustomField("expirationDate", util.NewTime(*txCredentialConfiguration.CredentialExpiresAt)) + } + return credential, nil } diff --git a/pkg/service/oidc4ci/composer_test.go b/pkg/service/oidc4ci/composer_test.go index 343ddcddf..d59abcb38 100644 --- a/pkg/service/oidc4ci/composer_test.go +++ b/pkg/service/oidc4ci/composer_test.go @@ -3,8 +3,11 @@ package oidc4ci_test import ( "context" "testing" + "time" + "github.com/samber/lo" "github.com/stretchr/testify/assert" + util "github.com/trustbloc/did-go/doc/util/time" "github.com/trustbloc/vc-go/verifiable" "github.com/trustbloc/vcs/pkg/service/oidc4ci" @@ -15,10 +18,16 @@ func TestComposer(t *testing.T) { srv := oidc4ci.NewCredentialComposer() cred, err := verifiable.CreateCredential(verifiable.CredentialContents{ + Types: []string{"VerifiableCredential"}, + Context: []string{ + "https://www.w3.org/2018/credentials/v1", + }, Subject: []verifiable.Subject{{ID: "xxx:yyy"}}, }, verifiable.CustomFields{}) assert.NoError(t, err) + expectedExpiration := time.Now().UTC() + resp, err := srv.Compose( context.TODO(), cred, @@ -34,6 +43,7 @@ func TestComposer(t *testing.T) { OverrideIssuer: true, OverrideSubjectDID: true, }, + CredentialExpiresAt: &expectedExpiration, }, &oidc4ci.PrepareCredentialRequest{ DID: "some-awesome-did", @@ -43,9 +53,69 @@ func TestComposer(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) + credJSON, err := resp.MarshalAsJSONLD() + assert.NoError(t, err) + + parsedCred, err := verifiable.ParseCredential(credJSON, + verifiable.WithCredDisableValidation(), + verifiable.WithDisabledProofCheck(), + ) + assert.NoError(t, err) + assert.EqualValues(t, "hardcoded:some-awesome-id:suffix", resp.Contents().ID) assert.EqualValues(t, "did:example:123", resp.Contents().Issuer.ID) assert.EqualValues(t, "some-awesome-did", resp.Contents().Subject[0].ID) + assert.EqualValues(t, expectedExpiration, parsedCred.Contents().Expired.Time) + }) + + t.Run("success with prev-id", func(t *testing.T) { + srv := oidc4ci.NewCredentialComposer() + + cred, err := verifiable.CreateCredential(verifiable.CredentialContents{ + ID: "some-id", + Expired: util.NewTime(time.Now()), + Issuer: &verifiable.Issuer{ + ID: "did:example:123", + CustomFields: map[string]interface{}{ + "key": "value", + "name": "issuer", + }, + }, + Subject: []verifiable.Subject{{ID: "xxx:yyy"}}, + }, verifiable.CustomFields{}) + assert.NoError(t, err) + + resp, err := srv.Compose( + context.TODO(), + cred, + &oidc4ci.Transaction{ + ID: "some-awesome-id", + TransactionData: oidc4ci.TransactionData{ + DID: "did:example:123", + }, + }, + &oidc4ci.TxCredentialConfiguration{ + CredentialComposeConfiguration: &oidc4ci.CredentialComposeConfiguration{ + IDTemplate: "{{.CredentialID}}:suffix", + OverrideIssuer: true, + OverrideSubjectDID: true, + }, + CredentialExpiresAt: lo.ToPtr(time.Now()), + }, + &oidc4ci.PrepareCredentialRequest{ + DID: "some-awesome-did", + }, + ) + + assert.NoError(t, err) + assert.NotNil(t, resp) + + assert.EqualValues(t, "some-id:suffix", resp.Contents().ID) + assert.EqualValues(t, "did:example:123", resp.Contents().Issuer.ID) + assert.EqualValues(t, "value", resp.Contents().Issuer.CustomFields["key"]) + assert.EqualValues(t, "issuer", resp.Contents().Issuer.CustomFields["name"]) + + assert.EqualValues(t, "some-awesome-did", resp.Contents().Subject[0].ID) }) t.Run("invalid template", func(t *testing.T) {