@sphereon/ssi-sdk.siopv2-oid4vp-op-auth 0.32.1-next.20 → 0.32.1-next.287
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/DidAuthSiopOpAuthenticator.d.ts +8 -3
- package/dist/agent/DidAuthSiopOpAuthenticator.d.ts.map +1 -1
- package/dist/agent/DidAuthSiopOpAuthenticator.js +105 -35
- package/dist/agent/DidAuthSiopOpAuthenticator.js.map +1 -1
- package/dist/services/Siopv2MachineService.d.ts +5 -0
- package/dist/services/Siopv2MachineService.d.ts.map +1 -1
- package/dist/services/Siopv2MachineService.js +112 -14
- package/dist/services/Siopv2MachineService.js.map +1 -1
- package/dist/session/OID4VP.d.ts +4 -4
- package/dist/session/OID4VP.d.ts.map +1 -1
- package/dist/session/OID4VP.js +2 -1
- package/dist/session/OID4VP.js.map +1 -1
- package/dist/session/OpSession.d.ts.map +1 -1
- package/dist/session/OpSession.js +3 -3
- package/dist/session/OpSession.js.map +1 -1
- package/dist/types/IDidAuthSiopOpAuthenticator.d.ts +12 -7
- package/dist/types/IDidAuthSiopOpAuthenticator.d.ts.map +1 -1
- package/dist/types/IDidAuthSiopOpAuthenticator.js.map +1 -1
- package/dist/types/machine/index.d.ts +1 -0
- package/dist/types/machine/index.d.ts.map +1 -1
- package/dist/types/machine/index.js.map +1 -1
- package/dist/types/siop-service/index.d.ts +22 -5
- package/dist/types/siop-service/index.d.ts.map +1 -1
- package/dist/types/siop-service/index.js.map +1 -1
- package/dist/utils/CredentialUtils.d.ts +23 -0
- package/dist/utils/CredentialUtils.d.ts.map +1 -0
- package/dist/utils/CredentialUtils.js +65 -0
- package/dist/utils/CredentialUtils.js.map +1 -0
- package/dist/utils/dcql.d.ts +5 -0
- package/dist/utils/dcql.d.ts.map +1 -0
- package/dist/utils/dcql.js +37 -0
- package/dist/utils/dcql.js.map +1 -0
- package/package.json +26 -23
- package/src/agent/DidAuthSiopOpAuthenticator.ts +132 -49
- package/src/services/Siopv2MachineService.ts +132 -19
- package/src/session/OID4VP.ts +8 -8
- package/src/session/OpSession.ts +7 -5
- package/src/types/IDidAuthSiopOpAuthenticator.ts +21 -7
- package/src/types/machine/index.ts +1 -0
- package/src/types/siop-service/index.ts +25 -5
- package/src/utils/CredentialUtils.ts +71 -0
- package/src/utils/dcql.ts +36 -0
package/src/session/OpSession.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { encodeBase64url } from '@sphereon/ssi-sdk.core'
|
|
|
20
20
|
import {
|
|
21
21
|
CompactSdJwtVc,
|
|
22
22
|
CredentialMapper,
|
|
23
|
-
|
|
23
|
+
HasherSync,
|
|
24
24
|
OriginalVerifiableCredential,
|
|
25
25
|
parseDid,
|
|
26
26
|
PresentationSubmission,
|
|
@@ -240,7 +240,7 @@ export class OpSession {
|
|
|
240
240
|
private createPresentationVerificationCallback(context: IRequiredContext) {
|
|
241
241
|
async function presentationVerificationCallback(
|
|
242
242
|
args: W3CVerifiablePresentation | CompactSdJwtVc,
|
|
243
|
-
presentationSubmission
|
|
243
|
+
presentationSubmission?: PresentationSubmission,
|
|
244
244
|
): Promise<PresentationVerificationResult> {
|
|
245
245
|
let result: IVerifyResult
|
|
246
246
|
if (CredentialMapper.isSdJwtEncoded(args)) {
|
|
@@ -293,8 +293,8 @@ export class OpSession {
|
|
|
293
293
|
.jwtEncryptJweCompactJwt({
|
|
294
294
|
recipientKey,
|
|
295
295
|
protectedHeader: {},
|
|
296
|
-
alg: requestObjectPayload.client_metadata.authorization_encrypted_response_alg as JweAlg | undefined ?? 'ECDH-ES',
|
|
297
|
-
enc: requestObjectPayload.client_metadata.authorization_encrypted_response_enc as JweEnc | undefined ?? 'A256GCM',
|
|
296
|
+
alg: (requestObjectPayload.client_metadata.authorization_encrypted_response_alg as JweAlg | undefined) ?? 'ECDH-ES',
|
|
297
|
+
enc: (requestObjectPayload.client_metadata.authorization_encrypted_response_enc as JweEnc | undefined) ?? 'A256GCM',
|
|
298
298
|
apv: encodeBase64url(opts.requestObjectPayload.nonce),
|
|
299
299
|
apu: encodeBase64url(v4()),
|
|
300
300
|
payload: authResponse,
|
|
@@ -360,12 +360,14 @@ export class OpSession {
|
|
|
360
360
|
const responseOpts = {
|
|
361
361
|
verification,
|
|
362
362
|
issuer,
|
|
363
|
+
...(args.isFirstParty && { isFirstParty: args.isFirstParty }),
|
|
363
364
|
...(args.verifiablePresentations && {
|
|
364
365
|
presentationExchange: {
|
|
365
366
|
verifiablePresentations,
|
|
366
367
|
presentationSubmission: args.presentationSubmission,
|
|
367
368
|
} as PresentationExchangeResponseOpts,
|
|
368
369
|
}),
|
|
370
|
+
dcqlQuery: args.dcqlResponse,
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
const authResponse = await op.createAuthorizationResponse(request, responseOpts)
|
|
@@ -378,7 +380,7 @@ export class OpSession {
|
|
|
378
380
|
}
|
|
379
381
|
}
|
|
380
382
|
|
|
381
|
-
private countVCsInAllVPs(verifiablePresentations: W3CVerifiablePresentation[], hasher?:
|
|
383
|
+
private countVCsInAllVPs(verifiablePresentations: W3CVerifiablePresentation[], hasher?: HasherSync) {
|
|
382
384
|
return verifiablePresentations.reduce((sum, vp) => {
|
|
383
385
|
if (CredentialMapper.isMsoMdocDecodedPresentation(vp) || CredentialMapper.isMsoMdocOid4VPEncoded(vp)) {
|
|
384
386
|
return sum + 1
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DcqlResponseOpts,
|
|
2
3
|
PresentationDefinitionWithLocation,
|
|
3
4
|
PresentationSignCallback,
|
|
4
5
|
ResponseMode,
|
|
@@ -18,7 +19,7 @@ import { ICredentialStore, UniqueDigitalCredential } from '@sphereon/ssi-sdk.cre
|
|
|
18
19
|
import { Party } from '@sphereon/ssi-sdk.data-store'
|
|
19
20
|
import { IPDManager } from '@sphereon/ssi-sdk.pd-manager'
|
|
20
21
|
import { ISDJwtPlugin } from '@sphereon/ssi-sdk.sd-jwt'
|
|
21
|
-
import {
|
|
22
|
+
import { HasherSync, OriginalVerifiableCredential, PresentationSubmission, W3CVerifiablePresentation } from '@sphereon/ssi-types'
|
|
22
23
|
import { VerifyCallback } from '@sphereon/wellknown-dids-client'
|
|
23
24
|
import {
|
|
24
25
|
IAgentContext,
|
|
@@ -122,7 +123,9 @@ export interface IOpsSendSiopAuthorizationResponseArgs {
|
|
|
122
123
|
// verifiedAuthorizationRequest: VerifiedAuthorizationRequest
|
|
123
124
|
presentationSubmission?: PresentationSubmission
|
|
124
125
|
verifiablePresentations?: W3CVerifiablePresentation[]
|
|
125
|
-
|
|
126
|
+
dcqlResponse?: DcqlResponseOpts
|
|
127
|
+
hasher?: HasherSync
|
|
128
|
+
isFirstParty?: boolean
|
|
126
129
|
}
|
|
127
130
|
|
|
128
131
|
export enum events {
|
|
@@ -159,7 +162,7 @@ export interface IOPOptions {
|
|
|
159
162
|
presentationSignCallback?: PresentationSignCallback
|
|
160
163
|
|
|
161
164
|
resolveOpts?: ResolveOpts
|
|
162
|
-
hasher?:
|
|
165
|
+
hasher?: HasherSync
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
/*
|
|
@@ -182,19 +185,30 @@ export interface VerifiablePresentationWithDefinition extends VerifiablePresenta
|
|
|
182
185
|
|
|
183
186
|
export interface IOpSessionGetOID4VPArgs {
|
|
184
187
|
allIdentifiers?: string[]
|
|
185
|
-
hasher?:
|
|
188
|
+
hasher?: HasherSync
|
|
186
189
|
}
|
|
187
190
|
|
|
188
191
|
export interface IOID4VPArgs {
|
|
189
192
|
session: OpSession
|
|
190
193
|
allIdentifiers?: string[]
|
|
191
|
-
hasher?:
|
|
194
|
+
hasher?: HasherSync
|
|
192
195
|
}
|
|
193
196
|
|
|
194
197
|
export interface IGetPresentationExchangeArgs {
|
|
195
198
|
verifiableCredentials: OriginalVerifiableCredential[]
|
|
196
199
|
allIdentifiers?: string[]
|
|
197
|
-
hasher?:
|
|
198
|
-
}
|
|
200
|
+
hasher?: HasherSync
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// It was added here because it's not exported from DCQL anymore
|
|
204
|
+
export type Json =
|
|
205
|
+
| string
|
|
206
|
+
| number
|
|
207
|
+
| boolean
|
|
208
|
+
| null
|
|
209
|
+
| {
|
|
210
|
+
[key: string]: Json
|
|
211
|
+
}
|
|
212
|
+
| Json[]
|
|
199
213
|
|
|
200
214
|
export const DEFAULT_JWT_PROOF_TYPE = 'JwtProof2020'
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
PresentationDefinitionWithLocation,
|
|
3
|
+
PresentationSignCallback,
|
|
4
|
+
RPRegistrationMetadataPayload,
|
|
5
|
+
VerifiedAuthorizationRequest,
|
|
6
|
+
} from '@sphereon/did-auth-siop'
|
|
2
7
|
import { IIdentifierResolution, ManagedIdentifierOptsOrResult } from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
3
8
|
import { IContactManager } from '@sphereon/ssi-sdk.contact-manager'
|
|
4
9
|
import { ICredentialStore, UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
@@ -7,10 +12,15 @@ import { IIssuanceBranding } from '@sphereon/ssi-sdk.issuance-branding'
|
|
|
7
12
|
import { IAgentContext, IDIDManager, IIdentifier, IResolver } from '@veramo/core'
|
|
8
13
|
import { IDidAuthSiopOpAuthenticator } from '../IDidAuthSiopOpAuthenticator'
|
|
9
14
|
import { Siopv2MachineContext, Siopv2MachineInterpreter, Siopv2MachineState } from '../machine'
|
|
15
|
+
import { DcqlQuery } from 'dcql'
|
|
16
|
+
import { HasherSync } from '@sphereon/ssi-types'
|
|
10
17
|
|
|
11
18
|
export type DidAuthSiopOpAuthenticatorOptions = {
|
|
19
|
+
presentationSignCallback?: PresentationSignCallback
|
|
20
|
+
customApprovals?: Record<string, (verifiedAuthorizationRequest: VerifiedAuthorizationRequest, sessionId: string) => Promise<void>>
|
|
12
21
|
onContactIdentityCreated?: (args: OnContactIdentityCreatedArgs) => Promise<void>
|
|
13
22
|
onIdentifierCreated?: (args: OnIdentifierCreatedArgs) => Promise<void>
|
|
23
|
+
hasher?: HasherSync
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
export type GetMachineArgs = {
|
|
@@ -19,12 +29,21 @@ export type GetMachineArgs = {
|
|
|
19
29
|
stateNavigationListener?: (siopv2Machine: Siopv2MachineInterpreter, state: Siopv2MachineState, navigation?: any) => Promise<void>
|
|
20
30
|
}
|
|
21
31
|
|
|
22
|
-
export type CreateConfigArgs =
|
|
32
|
+
export type CreateConfigArgs = { url: string }
|
|
23
33
|
export type CreateConfigResult = Omit<DidAuthConfig, 'stateId' | 'idOpts'>
|
|
24
|
-
export type GetSiopRequestArgs =
|
|
34
|
+
export type GetSiopRequestArgs = { didAuthConfig?: Omit<DidAuthConfig, 'identifier'>; url: string }
|
|
35
|
+
// FIXME it would be nicer if these function are not tied to a certain machine so that we can start calling them for anywhere
|
|
25
36
|
export type RetrieveContactArgs = Pick<Siopv2MachineContext, 'url' | 'authorizationRequestData'>
|
|
37
|
+
// FIXME it would be nicer if these function are not tied to a certain machine so that we can start calling them for anywhere
|
|
26
38
|
export type AddIdentityArgs = Pick<Siopv2MachineContext, 'contact' | 'authorizationRequestData'>
|
|
27
|
-
export type SendResponseArgs =
|
|
39
|
+
export type SendResponseArgs = {
|
|
40
|
+
didAuthConfig?: Omit<DidAuthConfig, 'identifier'>
|
|
41
|
+
authorizationRequestData?: Siopv2AuthorizationRequestData
|
|
42
|
+
selectedCredentials: Array<UniqueDigitalCredential>
|
|
43
|
+
idOpts?: ManagedIdentifierOptsOrResult
|
|
44
|
+
isFirstParty?: boolean
|
|
45
|
+
}
|
|
46
|
+
// FIXME it would be nicer if these function are not tied to a certain machine so that we can start calling them for anywhere
|
|
28
47
|
export type GetSelectableCredentialsArgs = Pick<Siopv2MachineContext, 'authorizationRequestData'>
|
|
29
48
|
|
|
30
49
|
export enum Siopv2HolderEvent {
|
|
@@ -38,7 +57,7 @@ export enum SupportedLanguage {
|
|
|
38
57
|
}
|
|
39
58
|
|
|
40
59
|
export type Siopv2AuthorizationResponseData = {
|
|
41
|
-
body?: string
|
|
60
|
+
body?: string | Record<string, any>
|
|
42
61
|
url?: string
|
|
43
62
|
queryParams?: Record<string, any>
|
|
44
63
|
}
|
|
@@ -51,6 +70,7 @@ export type Siopv2AuthorizationRequestData = {
|
|
|
51
70
|
uri?: URL
|
|
52
71
|
clientId?: string
|
|
53
72
|
presentationDefinitions?: PresentationDefinitionWithLocation[]
|
|
73
|
+
dcqlQuery?: DcqlQuery
|
|
54
74
|
}
|
|
55
75
|
|
|
56
76
|
export type SelectableCredentialsMap = Map<string, Array<SelectableCredential>>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { CredentialMapper, HasherSync, ICredential, IVerifiableCredential, OriginalVerifiableCredential } from '@sphereon/ssi-types'
|
|
2
|
+
import { VerifiableCredential } from '@veramo/core'
|
|
3
|
+
import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Return the type(s) of a VC minus the VerifiableCredential type which should always be present
|
|
7
|
+
* @param credential The input credential
|
|
8
|
+
*/
|
|
9
|
+
export const getCredentialTypeAsString = (credential: ICredential | VerifiableCredential): string => {
|
|
10
|
+
if (!credential.type) {
|
|
11
|
+
return 'Verifiable Credential'
|
|
12
|
+
} else if (typeof credential.type === 'string') {
|
|
13
|
+
return credential.type
|
|
14
|
+
}
|
|
15
|
+
return credential.type.filter((type: string): boolean => type !== 'VerifiableCredential').join(', ')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Returns a Unique Verifiable Credential (with hash) as stored in Veramo, based upon matching the id of the input VC or the proof value of the input VC
|
|
20
|
+
* @param uniqueVCs The Unique VCs to search in
|
|
21
|
+
* @param searchVC The VC to search for in the unique VCs array
|
|
22
|
+
*/
|
|
23
|
+
export const getMatchingUniqueDigitalCredential = (
|
|
24
|
+
uniqueVCs: UniqueDigitalCredential[],
|
|
25
|
+
searchVC: OriginalVerifiableCredential,
|
|
26
|
+
): UniqueDigitalCredential | undefined => {
|
|
27
|
+
// Since an ID is optional in a VC according to VCDM, and we really need the matches, we have a fallback match on something which is guaranteed to be unique for any VC (the proof(s))
|
|
28
|
+
return uniqueVCs.find(
|
|
29
|
+
(uniqueVC: UniqueDigitalCredential) =>
|
|
30
|
+
(typeof searchVC !== 'string' &&
|
|
31
|
+
(uniqueVC.id === (<IVerifiableCredential>searchVC).id ||
|
|
32
|
+
(uniqueVC.originalVerifiableCredential as VerifiableCredential).proof === (<IVerifiableCredential>searchVC).proof)) ||
|
|
33
|
+
(typeof searchVC === 'string' && (uniqueVC.uniformVerifiableCredential as VerifiableCredential)?.proof?.jwt === searchVC) ||
|
|
34
|
+
// We are ignoring the signature of the sd-jwt as PEX signs the vc again and it will not match anymore with the jwt in the proof of the stored jsonld vc
|
|
35
|
+
(typeof searchVC === 'string' &&
|
|
36
|
+
CredentialMapper.isSdJwtEncoded(searchVC) &&
|
|
37
|
+
uniqueVC.uniformVerifiableCredential?.proof &&
|
|
38
|
+
'jwt' in uniqueVC.uniformVerifiableCredential.proof &&
|
|
39
|
+
uniqueVC.uniformVerifiableCredential.proof.jwt?.split('.')?.slice(0, 2)?.join('.') === searchVC.split('.')?.slice(0, 2)?.join('.')),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type InputCredential = UniqueDigitalCredential | VerifiableCredential | ICredential | OriginalVerifiableCredential
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get an original verifiable credential. Maps to wrapped Verifiable Credential first, to get an original JWT as Veramo stores these with a special proof value
|
|
47
|
+
* @param credential The input VC
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
export const getOriginalVerifiableCredential = (credential: InputCredential): OriginalVerifiableCredential => {
|
|
51
|
+
if (isUniqueDigitalCredential(credential)) {
|
|
52
|
+
if (!credential.originalVerifiableCredential) {
|
|
53
|
+
throw new Error('originalVerifiableCredential is not defined in UniqueDigitalCredential')
|
|
54
|
+
}
|
|
55
|
+
return getCredentialFromProofOrWrapped(credential.originalVerifiableCredential)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return getCredentialFromProofOrWrapped(credential)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const getCredentialFromProofOrWrapped = (cred: any, hasher?: HasherSync): OriginalVerifiableCredential => {
|
|
62
|
+
if (typeof cred === 'object' && 'proof' in cred && 'jwt' in cred.proof && CredentialMapper.isSdJwtEncoded(cred.proof.jwt)) {
|
|
63
|
+
return cred.proof.jwt
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return CredentialMapper.toWrappedVerifiableCredential(cred as OriginalVerifiableCredential, { hasher }).original
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const isUniqueDigitalCredential = (credential: InputCredential): credential is UniqueDigitalCredential => {
|
|
70
|
+
return (credential as UniqueDigitalCredential).digitalCredential !== undefined
|
|
71
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { UniqueDigitalCredential } from '@sphereon/ssi-sdk.credential-store'
|
|
2
|
+
import { DcqlCredential, DcqlSdJwtVcCredential, DcqlW3cVcCredential } from 'dcql'
|
|
3
|
+
import { CredentialMapper, HasherSync, OriginalVerifiableCredential } from '@sphereon/ssi-types'
|
|
4
|
+
import { isUniqueDigitalCredential } from './CredentialUtils'
|
|
5
|
+
|
|
6
|
+
export function convertToDcqlCredentials(credential: UniqueDigitalCredential | OriginalVerifiableCredential, hasher?: HasherSync): DcqlCredential {
|
|
7
|
+
let payload
|
|
8
|
+
if (isUniqueDigitalCredential(credential)) {
|
|
9
|
+
if (!credential.originalVerifiableCredential) {
|
|
10
|
+
throw new Error('originalVerifiableCredential is not defined in UniqueDigitalCredential')
|
|
11
|
+
}
|
|
12
|
+
payload = CredentialMapper.decodeVerifiableCredential(credential.originalVerifiableCredential, hasher)
|
|
13
|
+
} else {
|
|
14
|
+
payload = CredentialMapper.decodeVerifiableCredential(credential as OriginalVerifiableCredential, hasher)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!payload) {
|
|
18
|
+
throw new Error('No payload found')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if ('decodedPayload' in payload && payload.decodedPayload) {
|
|
22
|
+
payload = payload.decodedPayload
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if ('vct' in payload!) {
|
|
26
|
+
return { vct: payload.vct, claims: payload, credential_format: 'vc+sd-jwt' } satisfies DcqlSdJwtVcCredential // TODO dc+sd-jwt support?
|
|
27
|
+
} else if ('docType' in payload! && 'namespaces' in payload) {
|
|
28
|
+
// mdoc
|
|
29
|
+
return { docType: payload.docType, namespaces: payload.namespaces, claims: payload }
|
|
30
|
+
} else {
|
|
31
|
+
return {
|
|
32
|
+
claims: payload,
|
|
33
|
+
credential_format: 'jwt_vc_json', // TODO jwt_vc_json-ld support
|
|
34
|
+
} as DcqlW3cVcCredential
|
|
35
|
+
}
|
|
36
|
+
}
|