From 57207b9e326e0ae3a83077fd9745972a3a24acc5 Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Wed, 10 Apr 2024 18:51:36 +0200 Subject: [PATCH 1/2] feat: compose issuer --- pkg/service/oidc4ci/composer.go | 14 ++++++- pkg/service/oidc4ci/composer_test.go | 57 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/pkg/service/oidc4ci/composer.go b/pkg/service/oidc4ci/composer.go index 9c0d697de..437bc2413 100644 --- a/pkg/service/oidc4ci/composer.go +++ b/pkg/service/oidc4ci/composer.go @@ -34,7 +34,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 +46,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 { diff --git a/pkg/service/oidc4ci/composer_test.go b/pkg/service/oidc4ci/composer_test.go index 343ddcddf..6175e1a8e 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" @@ -19,6 +22,8 @@ func TestComposer(t *testing.T) { }, verifiable.CustomFields{}) assert.NoError(t, err) + expectedExpiration := time.Now().UTC() + resp, err := srv.Compose( context.TODO(), cred, @@ -34,6 +39,7 @@ func TestComposer(t *testing.T) { OverrideIssuer: true, OverrideSubjectDID: true, }, + CredentialExpiresAt: &expectedExpiration, }, &oidc4ci.PrepareCredentialRequest{ DID: "some-awesome-did", @@ -46,6 +52,57 @@ func TestComposer(t *testing.T) { 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, resp.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) { From 808efa39a7fbe76c996fa05c6d342dc4d9f57cdb Mon Sep 17 00:00:00 2001 From: Stas Dm Date: Wed, 10 Apr 2024 19:04:53 +0200 Subject: [PATCH 2/2] fix: expiration --- pkg/service/oidc4ci/composer.go | 5 +++++ pkg/service/oidc4ci/composer_test.go | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pkg/service/oidc4ci/composer.go b/pkg/service/oidc4ci/composer.go index 437bc2413..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" ) @@ -67,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 6175e1a8e..d59abcb38 100644 --- a/pkg/service/oidc4ci/composer_test.go +++ b/pkg/service/oidc4ci/composer_test.go @@ -18,6 +18,10 @@ 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) @@ -49,10 +53,19 @@ 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, resp.Contents().Expired.Time) + assert.EqualValues(t, expectedExpiration, parsedCred.Contents().Expired.Time) }) t.Run("success with prev-id", func(t *testing.T) {