Skip to content

Commit a0d8ad3

Browse files
authored
Merge pull request #113 from Sphereon-Opensource/feature/CWALL-174_impl-draft13_fixes_v11support
Feature/cwall 174 impl draft13 fixes v11support
2 parents 41e0485 + 036ec45 commit a0d8ad3

87 files changed

Lines changed: 6784 additions & 1048 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"packages": ["packages/*"],
3-
"version": "0.10.3",
3+
"version": "0.11.0",
44
"npmClient": "pnpm",
55
"command": {
66
"publish": {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sphereon/oid4vci-workspace",
3-
"version": "0.5.0",
3+
"version": "0.11.0",
44
"description": "OpenID for Verifiable Credential Issuance workspace",
55
"author": "Sphereon",
66
"license": "Apache-2.0",

packages/callback-example/lib/IssuerCallback.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020
33
import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020'
44
import { securityLoader } from '@digitalcredentials/security-document-loader'
55
import vc from '@digitalcredentials/vc'
6-
import { CredentialRequestV1_0_11 } from '@sphereon/oid4vci-common'
6+
import { CredentialRequest, CredentialRequestV1_0_11 } from '@sphereon/oid4vci-common'
77
import { CredentialIssuanceInput } from '@sphereon/oid4vci-issuer'
88
import { CompactSdJwtVc, W3CVerifiableCredential } from '@sphereon/ssi-types'
99

@@ -15,7 +15,7 @@ export const generateDid = async () => {
1515
}
1616

1717
// eslint-disable-next-line @typescript-eslint/no-explicit-any
18-
export const getIssuerCallback = (credential: CredentialIssuanceInput, keyPair: any, verificationMethod: string) => {
18+
export const getIssuerCallbackV1_0_11 = (credential: CredentialIssuanceInput, keyPair: any, verificationMethod: string) => {
1919
if (!credential) {
2020
throw new Error('A credential needs to be provided')
2121
}
@@ -33,6 +33,32 @@ export const getIssuerCallback = (credential: CredentialIssuanceInput, keyPair:
3333
return await vc.issue({ credential, suite, documentLoader })
3434
}
3535
}
36+
37+
export const getIssuerCallbackV1_0_13 = (
38+
credential: CredentialIssuanceInput,
39+
credentialRequest: CredentialRequest,
40+
keyPair: any,
41+
verificationMethod: string,
42+
) => {
43+
if (!credential) {
44+
throw new Error('A credential needs to be provided')
45+
}
46+
47+
return async (_opts: {
48+
credentialRequest: CredentialRequest
49+
credential: CredentialIssuanceInput
50+
format?: string
51+
jwtVerifyResult: any // Adjust type if necessary
52+
}): Promise<W3CVerifiableCredential | CompactSdJwtVc> => {
53+
const documentLoader = securityLoader().build()
54+
const verificationKey: any = Array.from(keyPair.values())[0]
55+
const keys = await Ed25519VerificationKey2020.from({ ...verificationKey })
56+
const suite = new Ed25519Signature2020({ key: keys })
57+
suite.verificationMethod = verificationMethod
58+
return await vc.issue({ credential, suite, documentLoader })
59+
}
60+
}
61+
3662
// eslint-disable-next-line @typescript-eslint/no-explicit-any
3763
export const verifyCredential = async (credential: W3CVerifiableCredential, keyPair: any, verificationMethod: string): Promise<any> => {
3864
const documentLoader = securityLoader().build()

packages/callback-example/lib/__tests__/issuerCallback.spec.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { CredentialRequestClient, CredentialRequestClientBuilder, ProofOfPossess
44
import {
55
Alg,
66
CNonceState,
7-
CredentialSupported,
7+
CredentialConfigurationSupportedV1_0_13,
8+
CredentialIssuerMetadataV1_0_13,
9+
CredentialRequest,
810
IssuerCredentialSubjectDisplay,
911
IssueStatus,
1012
Jwt,
@@ -13,18 +15,18 @@ import {
1315
ProofOfPossession,
1416
} from '@sphereon/oid4vci-common'
1517
import { CredentialOfferSession } from '@sphereon/oid4vci-common/dist'
16-
import { CredentialSupportedBuilderV1_11, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
18+
import { CredentialSupportedBuilderV1_13, VcIssuer, VcIssuerBuilder } from '@sphereon/oid4vci-issuer'
1719
import { MemoryStates } from '@sphereon/oid4vci-issuer'
1820
import { CredentialDataSupplierResult } from '@sphereon/oid4vci-issuer/dist/types'
1921
import { ICredential, IProofPurpose, IProofType, W3CVerifiableCredential } from '@sphereon/ssi-types'
2022
import { DIDDocument } from 'did-resolver'
2123
import * as jose from 'jose'
2224
import { v4 } from 'uuid'
2325

24-
import { generateDid, getIssuerCallback, verifyCredential } from '../IssuerCallback'
26+
import { generateDid, getIssuerCallbackV1_0_11, getIssuerCallbackV1_0_13, verifyCredential } from '../IssuerCallback'
2527

2628
const INITIATION_TEST_URI =
27-
'openid-initiate-issuance://?credential_type=OpenBadgeCredential&issuer=https%3A%2F%2Fjff%2Ewalt%2Eid%2Fissuer-api%2Foidc%2F&pre-authorized_code=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhOTUyZjUxNi1jYWVmLTQ4YjMtODIxYy00OTRkYzgyNjljZjAiLCJwcmUtYXV0aG9yaXplZCI6dHJ1ZX0.YE5DlalcLC2ChGEg47CQDaN1gTxbaQqSclIVqsSAUHE&user_pin_required=false'
29+
'openid-credential-offer://?credential_offer=%7B%22credential_issuer%22:%22https://credential-issuer.example.com%22,%22credential_configuration_ids%22:%5B%22UniversityDegreeCredential%22%5D,%22grants%22:%7B%22urn:ietf:params:oauth:grant-type:pre-authorized_code%22:%7B%22pre-authorized_code%22:%22oaKazRN8I0IbtZ0C7JuMn5%22,%22tx_code%22:%7B%22input_mode%22:%22text%22,%22description%22:%22Please%20enter%20the%20serial%20number%20of%20your%20physical%20drivers%20license%22%7D%7D%7D%7D'
2830
const IDENTIPROOF_ISSUER_URL = 'https://example.com/credential'
2931
const kid = 'did:example:ebfeb1f712ebc6f1c276e12ec21#keys-1'
3032
let keypair: KeyPair // Proof of Possession JWT
@@ -86,12 +88,14 @@ describe('issuerCallback', () => {
8688
const clientId = 'sphereon:wallet'
8789

8890
beforeAll(async () => {
89-
const credentialsSupported: CredentialSupported = new CredentialSupportedBuilderV1_11()
90-
.withCryptographicSuitesSupported('ES256K')
91+
const credentialsSupported: Record<string, CredentialConfigurationSupportedV1_0_13> = new CredentialSupportedBuilderV1_13()
92+
.withCredentialSigningAlgValuesSupported('ES256K')
9193
.withCryptographicBindingMethod('did')
9294
.withFormat('jwt_vc_json')
93-
.withTypes('VerifiableCredential')
94-
.withId('UniversityDegree_JWT')
95+
.withCredentialName('UniversityDegree_JWT')
96+
.withCredentialDefinition({
97+
type: ['VerifiableCredential', 'UniversityDegree_JWT'],
98+
})
9599
.withCredentialSupportedDisplay({
96100
name: 'University Credential',
97101
locale: 'en-US',
@@ -143,14 +147,14 @@ describe('issuerCallback', () => {
143147
const nonces = new MemoryStates<CNonceState>()
144148
await nonces.set('test_value', { cNonce: 'test_value', createdAt: +new Date(), issuerState: 'existing-state' })
145149
vcIssuer = new VcIssuerBuilder<DIDDocument>()
146-
.withAuthorizationServer('https://authorization-server')
150+
.withAuthorizationServers('https://authorization-server')
147151
.withCredentialEndpoint('https://credential-endpoint')
148152
.withCredentialIssuer(IDENTIPROOF_ISSUER_URL)
149153
.withIssuerDisplay({
150154
name: 'example issuer',
151155
locale: 'en-US',
152156
})
153-
.withCredentialsSupported(credentialsSupported)
157+
.withCredentialConfigurationsSupported(credentialsSupported)
154158
.withCredentialOfferStateManager(stateManager)
155159
.withCNonceStateManager(nonces)
156160
.withJWTVerifyCallback(verifyCallbackFunction)
@@ -194,7 +198,7 @@ describe('issuerCallback', () => {
194198
credentialSubject: {},
195199
issuanceDate: new Date().toISOString(),
196200
}
197-
const vc = await getIssuerCallback(credential, didKey.keyPairs, didKey.didDocument.verificationMethod[0].id)({})
201+
const vc = await getIssuerCallbackV1_0_11(credential, didKey.keyPairs, didKey.didDocument.verificationMethod[0].id)({})
198202
expect(vc).toEqual({
199203
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://w3id.org/security/suites/ed25519-2020/v1'],
200204
credentialSubject: {},
@@ -213,11 +217,15 @@ describe('issuerCallback', () => {
213217
expect.objectContaining({ verified: true }),
214218
)
215219
})
220+
216221
it('Should pass requesting a verifiable credential using the client', async () => {
217222
const credReqClient = (await CredentialRequestClientBuilder.fromURI({ uri: INITIATION_TEST_URI }))
218223
.withCredentialEndpoint('https://oidc4vci.demo.spruceid.com/credential')
224+
.withCredentialEndpointFromMetadata({
225+
credential_configurations_supported: { VeriCred: { format: 'jwt_vc_json' } },
226+
} as unknown as CredentialIssuerMetadataV1_0_13)
219227
.withFormat('jwt_vc_json')
220-
.withCredentialType('credentialType')
228+
.withCredentialIdentifier('VeriCred')
221229
.withToken('token')
222230

223231
const jwt: Jwt = {
@@ -238,33 +246,34 @@ describe('issuerCallback', () => {
238246
callbacks: {
239247
signCallback: proofOfPossessionCallbackFunction,
240248
},
241-
version: OpenId4VCIVersion.VER_1_0_11,
249+
version: OpenId4VCIVersion.VER_1_0_13,
242250
})
243251
.withClientId(clientId)
244252
.withKid(kid)
245253
.build()
246254

247255
const credentialRequestClient = new CredentialRequestClient(credReqClient)
248-
const credentialRequest = await credentialRequestClient.createCredentialRequest({
249-
credentialTypes: ['VerifiableCredential'],
250-
format: 'jwt_vc_json',
256+
const credentialRequest: CredentialRequest = await credentialRequestClient.createCredentialRequest({
257+
credentialIdentifier: 'VerifiableCredential',
258+
// format: 'jwt_vc_json',
251259
proofInput: proof,
252-
version: OpenId4VCIVersion.VER_1_0_11,
260+
version: OpenId4VCIVersion.VER_1_0_13,
253261
})
262+
254263
expect(credentialRequest).toEqual({
255-
format: 'jwt_vc_json',
264+
// format: 'jwt_vc_json',
256265
proof: {
257266
jwt: expect.stringContaining('eyJhbGciOiJFUzI1NiIsImtpZCI6ImRpZDpleGFtcGxlOmViZmViMWY3MTJlYmM2ZjFj'),
258267
proof_type: 'jwt',
259268
},
260-
types: ['VerifiableCredential'],
269+
credential_identifier: 'VerifiableCredential',
261270
})
262271

263272
const credentialResponse = await vcIssuer.issueCredential({
264273
credentialRequest: credentialRequest,
265274
credential,
266275
responseCNonce: state,
267-
credentialSignerCallback: getIssuerCallback(credential, didKey.keyPairs, didKey.didDocument.verificationMethod[0].id),
276+
credentialSignerCallback: getIssuerCallbackV1_0_13(credential, credentialRequest, didKey.keyPairs, didKey.didDocument.verificationMethod[0].id),
268277
})
269278

270279
expect(credentialResponse).toEqual({
@@ -287,7 +296,7 @@ describe('issuerCallback', () => {
287296
},
288297
type: ['VerifiableCredential'],
289298
},
290-
format: 'jwt_vc_json',
299+
// format: 'jwt_vc_json',
291300
})
292301

293302
await expect(
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { getIssuerCallback, generateDid, verifyCredential } from './IssuerCallback'
1+
export { getIssuerCallbackV1_0_11, generateDid, verifyCredential } from './IssuerCallback'

packages/callback-example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@sphereon/oid4vci-callback-example",
3-
"version": "0.10.3",
3+
"version": "0.11.0",
44
"description": "OpenID 4 Verifiable Credential Issuance issuer callback example",
55
"source": "lib/index.ts",
66
"main": "dist/index.js",

packages/client/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Release with support for the pre-authorized code flow only!
166166
- Documentation updates/fixes
167167

168168
- Fixes:
169-
- The acquireCredential in the OpenID4VCIClient was not using the access token, resulting in auth issues.
169+
- The acquireCredential in the OpenID4VCIClientV1_0_13 was not using the access token, resulting in auth issues.
170170

171171
## v0.3.1 - 2022-11-20
172172

packages/client/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ This initiates the client using a URI obtained from the Issuer using a link (URL
5252
already fetching the Server Metadata
5353

5454
```typescript
55-
import { OpenID4VCIClient } from '@sphereon/oid4vci-client';
55+
import { OpenID4VCIClientV1_0_13 } from '@sphereon/oid4vci-client';
5656

5757
// The client is initiated from a URI. This URI is provided by the Issuer, typically as a URL or QR code.
58-
const client = await OpenID4VCIClient.fromURI({
58+
const client = await OpenID4VCIClientV1_0_13.fromURI({
5959
uri: 'openid-initiate-issuance://?issuer=https%3A%2F%2Fissuer.research.identiproof.io&credential_type=OpenBadgeCredentialUrl&pre-authorized_code=4jLs9xZHEfqcoow0kHE7d1a8hUk6Sy-5bVSV2MqBUGUgiFFQi-ImL62T-FmLIo8hKA1UdMPH0lM1xAgcFkJfxIw9L-lI3mVs0hRT8YVwsEM1ma6N3wzuCdwtMU4bcwKp&user_pin_required=true',
6060
kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21#key-1', // Our DID. You can defer this also to when the acquireCredential method is called
6161
alg: Alg.ES256, // The signing Algorithm we will use. You can defer this also to when the acquireCredential method is called
@@ -71,10 +71,10 @@ console.log(client.getAccessTokenEndpoint()); // https://auth.research.identipro
7171
Using https scheme
7272

7373
```typescript
74-
import { OpenID4VCIClient } from '@sphereon/oid4vci-client';
74+
import { OpenID4VCIClientV1_0_13 } from '@sphereon/oid4vci-client';
7575

7676
// The client is initiated from a URI. This URI is provided by the Issuer, typically as a URL or QR code.
77-
const client = await OpenID4VCIClient.fromURI({
77+
const client = await OpenID4VCIClientV1_0_13.fromURI({
7878
uri: 'https://launchpad.vii.electron.mattrlabs.io?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flaunchpad.vii.electron.mattrlabs.io%22%2C%22credentials%22%3A%5B%7B%22format%22%3A%22ldp_vc%22%2C%22types%22%3A%5B%22OpenBadgeCredential%22%5D%7D%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%22UPZohaodPlLBnGsqB02n2tIupCIg8nKRRUEUHWA665X%22%7D%7D%7D',
7979
kid: 'did:example:ebfeb1f712ebc6f1c276e12ec21#key-1', // Our DID. You can defer this also to when the acquireCredential method is called
8080
alg: Alg.ES256, // The signing Algorithm we will use. You can defer this also to when the acquireCredential method is called
@@ -206,15 +206,15 @@ The OpenID4VCI spec defines a server metadata object that contains information a
206206
support. Next to this predefined endpoint there are also the well-known locations for OpenID Connect Discovery
207207
configuration and
208208
Oauth2 Authorization Server configuration. These contain for instance the token endpoints.
209-
The MetadataClient checks the OpenID4VCI well-known location for the medata and existence of a token endpoint. If the
209+
The MetadataClientV1_0_13 checks the OpenID4VCI well-known location for the medata and existence of a token endpoint. If the
210210
OpenID4VCI well-known location is not found, the OIDC/OAuth2 well-known locations will be tried:
211211

212212
Example:
213213

214214
```typescript
215-
import { MetadataClient } from '@sphereon/oid4vci-client';
215+
import { MetadataClientV1_0_13 } from '@sphereon/oid4vci-client';
216216

217-
const metadata = await MetadataClient.retrieveAllMetadataFromCredentialOffer(initiationRequestWithUrl);
217+
const metadata = await MetadataClientV1_0_13.retrieveAllMetadataFromCredentialOffer(initiationRequestWithUrl);
218218

219219
console.log(metadata);
220220
/**

0 commit comments

Comments
 (0)