@sphereon/ssi-sdk.oid4vci-holder 0.32.1-next.54 → 0.33.0
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/OID4VCIHolder.d.ts +1 -0
- package/dist/agent/OID4VCIHolder.d.ts.map +1 -1
- package/dist/agent/OID4VCIHolder.js +23 -10
- package/dist/agent/OID4VCIHolder.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/link-handler/index.d.ts.map +1 -1
- package/dist/link-handler/index.js.map +1 -1
- package/dist/machines/firstPartyMachine.d.ts.map +1 -1
- package/dist/machines/firstPartyMachine.js +10 -10
- package/dist/machines/firstPartyMachine.js.map +1 -1
- package/dist/machines/oid4vciMachine.d.ts.map +1 -1
- package/dist/machines/oid4vciMachine.js +3 -3
- package/dist/machines/oid4vciMachine.js.map +1 -1
- package/dist/mappers/OIDC4VCIBrandingMapper.d.ts.map +1 -1
- package/dist/mappers/OIDC4VCIBrandingMapper.js +1 -1
- package/dist/mappers/OIDC4VCIBrandingMapper.js.map +1 -1
- package/dist/services/FirstPartyMachineServices.d.ts.map +1 -1
- package/dist/services/FirstPartyMachineServices.js +3 -2
- package/dist/services/FirstPartyMachineServices.js.map +1 -1
- package/dist/services/OID4VCIHolderService.d.ts.map +1 -1
- package/dist/services/OID4VCIHolderService.js +4 -3
- package/dist/services/OID4VCIHolderService.js.map +1 -1
- package/dist/types/FirstPartyMachine.d.ts.map +1 -1
- package/dist/types/FirstPartyMachine.js.map +1 -1
- package/dist/types/IOID4VCIHolder.d.ts +6 -6
- package/dist/types/IOID4VCIHolder.d.ts.map +1 -1
- package/dist/types/IOID4VCIHolder.js.map +1 -1
- package/package.json +26 -25
- package/src/agent/OID4VCIHolder.ts +33 -11
- package/src/index.ts +1 -0
- package/src/link-handler/index.ts +6 -8
- package/src/machines/firstPartyMachine.ts +60 -69
- package/src/machines/oid4vciMachine.ts +9 -11
- package/src/mappers/OIDC4VCIBrandingMapper.ts +26 -25
- package/src/services/FirstPartyMachineServices.ts +11 -10
- package/src/services/OID4VCIHolderService.ts +25 -24
- package/src/types/FirstPartyMachine.ts +56 -64
- package/src/types/IOID4VCIHolder.ts +35 -32
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
AuthorizationRequestOpts,
|
|
5
5
|
AuthorizationServerClientOpts,
|
|
6
6
|
AuthorizationServerOpts,
|
|
7
|
+
CredentialConfigurationSupportedJwtVcJsonLdAndLdpVcV1_0_13,
|
|
8
|
+
CredentialDefinitionJwtVcJsonLdAndLdpVcV1_0_13,
|
|
7
9
|
CredentialOfferRequestWithBaseUrl,
|
|
8
10
|
DefaultURISchemes,
|
|
9
11
|
EndpointMetadataResult,
|
|
@@ -45,7 +47,7 @@ import {
|
|
|
45
47
|
} from '@sphereon/ssi-sdk.data-store'
|
|
46
48
|
import {
|
|
47
49
|
CredentialMapper,
|
|
48
|
-
|
|
50
|
+
HasherSync,
|
|
49
51
|
IVerifiableCredential,
|
|
50
52
|
JoseSignatureAlgorithm,
|
|
51
53
|
JoseSignatureAlgorithmString,
|
|
@@ -107,7 +109,7 @@ import {
|
|
|
107
109
|
StoreIssuerBrandingArgs,
|
|
108
110
|
VerificationResult,
|
|
109
111
|
VerifyEBSICredentialIssuerArgs,
|
|
110
|
-
VerifyEBSICredentialIssuerResult
|
|
112
|
+
VerifyEBSICredentialIssuerResult,
|
|
111
113
|
} from '../types/IOID4VCIHolder'
|
|
112
114
|
import {
|
|
113
115
|
getBasicIssuerLocaleBranding,
|
|
@@ -117,10 +119,11 @@ import {
|
|
|
117
119
|
getIssuanceOpts,
|
|
118
120
|
mapCredentialToAccept,
|
|
119
121
|
selectCredentialLocaleBranding,
|
|
122
|
+
startFirstPartApplicationMachine,
|
|
120
123
|
verifyCredentialToAccept,
|
|
121
|
-
startFirstPartApplicationMachine
|
|
122
124
|
} from '../services/OID4VCIHolderService'
|
|
123
125
|
import 'cross-fetch/polyfill'
|
|
126
|
+
import { defaultHasher } from '@sphereon/ssi-sdk.core'
|
|
124
127
|
|
|
125
128
|
/**
|
|
126
129
|
* {@inheritDoc IOID4VCIHolder}
|
|
@@ -202,7 +205,7 @@ export async function verifyEBSICredentialIssuer(args: VerifyEBSICredentialIssue
|
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
export class OID4VCIHolder implements IAgentPlugin {
|
|
205
|
-
private readonly hasher?:
|
|
208
|
+
private readonly hasher?: HasherSync
|
|
206
209
|
readonly eventTypes: Array<OID4VCIHolderEvent> = [
|
|
207
210
|
OID4VCIHolderEvent.CONTACT_IDENTITY_CREATED,
|
|
208
211
|
OID4VCIHolderEvent.CREDENTIAL_STORED,
|
|
@@ -264,7 +267,7 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
264
267
|
didMethodPreferences,
|
|
265
268
|
jwtCryptographicSuitePreferences,
|
|
266
269
|
defaultAuthorizationRequestOptions,
|
|
267
|
-
hasher,
|
|
270
|
+
hasher = defaultHasher,
|
|
268
271
|
} = { ...options }
|
|
269
272
|
|
|
270
273
|
this.hasher = hasher
|
|
@@ -319,15 +322,19 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
319
322
|
},
|
|
320
323
|
context,
|
|
321
324
|
),
|
|
322
|
-
[OID4VCIMachineServices.startFirstPartApplicationFlow]: (args: StartFirstPartApplicationMachine) =>
|
|
323
|
-
|
|
325
|
+
[OID4VCIMachineServices.startFirstPartApplicationFlow]: (args: StartFirstPartApplicationMachine) =>
|
|
326
|
+
startFirstPartApplicationMachine({ ...args, stateNavigationListener: opts.firstPartyStateNavigationListener }, context),
|
|
327
|
+
[OID4VCIMachineServices.createCredentialsToSelectFrom]: (args: CreateCredentialsToSelectFromArgs) =>
|
|
328
|
+
this.oid4vciHolderCreateCredentialsToSelectFrom(args, context),
|
|
324
329
|
[OID4VCIMachineServices.getContact]: (args: GetContactArgs) => this.oid4vciHolderGetContact(args, context),
|
|
325
|
-
[OID4VCIMachineServices.getCredentials]: (args: GetCredentialsArgs) =>
|
|
330
|
+
[OID4VCIMachineServices.getCredentials]: (args: GetCredentialsArgs) =>
|
|
331
|
+
this.oid4vciHolderGetCredentials({ accessTokenOpts: args.accessTokenOpts ?? opts.accessTokenOpts, ...args }, context),
|
|
326
332
|
[OID4VCIMachineServices.addContactIdentity]: (args: AddContactIdentityArgs) => this.oid4vciHolderAddContactIdentity(args, context),
|
|
327
333
|
[OID4VCIMachineServices.getIssuerBranding]: (args: GetIssuerBrandingArgs) => this.oid4vciHolderGetIssuerBranding(args, context),
|
|
328
334
|
[OID4VCIMachineServices.storeIssuerBranding]: (args: StoreIssuerBrandingArgs) => this.oid4vciHolderStoreIssuerBranding(args, context),
|
|
329
335
|
[OID4VCIMachineServices.assertValidCredentials]: (args: AssertValidCredentialsArgs) => this.oid4vciHolderAssertValidCredentials(args, context),
|
|
330
|
-
[OID4VCIMachineServices.storeCredentialBranding]: (args: StoreCredentialBrandingArgs) =>
|
|
336
|
+
[OID4VCIMachineServices.storeCredentialBranding]: (args: StoreCredentialBrandingArgs) =>
|
|
337
|
+
this.oid4vciHolderStoreCredentialBranding(args, context),
|
|
331
338
|
[OID4VCIMachineServices.storeCredentials]: (args: StoreCredentialsArgs) => this.oid4vciHolderStoreCredentials(args, context),
|
|
332
339
|
[OID4VCIMachineServices.sendNotification]: (args: SendNotificationArgs) => this.oid4vciHolderSendNotification(args, context),
|
|
333
340
|
[OID4VCIMachineServices.getFederationTrust]: (args: GetFederationTrustArgs) => this.getFederationTrust(args, context),
|
|
@@ -632,7 +639,7 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
632
639
|
// The VCI lib either expects a jwk or a kid
|
|
633
640
|
const jwk = isManagedIdentifierJwkResult(identifier) ? identifier.jwk : undefined
|
|
634
641
|
|
|
635
|
-
const callbacks: ProofOfPossessionCallbacks
|
|
642
|
+
const callbacks: ProofOfPossessionCallbacks = {
|
|
636
643
|
signCallback: signCallback(identifier, context),
|
|
637
644
|
}
|
|
638
645
|
|
|
@@ -678,7 +685,10 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
678
685
|
if (!credentialTypes || credentialTypes.length === 0) {
|
|
679
686
|
return Promise.reject(Error('cannot determine credential id to request'))
|
|
680
687
|
}
|
|
688
|
+
|
|
689
|
+
const credentialDefinition = this.getCredentialDefinition(issuanceOpt)
|
|
681
690
|
const credentialResponse = await client.acquireCredentials({
|
|
691
|
+
...(credentialDefinition && { context: credentialDefinition['@context'] }),
|
|
682
692
|
credentialTypes,
|
|
683
693
|
proofCallbacks: callbacks,
|
|
684
694
|
format: issuanceOpt.format,
|
|
@@ -911,7 +921,7 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
911
921
|
: 'credential_deleted_holder_signed'
|
|
912
922
|
logger.log(`Subject issuance/signing will be used, with event`, event)
|
|
913
923
|
const issuerVC = mappedCredentialToAccept.credentialToAccept.credentialResponse.credential as OriginalVerifiableCredential
|
|
914
|
-
const wrappedIssuerVC = CredentialMapper.toWrappedVerifiableCredential(issuerVC, { hasher: this.hasher })
|
|
924
|
+
const wrappedIssuerVC = CredentialMapper.toWrappedVerifiableCredential(issuerVC, { hasher: this.hasher ?? defaultHasher })
|
|
915
925
|
console.log(`Wrapped VC: ${wrappedIssuerVC.type}, ${wrappedIssuerVC.format}`)
|
|
916
926
|
// We will use the subject of the VCI Issuer (the holder, as the issuer of the new credential, so the below is not a mistake!)
|
|
917
927
|
|
|
@@ -1078,6 +1088,11 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
1078
1088
|
const params = new URLSearchParams(url.search)
|
|
1079
1089
|
const openidFederation = params.get('openid_federation')
|
|
1080
1090
|
const entityIdentifier = openidFederation ?? serverMetadata.issuer
|
|
1091
|
+
if (entityIdentifier.startsWith('http://')) {
|
|
1092
|
+
console.warn(`OpenID federation does not support http://, only https:// allowed; got: (${url.toString()})`)
|
|
1093
|
+
// OIDF always needs to be https
|
|
1094
|
+
return []
|
|
1095
|
+
}
|
|
1081
1096
|
|
|
1082
1097
|
const result = await context.agent.identifierExternalResolveByOIDFEntityId({
|
|
1083
1098
|
method: 'entity_id',
|
|
@@ -1130,4 +1145,11 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
1130
1145
|
}
|
|
1131
1146
|
return undefined
|
|
1132
1147
|
}
|
|
1148
|
+
|
|
1149
|
+
private getCredentialDefinition(issuanceOpt: IssuanceOpts): CredentialDefinitionJwtVcJsonLdAndLdpVcV1_0_13 | undefined {
|
|
1150
|
+
if (issuanceOpt.format == 'ldp_vc' || issuanceOpt.format == 'jwt_vc_json-ld') {
|
|
1151
|
+
return (issuanceOpt as CredentialConfigurationSupportedJwtVcJsonLdAndLdpVcV1_0_13).credential_definition
|
|
1152
|
+
}
|
|
1153
|
+
return undefined
|
|
1154
|
+
}
|
|
1133
1155
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export { OID4VCIHolder, oid4vciHolderContextMethods, signCallback } from './agent/OID4VCIHolder'
|
|
6
|
+
export * from './mappers/OIDC4VCIBrandingMapper'
|
|
6
7
|
export * from './services/OID4VCIHolderService'
|
|
7
8
|
export * from './services/FirstPartyMachineServices'
|
|
8
9
|
export * from './types/IOID4VCIHolder'
|
|
@@ -3,12 +3,7 @@ import { AuthorizationRequestOpts, AuthorizationServerClientOpts, AuthzFlowType,
|
|
|
3
3
|
import { DefaultLinkPriorities, LinkHandlerAdapter } from '@sphereon/ssi-sdk.core'
|
|
4
4
|
import { IMachineStatePersistence, interpreterStartOrResume, SerializableState } from '@sphereon/ssi-sdk.xstate-machine-persistence'
|
|
5
5
|
import { IAgentContext } from '@veramo/core'
|
|
6
|
-
import {
|
|
7
|
-
GetMachineArgs,
|
|
8
|
-
IOID4VCIHolder,
|
|
9
|
-
OID4VCIMachineEvents,
|
|
10
|
-
OID4VCIMachineStateNavigationListener
|
|
11
|
-
} from '../types/IOID4VCIHolder'
|
|
6
|
+
import { GetMachineArgs, IOID4VCIHolder, OID4VCIMachineEvents, OID4VCIMachineStateNavigationListener } from '../types/IOID4VCIHolder'
|
|
12
7
|
import { FirstPartyMachineStateNavigationListener } from '../types/FirstPartyMachine'
|
|
13
8
|
|
|
14
9
|
/**
|
|
@@ -24,7 +19,10 @@ export class OID4VCIHolderLinkHandler extends LinkHandlerAdapter {
|
|
|
24
19
|
private readonly trustAnchors?: Array<string>
|
|
25
20
|
|
|
26
21
|
constructor(
|
|
27
|
-
args: Pick<
|
|
22
|
+
args: Pick<
|
|
23
|
+
GetMachineArgs,
|
|
24
|
+
'stateNavigationListener' | 'authorizationRequestOpts' | 'clientOpts' | 'trustAnchors' | 'firstPartyStateNavigationListener'
|
|
25
|
+
> & {
|
|
28
26
|
priority?: number | DefaultLinkPriorities
|
|
29
27
|
protocols?: Array<string | RegExp>
|
|
30
28
|
noStateMachinePersistence?: boolean
|
|
@@ -69,7 +67,7 @@ export class OID4VCIHolderLinkHandler extends LinkHandlerAdapter {
|
|
|
69
67
|
authorizationRequestOpts: { ...this.authorizationRequestOpts, ...opts?.authorizationRequestOpts },
|
|
70
68
|
...((clientOpts.clientId || clientOpts.clientAssertionType) && { clientOpts: clientOpts as AuthorizationServerClientOpts }),
|
|
71
69
|
stateNavigationListener: this.stateNavigationListener,
|
|
72
|
-
firstPartyStateNavigationListener: this.firstPartyStateNavigationListener
|
|
70
|
+
firstPartyStateNavigationListener: this.firstPartyStateNavigationListener,
|
|
73
71
|
})
|
|
74
72
|
|
|
75
73
|
const interpreter = oid4vciMachine.interpreter
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
import { assign, createMachine, DoneInvokeEvent, interpret } from 'xstate'
|
|
2
|
-
import {
|
|
3
|
-
AuthorizationChallengeCodeResponse,
|
|
4
|
-
AuthorizationChallengeError,
|
|
5
|
-
AuthorizationChallengeErrorResponse
|
|
6
|
-
} from '@sphereon/oid4vci-common'
|
|
2
|
+
import { AuthorizationChallengeCodeResponse, AuthorizationChallengeError, AuthorizationChallengeErrorResponse } from '@sphereon/oid4vci-common'
|
|
7
3
|
import { DidAuthConfig } from '@sphereon/ssi-sdk.data-store'
|
|
8
4
|
import { CreateConfigResult } from '@sphereon/ssi-sdk.siopv2-oid4vp-op-auth'
|
|
9
|
-
import {
|
|
10
|
-
createConfig,
|
|
11
|
-
getSiopRequest,
|
|
12
|
-
sendAuthorizationChallengeRequest,
|
|
13
|
-
sendAuthorizationResponse
|
|
14
|
-
} from '../services/FirstPartyMachineServices'
|
|
5
|
+
import { createConfig, getSiopRequest, sendAuthorizationChallengeRequest, sendAuthorizationResponse } from '../services/FirstPartyMachineServices'
|
|
15
6
|
import { translate } from '../localization/Localization'
|
|
16
7
|
import { ErrorDetails } from '../types/IOID4VCIHolder'
|
|
17
8
|
import {
|
|
@@ -31,7 +22,7 @@ import {
|
|
|
31
22
|
InstanceFirstPartyMachineOpts,
|
|
32
23
|
SiopV2AuthorizationRequestData,
|
|
33
24
|
SendAuthorizationResponseArgs,
|
|
34
|
-
FirstPartySelectCredentialsEvent
|
|
25
|
+
FirstPartySelectCredentialsEvent,
|
|
35
26
|
} from '../types/FirstPartyMachine'
|
|
36
27
|
|
|
37
28
|
const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
@@ -42,16 +33,18 @@ const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
|
42
33
|
onDone: {
|
|
43
34
|
target: FirstPartyMachineStateTypes.done,
|
|
44
35
|
actions: assign({
|
|
45
|
-
authorizationCodeResponse: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeCodeResponse>) => _event.data
|
|
46
|
-
})
|
|
36
|
+
authorizationCodeResponse: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeCodeResponse>) => _event.data,
|
|
37
|
+
}),
|
|
47
38
|
},
|
|
48
39
|
onError: [
|
|
49
40
|
{
|
|
50
41
|
target: FirstPartyMachineStateTypes.createConfig,
|
|
51
|
-
cond: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>): boolean =>
|
|
42
|
+
cond: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>): boolean =>
|
|
43
|
+
_event.data.error === AuthorizationChallengeError.insufficient_authorization,
|
|
52
44
|
actions: assign({
|
|
53
45
|
authSession: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>) => _event.data.auth_session,
|
|
54
|
-
presentationUri: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>) =>
|
|
46
|
+
presentationUri: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>) =>
|
|
47
|
+
_event.data.presentation,
|
|
55
48
|
}),
|
|
56
49
|
},
|
|
57
50
|
{
|
|
@@ -63,9 +56,9 @@ const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
|
63
56
|
stack: _event.data.stack,
|
|
64
57
|
}),
|
|
65
58
|
}),
|
|
66
|
-
}
|
|
59
|
+
},
|
|
67
60
|
],
|
|
68
|
-
}
|
|
61
|
+
},
|
|
69
62
|
},
|
|
70
63
|
[FirstPartyMachineStateTypes.createConfig]: {
|
|
71
64
|
id: FirstPartyMachineStateTypes.createConfig,
|
|
@@ -115,7 +108,7 @@ const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
|
115
108
|
id: FirstPartyMachineStateTypes.selectCredentials,
|
|
116
109
|
on: {
|
|
117
110
|
[FirstPartyMachineEvents.SET_SELECTED_CREDENTIALS]: {
|
|
118
|
-
actions: assign({selectedCredentials: (_ctx: FirstPartyMachineContext, _event: FirstPartySelectCredentialsEvent) => _event.data}),
|
|
111
|
+
actions: assign({ selectedCredentials: (_ctx: FirstPartyMachineContext, _event: FirstPartySelectCredentialsEvent) => _event.data }),
|
|
119
112
|
},
|
|
120
113
|
[FirstPartyMachineEvents.NEXT]: {
|
|
121
114
|
target: FirstPartyMachineStateTypes.sendAuthorizationResponse,
|
|
@@ -148,15 +141,15 @@ const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
|
148
141
|
}),
|
|
149
142
|
}),
|
|
150
143
|
},
|
|
151
|
-
}
|
|
144
|
+
},
|
|
152
145
|
},
|
|
153
146
|
[FirstPartyMachineStateTypes.aborted]: {
|
|
154
147
|
id: FirstPartyMachineStateTypes.aborted,
|
|
155
|
-
type: 'final'
|
|
148
|
+
type: 'final',
|
|
156
149
|
},
|
|
157
150
|
[FirstPartyMachineStateTypes.declined]: {
|
|
158
151
|
id: FirstPartyMachineStateTypes.declined,
|
|
159
|
-
type: 'final'
|
|
152
|
+
type: 'final',
|
|
160
153
|
},
|
|
161
154
|
[FirstPartyMachineStateTypes.error]: {
|
|
162
155
|
id: FirstPartyMachineStateTypes.error,
|
|
@@ -165,7 +158,7 @@ const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
|
165
158
|
[FirstPartyMachineStateTypes.done]: {
|
|
166
159
|
id: FirstPartyMachineStateTypes.done,
|
|
167
160
|
type: 'final',
|
|
168
|
-
}
|
|
161
|
+
},
|
|
169
162
|
}
|
|
170
163
|
|
|
171
164
|
const createFirstPartyActivationMachine = (opts: CreateFirstPartyMachineOpts): FirstPartyStateMachine => {
|
|
@@ -173,66 +166,64 @@ const createFirstPartyActivationMachine = (opts: CreateFirstPartyMachineOpts): F
|
|
|
173
166
|
openID4VCIClientState: opts.openID4VCIClientState,
|
|
174
167
|
contact: opts.contact,
|
|
175
168
|
selectedCredentials: [],
|
|
176
|
-
}
|
|
169
|
+
}
|
|
177
170
|
|
|
178
|
-
return createMachine<FirstPartyMachineContext, FirstPartyMachineEventTypes>(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
data: void
|
|
190
|
-
},
|
|
191
|
-
[FirstPartyMachineServices.createConfig]: {
|
|
192
|
-
data: CreateConfigResult
|
|
193
|
-
},
|
|
194
|
-
[FirstPartyMachineServices.getSiopRequest]: {
|
|
195
|
-
data: SiopV2AuthorizationRequestData
|
|
196
|
-
},
|
|
197
|
-
[FirstPartyMachineServices.sendAuthorizationResponse]: {
|
|
198
|
-
data: string
|
|
199
|
-
}
|
|
171
|
+
return createMachine<FirstPartyMachineContext, FirstPartyMachineEventTypes>({
|
|
172
|
+
id: opts?.machineId ?? 'FirstParty',
|
|
173
|
+
predictableActionArguments: true,
|
|
174
|
+
initial: FirstPartyMachineStateTypes.sendAuthorizationChallengeRequest,
|
|
175
|
+
context: initialContext,
|
|
176
|
+
states: firstPartyMachineStates,
|
|
177
|
+
schema: {
|
|
178
|
+
events: {} as FirstPartyMachineEventTypes,
|
|
179
|
+
services: {} as {
|
|
180
|
+
[FirstPartyMachineServices.sendAuthorizationChallengeRequest]: {
|
|
181
|
+
data: void
|
|
200
182
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
183
|
+
[FirstPartyMachineServices.createConfig]: {
|
|
184
|
+
data: CreateConfigResult
|
|
185
|
+
}
|
|
186
|
+
[FirstPartyMachineServices.getSiopRequest]: {
|
|
187
|
+
data: SiopV2AuthorizationRequestData
|
|
188
|
+
}
|
|
189
|
+
[FirstPartyMachineServices.sendAuthorizationResponse]: {
|
|
190
|
+
data: string
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
})
|
|
195
|
+
}
|
|
205
196
|
|
|
206
197
|
export class FirstPartyMachine {
|
|
207
|
-
private static _instance: FirstPartyMachineInterpreter | undefined
|
|
198
|
+
private static _instance: FirstPartyMachineInterpreter | undefined
|
|
208
199
|
|
|
209
200
|
static hasInstance(): boolean {
|
|
210
|
-
return FirstPartyMachine._instance !== undefined
|
|
201
|
+
return FirstPartyMachine._instance !== undefined
|
|
211
202
|
}
|
|
212
203
|
|
|
213
204
|
static get instance(): FirstPartyMachineInterpreter {
|
|
214
205
|
if (!FirstPartyMachine._instance) {
|
|
215
|
-
throw Error('Please initialize ESIMActivation machine first')
|
|
206
|
+
throw Error('Please initialize ESIMActivation machine first')
|
|
216
207
|
}
|
|
217
|
-
return FirstPartyMachine._instance
|
|
208
|
+
return FirstPartyMachine._instance
|
|
218
209
|
}
|
|
219
210
|
|
|
220
|
-
static clearInstance(opts: {stop: boolean}) {
|
|
221
|
-
const {stop} = opts
|
|
211
|
+
static clearInstance(opts: { stop: boolean }) {
|
|
212
|
+
const { stop } = opts
|
|
222
213
|
if (FirstPartyMachine.hasInstance()) {
|
|
223
214
|
if (stop) {
|
|
224
|
-
FirstPartyMachine.stopInstance()
|
|
215
|
+
FirstPartyMachine.stopInstance()
|
|
225
216
|
}
|
|
226
217
|
}
|
|
227
|
-
FirstPartyMachine._instance = undefined
|
|
218
|
+
FirstPartyMachine._instance = undefined
|
|
228
219
|
}
|
|
229
220
|
|
|
230
221
|
static stopInstance(): void {
|
|
231
222
|
if (!FirstPartyMachine.hasInstance()) {
|
|
232
|
-
return
|
|
223
|
+
return
|
|
233
224
|
}
|
|
234
|
-
FirstPartyMachine.instance.stop()
|
|
235
|
-
FirstPartyMachine._instance = undefined
|
|
225
|
+
FirstPartyMachine.instance.stop()
|
|
226
|
+
FirstPartyMachine._instance = undefined
|
|
236
227
|
}
|
|
237
228
|
|
|
238
229
|
public static newInstance(opts: InstanceFirstPartyMachineOpts): FirstPartyMachineInterpreter {
|
|
@@ -254,10 +245,10 @@ export class FirstPartyMachine {
|
|
|
254
245
|
...opts?.guards,
|
|
255
246
|
},
|
|
256
247
|
}),
|
|
257
|
-
)
|
|
248
|
+
)
|
|
258
249
|
|
|
259
250
|
if (typeof opts?.subscription === 'function') {
|
|
260
|
-
newInst.onTransition(opts.subscription)
|
|
251
|
+
newInst.onTransition(opts.subscription)
|
|
261
252
|
}
|
|
262
253
|
|
|
263
254
|
if (opts?.requireCustomNavigationHook !== true) {
|
|
@@ -265,23 +256,23 @@ export class FirstPartyMachine {
|
|
|
265
256
|
if (opts?.stateNavigationListener) {
|
|
266
257
|
void opts.stateNavigationListener(newInst, snapshot)
|
|
267
258
|
}
|
|
268
|
-
})
|
|
259
|
+
})
|
|
269
260
|
}
|
|
270
261
|
|
|
271
|
-
return newInst
|
|
262
|
+
return newInst
|
|
272
263
|
}
|
|
273
264
|
|
|
274
265
|
static getInstance(
|
|
275
266
|
opts: InstanceFirstPartyMachineOpts & {
|
|
276
|
-
requireExisting?: boolean
|
|
267
|
+
requireExisting?: boolean
|
|
277
268
|
},
|
|
278
269
|
): FirstPartyMachineInterpreter {
|
|
279
270
|
if (!FirstPartyMachine._instance) {
|
|
280
271
|
if (opts?.requireExisting === true) {
|
|
281
|
-
throw Error(`Existing FirstPartyMachine instance requested, but none was created at this point!`)
|
|
272
|
+
throw Error(`Existing FirstPartyMachine instance requested, but none was created at this point!`)
|
|
282
273
|
}
|
|
283
|
-
FirstPartyMachine._instance = FirstPartyMachine.newInstance(opts)
|
|
274
|
+
FirstPartyMachine._instance = FirstPartyMachine.newInstance(opts)
|
|
284
275
|
}
|
|
285
|
-
return FirstPartyMachine._instance
|
|
276
|
+
return FirstPartyMachine._instance
|
|
286
277
|
}
|
|
287
278
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AuthorizationChallengeCodeResponse,
|
|
3
|
-
AuthzFlowType,
|
|
4
|
-
toAuthorizationResponsePayload
|
|
5
|
-
} from '@sphereon/oid4vci-common'
|
|
1
|
+
import { AuthorizationChallengeCodeResponse, AuthzFlowType, toAuthorizationResponsePayload } from '@sphereon/oid4vci-common'
|
|
6
2
|
import { IBasicIssuerLocaleBranding, Identity, IIssuerLocaleBranding, Party } from '@sphereon/ssi-sdk.data-store'
|
|
7
3
|
import { assign, createMachine, DoneInvokeEvent, interpret } from 'xstate'
|
|
8
4
|
import { translate } from '../localization/Localization'
|
|
@@ -456,18 +452,20 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
456
452
|
},
|
|
457
453
|
],
|
|
458
454
|
},
|
|
459
|
-
[OID4VCIMachineStates.startFirstPartApplicationFlow]
|
|
455
|
+
[OID4VCIMachineStates.startFirstPartApplicationFlow]: {
|
|
460
456
|
id: OID4VCIMachineStates.startFirstPartApplicationFlow,
|
|
461
457
|
invoke: {
|
|
462
458
|
src: OID4VCIMachineServices.startFirstPartApplicationFlow,
|
|
463
459
|
onDone: [
|
|
464
460
|
{
|
|
465
461
|
target: OID4VCIMachineStates.aborted,
|
|
466
|
-
cond: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<FirstPartyMachineStateTypes>): boolean =>
|
|
462
|
+
cond: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<FirstPartyMachineStateTypes>): boolean =>
|
|
463
|
+
_event.data === FirstPartyMachineStateTypes.aborted,
|
|
467
464
|
},
|
|
468
465
|
{
|
|
469
466
|
target: OID4VCIMachineStates.declined,
|
|
470
|
-
cond: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<FirstPartyMachineStateTypes>): boolean =>
|
|
467
|
+
cond: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<FirstPartyMachineStateTypes>): boolean =>
|
|
468
|
+
_event.data === FirstPartyMachineStateTypes.declined,
|
|
471
469
|
},
|
|
472
470
|
{
|
|
473
471
|
target: OID4VCIMachineStates.getCredentials,
|
|
@@ -475,9 +473,9 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
475
473
|
openID4VCIClientState: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeCodeResponse>) => {
|
|
476
474
|
const authorizationCodeResponse = toAuthorizationResponsePayload(_event.data)
|
|
477
475
|
return { ..._ctx.openID4VCIClientState!, authorizationCodeResponse }
|
|
478
|
-
}
|
|
479
|
-
})
|
|
480
|
-
}
|
|
476
|
+
},
|
|
477
|
+
}),
|
|
478
|
+
},
|
|
481
479
|
],
|
|
482
480
|
onError: {
|
|
483
481
|
target: OID4VCIMachineStates.handleError,
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { CredentialsSupportedDisplay, NameAndLocale } from '@sphereon/oid4vci-common'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
IBasicCredentialLocaleBranding,
|
|
5
|
-
IBasicIssuerLocaleBranding
|
|
6
|
-
} from '@sphereon/ssi-sdk.data-store'
|
|
7
|
-
import {
|
|
8
|
-
SdJwtClaimDisplayMetadata,
|
|
9
|
-
SdJwtClaimMetadata,
|
|
10
|
-
SdJwtClaimPath,
|
|
11
|
-
SdJwtTypeDisplayMetadata
|
|
12
|
-
} from '@sphereon/ssi-types'
|
|
2
|
+
import { IBasicCredentialClaim, IBasicCredentialLocaleBranding, IBasicIssuerLocaleBranding } from '@sphereon/ssi-sdk.data-store'
|
|
3
|
+
import { SdJwtClaimDisplayMetadata, SdJwtClaimMetadata, SdJwtClaimPath, SdJwtTypeDisplayMetadata } from '@sphereon/ssi-types'
|
|
13
4
|
import {
|
|
14
5
|
IssuerLocaleBrandingFromArgs,
|
|
15
6
|
Oid4vciCombineDisplayLocalesFromArgs,
|
|
@@ -26,7 +17,9 @@ import {
|
|
|
26
17
|
|
|
27
18
|
// FIXME should we not move this to the branding plugin?
|
|
28
19
|
|
|
29
|
-
export const oid4vciGetCredentialBrandingFrom = async (
|
|
20
|
+
export const oid4vciGetCredentialBrandingFrom = async (
|
|
21
|
+
args: Oid4vciGetCredentialBrandingFromArgs,
|
|
22
|
+
): Promise<Array<IBasicCredentialLocaleBranding>> => {
|
|
30
23
|
const { credentialDisplay, issuerCredentialSubject } = args
|
|
31
24
|
|
|
32
25
|
return oid4vciCombineDisplayLocalesFrom({
|
|
@@ -35,7 +28,9 @@ export const oid4vciGetCredentialBrandingFrom = async (args: Oid4vciGetCredentia
|
|
|
35
28
|
})
|
|
36
29
|
}
|
|
37
30
|
|
|
38
|
-
export const oid4vciCredentialDisplayLocalesFrom = async (
|
|
31
|
+
export const oid4vciCredentialDisplayLocalesFrom = async (
|
|
32
|
+
args: Oid4vciCredentialDisplayLocalesFromArgs,
|
|
33
|
+
): Promise<Map<string, CredentialsSupportedDisplay>> => {
|
|
39
34
|
const { credentialDisplay } = args
|
|
40
35
|
return credentialDisplay.reduce((localeDisplays, display) => {
|
|
41
36
|
const localeKey = display.locale || ''
|
|
@@ -44,7 +39,9 @@ export const oid4vciCredentialDisplayLocalesFrom = async (args: Oid4vciCredentia
|
|
|
44
39
|
}, new Map<string, CredentialsSupportedDisplay>())
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
export const oid4vciIssuerCredentialSubjectLocalesFrom = async (
|
|
42
|
+
export const oid4vciIssuerCredentialSubjectLocalesFrom = async (
|
|
43
|
+
args: Oid4vciIssuerCredentialSubjectLocalesFromArgs,
|
|
44
|
+
): Promise<Map<string, Array<IBasicCredentialClaim>>> => {
|
|
48
45
|
const { issuerCredentialSubject } = args
|
|
49
46
|
const localeClaims = new Map<string, Array<IBasicCredentialClaim>>()
|
|
50
47
|
|
|
@@ -125,7 +122,9 @@ export const oid4vciCredentialLocaleBrandingFrom = async (args: Oid4vciCredentia
|
|
|
125
122
|
}
|
|
126
123
|
}
|
|
127
124
|
|
|
128
|
-
export const oid4vciCombineDisplayLocalesFrom = async (
|
|
125
|
+
export const oid4vciCombineDisplayLocalesFrom = async (
|
|
126
|
+
args: Oid4vciCombineDisplayLocalesFromArgs,
|
|
127
|
+
): Promise<Array<IBasicCredentialLocaleBranding>> => {
|
|
129
128
|
const {
|
|
130
129
|
credentialDisplayLocales = new Map<string, CredentialsSupportedDisplay>(),
|
|
131
130
|
issuerCredentialSubjectLocales = new Map<string, Array<IBasicCredentialClaim>>(),
|
|
@@ -156,7 +155,9 @@ export const sdJwtGetCredentialBrandingFrom = async (args: SdJwtGetCredentialBra
|
|
|
156
155
|
})
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
export const sdJwtCredentialDisplayLocalesFrom = async (
|
|
158
|
+
export const sdJwtCredentialDisplayLocalesFrom = async (
|
|
159
|
+
args: SdJwtCredentialDisplayLocalesFromArgs,
|
|
160
|
+
): Promise<Map<string, SdJwtTypeDisplayMetadata>> => {
|
|
160
161
|
const { credentialDisplay } = args
|
|
161
162
|
return credentialDisplay.reduce((localeDisplays, display) => {
|
|
162
163
|
const localeKey = display.lang || ''
|
|
@@ -165,14 +166,16 @@ export const sdJwtCredentialDisplayLocalesFrom = async (args: SdJwtCredentialDis
|
|
|
165
166
|
}, new Map<string, SdJwtTypeDisplayMetadata>())
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
export const sdJwtCredentialClaimLocalesFrom = async (
|
|
169
|
+
export const sdJwtCredentialClaimLocalesFrom = async (
|
|
170
|
+
args: SdJwtCredentialClaimLocalesFromArgs,
|
|
171
|
+
): Promise<Map<string, Array<IBasicCredentialClaim>>> => {
|
|
169
172
|
const { claimsMetadata } = args
|
|
170
173
|
const localeClaims = new Map<string, Array<IBasicCredentialClaim>>()
|
|
171
174
|
|
|
172
175
|
claimsMetadata.forEach((claim: SdJwtClaimMetadata): void => {
|
|
173
176
|
claim.display?.forEach((display: SdJwtClaimDisplayMetadata): void => {
|
|
174
|
-
const { lang = '', label } = display
|
|
175
|
-
const key = claim.path.map((value: SdJwtClaimPath) => String(value)).join('.')
|
|
177
|
+
const { lang = '', label } = display
|
|
178
|
+
const key = claim.path.map((value: SdJwtClaimPath) => String(value)).join('.')
|
|
176
179
|
if (!localeClaims.has(lang)) {
|
|
177
180
|
localeClaims.set(lang, [])
|
|
178
181
|
}
|
|
@@ -180,7 +183,7 @@ export const sdJwtCredentialClaimLocalesFrom = async (args: SdJwtCredentialClaim
|
|
|
180
183
|
})
|
|
181
184
|
})
|
|
182
185
|
|
|
183
|
-
return localeClaims
|
|
186
|
+
return localeClaims
|
|
184
187
|
}
|
|
185
188
|
|
|
186
189
|
export const sdJwtCredentialLocaleBrandingFrom = async (args: SdJwtCredentialLocaleBrandingFromArgs): Promise<IBasicCredentialLocaleBranding> => {
|
|
@@ -213,17 +216,15 @@ export const sdJwtCredentialLocaleBrandingFrom = async (args: SdJwtCredentialLoc
|
|
|
213
216
|
}),
|
|
214
217
|
...(credentialDisplay.rendering?.simple?.background_color && {
|
|
215
218
|
background: {
|
|
216
|
-
color: credentialDisplay.rendering.simple.background_color
|
|
219
|
+
color: credentialDisplay.rendering.simple.background_color,
|
|
217
220
|
},
|
|
218
221
|
}),
|
|
219
222
|
}
|
|
220
223
|
}
|
|
221
224
|
|
|
222
225
|
export const sdJwtCombineDisplayLocalesFrom = async (args: SdJwtCombineDisplayLocalesFromArgs): Promise<Array<IBasicCredentialLocaleBranding>> => {
|
|
223
|
-
const {
|
|
224
|
-
|
|
225
|
-
claimsMetadata = new Map<string, Array<IBasicCredentialClaim>>(),
|
|
226
|
-
} = args
|
|
226
|
+
const { credentialDisplayLocales = new Map<string, SdJwtTypeDisplayMetadata>(), claimsMetadata = new Map<string, Array<IBasicCredentialClaim>>() } =
|
|
227
|
+
args
|
|
227
228
|
|
|
228
229
|
const locales: Array<string> = Array.from(new Set([...claimsMetadata.keys(), ...credentialDisplayLocales.keys()]))
|
|
229
230
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
GetSiopRequestArgs,
|
|
10
10
|
SendAuthorizationChallengeRequestArgs,
|
|
11
11
|
SendAuthorizationResponseArgs,
|
|
12
|
-
SiopV2AuthorizationRequestData
|
|
12
|
+
SiopV2AuthorizationRequestData,
|
|
13
13
|
} from '../types/FirstPartyMachine'
|
|
14
14
|
|
|
15
15
|
export const sendAuthorizationChallengeRequest = async (args: SendAuthorizationChallengeRequestArgs): Promise<AuthorizationChallengeCodeResponse> => {
|
|
@@ -19,31 +19,32 @@ export const sendAuthorizationChallengeRequest = async (args: SendAuthorizationC
|
|
|
19
19
|
return oid4vciClient.acquireAuthorizationChallengeCode({
|
|
20
20
|
clientId: oid4vciClient.clientId ?? uuidv4(),
|
|
21
21
|
...(authSession && { authSession }),
|
|
22
|
-
...(!authSession &&
|
|
22
|
+
...(!authSession &&
|
|
23
|
+
openID4VCIClientState.credentialOffer?.preAuthorizedCode && { issuerState: openID4VCIClientState.credentialOffer?.preAuthorizedCode }),
|
|
23
24
|
...(!authSession && openID4VCIClientState.credentialOffer?.issuerState && { issuerState: openID4VCIClientState.credentialOffer?.issuerState }),
|
|
24
|
-
...(presentationDuringIssuanceSession && { presentationDuringIssuanceSession })
|
|
25
|
+
...(presentationDuringIssuanceSession && { presentationDuringIssuanceSession }),
|
|
25
26
|
})
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
export const createConfig = async (args: CreateConfigArgs, context: RequiredContext): Promise<CreateConfigResult> => {
|
|
29
|
-
const { presentationUri } = args
|
|
30
|
+
const { presentationUri } = args
|
|
30
31
|
|
|
31
32
|
if (!presentationUri) {
|
|
32
|
-
return Promise.reject(Error('Missing presentation uri in context'))
|
|
33
|
+
return Promise.reject(Error('Missing presentation uri in context'))
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
return context.agent.siopCreateConfig({ url: presentationUri })
|
|
36
|
-
}
|
|
37
|
+
}
|
|
37
38
|
|
|
38
39
|
export const getSiopRequest = async (args: GetSiopRequestArgs, context: RequiredContext): Promise<SiopV2AuthorizationRequestData> => {
|
|
39
|
-
const {didAuthConfig, presentationUri} = args
|
|
40
|
+
const { didAuthConfig, presentationUri } = args
|
|
40
41
|
|
|
41
42
|
if (presentationUri === undefined) {
|
|
42
|
-
return Promise.reject(Error('Missing presentation uri in context'))
|
|
43
|
+
return Promise.reject(Error('Missing presentation uri in context'))
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
if (didAuthConfig === undefined) {
|
|
46
|
-
return Promise.reject(Error('Missing did auth config in context'))
|
|
47
|
+
return Promise.reject(Error('Missing did auth config in context'))
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
return context.agent.siopGetSiopRequest({ didAuthConfig, url: presentationUri })
|
|
@@ -56,7 +57,7 @@ export const sendAuthorizationResponse = async (args: SendAuthorizationResponseA
|
|
|
56
57
|
authorizationRequestData,
|
|
57
58
|
selectedCredentials,
|
|
58
59
|
didAuthConfig,
|
|
59
|
-
isFirstParty: true
|
|
60
|
+
isFirstParty: true,
|
|
60
61
|
})
|
|
61
62
|
|
|
62
63
|
return (<AuthorizationChallengeValidationResponse>responseData.body).presentation_during_issuance_session
|