@sphereon/ssi-sdk.oid4vci-holder 0.32.1-next.13 → 0.32.1-next.141
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 +24 -16
- package/dist/agent/OID4VCIHolder.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/link-handler/index.d.ts +3 -2
- package/dist/link-handler/index.d.ts.map +1 -1
- package/dist/link-handler/index.js +2 -1
- package/dist/link-handler/index.js.map +1 -1
- package/dist/listeners/headlessStateNavListener.d.ts.map +1 -0
- package/dist/listeners/headlessStateNavListener.js.map +1 -0
- package/dist/localization/translations/en.json +5 -1
- package/dist/localization/translations/nl.json +5 -1
- package/dist/machines/firstPartyMachine.d.ts +15 -0
- package/dist/machines/firstPartyMachine.d.ts.map +1 -0
- package/dist/machines/firstPartyMachine.js +222 -0
- package/dist/machines/firstPartyMachine.js.map +1 -0
- package/dist/machines/oid4vciMachine.d.ts.map +1 -0
- package/dist/{machine → machines}/oid4vciMachine.js +58 -2
- package/dist/machines/oid4vciMachine.js.map +1 -0
- package/dist/mappers/OIDC4VCIBrandingMapper.d.ts.map +1 -0
- package/dist/mappers/OIDC4VCIBrandingMapper.js.map +1 -0
- package/dist/services/FirstPartyMachineServices.d.ts +9 -0
- package/dist/services/FirstPartyMachineServices.d.ts.map +1 -0
- package/dist/services/FirstPartyMachineServices.js +52 -0
- package/dist/services/FirstPartyMachineServices.js.map +1 -0
- package/dist/{agent → services}/OID4VCIHolderService.d.ts +3 -2
- package/dist/services/OID4VCIHolderService.d.ts.map +1 -0
- package/dist/{agent → services}/OID4VCIHolderService.js +46 -2
- package/dist/services/OID4VCIHolderService.js.map +1 -0
- package/dist/types/FirstPartyMachine.d.ts +112 -0
- package/dist/types/FirstPartyMachine.d.ts.map +1 -0
- package/dist/types/FirstPartyMachine.js +30 -0
- package/dist/types/FirstPartyMachine.js.map +1 -0
- package/dist/types/IOID4VCIHolder.d.ts +20 -9
- package/dist/types/IOID4VCIHolder.d.ts.map +1 -1
- package/dist/types/IOID4VCIHolder.js +3 -1
- package/dist/types/IOID4VCIHolder.js.map +1 -1
- package/package.json +19 -16
- package/src/agent/OID4VCIHolder.ts +35 -20
- package/src/index.ts +4 -2
- package/src/link-handler/index.ts +12 -5
- package/src/localization/translations/en.json +5 -1
- package/src/localization/translations/nl.json +5 -1
- package/src/machines/firstPartyMachine.ts +287 -0
- package/src/{machine → machines}/oid4vciMachine.ts +64 -3
- package/src/services/FirstPartyMachineServices.ts +63 -0
- package/src/{agent → services}/OID4VCIHolderService.ts +48 -1
- package/src/types/FirstPartyMachine.ts +169 -0
- package/src/types/IOID4VCIHolder.ts +40 -30
- package/dist/agent/OID4VCIHolderService.d.ts.map +0 -1
- package/dist/agent/OID4VCIHolderService.js.map +0 -1
- package/dist/agent/OIDC4VCIBrandingMapper.d.ts.map +0 -1
- package/dist/agent/OIDC4VCIBrandingMapper.js.map +0 -1
- package/dist/machine/headlessStateNavListener.d.ts.map +0 -1
- package/dist/machine/headlessStateNavListener.js.map +0 -1
- package/dist/machine/oid4vciMachine.d.ts.map +0 -1
- package/dist/machine/oid4vciMachine.js.map +0 -1
- /package/dist/{machine → listeners}/headlessStateNavListener.d.ts +0 -0
- /package/dist/{machine → listeners}/headlessStateNavListener.js +0 -0
- /package/dist/{machine → machines}/oid4vciMachine.d.ts +0 -0
- /package/dist/{agent → mappers}/OIDC4VCIBrandingMapper.d.ts +0 -0
- /package/dist/{agent → mappers}/OIDC4VCIBrandingMapper.js +0 -0
- /package/src/{machine → listeners}/headlessStateNavListener.ts +0 -0
- /package/src/{agent → mappers}/OIDC4VCIBrandingMapper.ts +0 -0
|
@@ -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,
|
|
@@ -70,12 +72,12 @@ import {
|
|
|
70
72
|
import { asArray, computeEntryHash } from '@veramo/utils'
|
|
71
73
|
import { decodeJWT } from 'did-jwt'
|
|
72
74
|
import { v4 as uuidv4 } from 'uuid'
|
|
73
|
-
import { OID4VCIMachine } from '../
|
|
75
|
+
import { OID4VCIMachine } from '../machines/oid4vciMachine'
|
|
74
76
|
import {
|
|
75
77
|
AddContactIdentityArgs,
|
|
76
78
|
AssertValidCredentialsArgs,
|
|
77
79
|
Attribute,
|
|
78
|
-
|
|
80
|
+
CreateCredentialsToSelectFromArgs,
|
|
79
81
|
CredentialToAccept,
|
|
80
82
|
CredentialToSelectFromResult,
|
|
81
83
|
GetContactArgs,
|
|
@@ -91,6 +93,8 @@ import {
|
|
|
91
93
|
OID4VCIHolderOptions,
|
|
92
94
|
OID4VCIMachine as OID4VCIMachineId,
|
|
93
95
|
OID4VCIMachineInstanceOpts,
|
|
96
|
+
OID4VCIMachineServiceDefinitions,
|
|
97
|
+
OID4VCIMachineServices,
|
|
94
98
|
OnContactIdentityCreatedArgs,
|
|
95
99
|
OnCredentialStoredArgs,
|
|
96
100
|
OnIdentifierCreatedArgs,
|
|
@@ -98,13 +102,14 @@ import {
|
|
|
98
102
|
RequestType,
|
|
99
103
|
RequiredContext,
|
|
100
104
|
SendNotificationArgs,
|
|
105
|
+
StartFirstPartApplicationMachine,
|
|
101
106
|
StartResult,
|
|
102
107
|
StoreCredentialBrandingArgs,
|
|
103
108
|
StoreCredentialsArgs,
|
|
104
109
|
StoreIssuerBrandingArgs,
|
|
105
110
|
VerificationResult,
|
|
106
111
|
VerifyEBSICredentialIssuerArgs,
|
|
107
|
-
VerifyEBSICredentialIssuerResult
|
|
112
|
+
VerifyEBSICredentialIssuerResult
|
|
108
113
|
} from '../types/IOID4VCIHolder'
|
|
109
114
|
import {
|
|
110
115
|
getBasicIssuerLocaleBranding,
|
|
@@ -115,8 +120,8 @@ import {
|
|
|
115
120
|
mapCredentialToAccept,
|
|
116
121
|
selectCredentialLocaleBranding,
|
|
117
122
|
verifyCredentialToAccept,
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
startFirstPartApplicationMachine
|
|
124
|
+
} from '../services/OID4VCIHolderService'
|
|
120
125
|
import 'cross-fetch/polyfill'
|
|
121
126
|
|
|
122
127
|
/**
|
|
@@ -307,8 +312,8 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
307
312
|
*/
|
|
308
313
|
private async oid4vciHolderGetMachineInterpreter(opts: OID4VCIMachineInstanceOpts, context: RequiredContext): Promise<OID4VCIMachineId> {
|
|
309
314
|
const authorizationRequestOpts = { ...this.defaultAuthorizationRequestOpts, ...opts.authorizationRequestOpts }
|
|
310
|
-
const services = {
|
|
311
|
-
start: (args: PrepareStartArgs) =>
|
|
315
|
+
const services: OID4VCIMachineServiceDefinitions = {
|
|
316
|
+
[OID4VCIMachineServices.start]: (args: PrepareStartArgs) =>
|
|
312
317
|
this.oid4vciHolderStart(
|
|
313
318
|
{
|
|
314
319
|
...args,
|
|
@@ -316,18 +321,18 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
316
321
|
},
|
|
317
322
|
context,
|
|
318
323
|
),
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
addContactIdentity: (args: AddContactIdentityArgs) => this.oid4vciHolderAddContactIdentity(args, context),
|
|
324
|
-
getIssuerBranding: (args: GetIssuerBrandingArgs) => this.oid4vciHolderGetIssuerBranding(args, context),
|
|
325
|
-
storeIssuerBranding: (args: StoreIssuerBrandingArgs) => this.oid4vciHolderStoreIssuerBranding(args, context),
|
|
326
|
-
assertValidCredentials: (args: AssertValidCredentialsArgs) => this.oid4vciHolderAssertValidCredentials(args, context),
|
|
327
|
-
storeCredentialBranding: (args: StoreCredentialBrandingArgs) => this.oid4vciHolderStoreCredentialBranding(args, context),
|
|
328
|
-
storeCredentials: (args: StoreCredentialsArgs) => this.oid4vciHolderStoreCredentials(args, context),
|
|
329
|
-
sendNotification: (args: SendNotificationArgs) => this.oid4vciHolderSendNotification(args, context),
|
|
330
|
-
getFederationTrust: (args: GetFederationTrustArgs) => this.getFederationTrust(args, context),
|
|
324
|
+
[OID4VCIMachineServices.startFirstPartApplicationFlow]: (args: StartFirstPartApplicationMachine) => startFirstPartApplicationMachine({ ...args, stateNavigationListener: opts.firstPartyStateNavigationListener }, context),
|
|
325
|
+
[OID4VCIMachineServices.createCredentialsToSelectFrom]: (args: CreateCredentialsToSelectFromArgs) => this.oid4vciHolderCreateCredentialsToSelectFrom(args, context),
|
|
326
|
+
[OID4VCIMachineServices.getContact]: (args: GetContactArgs) => this.oid4vciHolderGetContact(args, context),
|
|
327
|
+
[OID4VCIMachineServices.getCredentials]: (args: GetCredentialsArgs) => this.oid4vciHolderGetCredentials({ accessTokenOpts: args.accessTokenOpts ?? opts.accessTokenOpts, ...args }, context),
|
|
328
|
+
[OID4VCIMachineServices.addContactIdentity]: (args: AddContactIdentityArgs) => this.oid4vciHolderAddContactIdentity(args, context),
|
|
329
|
+
[OID4VCIMachineServices.getIssuerBranding]: (args: GetIssuerBrandingArgs) => this.oid4vciHolderGetIssuerBranding(args, context),
|
|
330
|
+
[OID4VCIMachineServices.storeIssuerBranding]: (args: StoreIssuerBrandingArgs) => this.oid4vciHolderStoreIssuerBranding(args, context),
|
|
331
|
+
[OID4VCIMachineServices.assertValidCredentials]: (args: AssertValidCredentialsArgs) => this.oid4vciHolderAssertValidCredentials(args, context),
|
|
332
|
+
[OID4VCIMachineServices.storeCredentialBranding]: (args: StoreCredentialBrandingArgs) => this.oid4vciHolderStoreCredentialBranding(args, context),
|
|
333
|
+
[OID4VCIMachineServices.storeCredentials]: (args: StoreCredentialsArgs) => this.oid4vciHolderStoreCredentials(args, context),
|
|
334
|
+
[OID4VCIMachineServices.sendNotification]: (args: SendNotificationArgs) => this.oid4vciHolderSendNotification(args, context),
|
|
335
|
+
[OID4VCIMachineServices.getFederationTrust]: (args: GetFederationTrustArgs) => this.getFederationTrust(args, context),
|
|
331
336
|
}
|
|
332
337
|
|
|
333
338
|
const oid4vciMachineInstanceArgs: OID4VCIMachineInstanceOpts = {
|
|
@@ -463,7 +468,7 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
463
468
|
}
|
|
464
469
|
|
|
465
470
|
private async oid4vciHolderCreateCredentialsToSelectFrom(
|
|
466
|
-
args:
|
|
471
|
+
args: CreateCredentialsToSelectFromArgs,
|
|
467
472
|
context: RequiredContext,
|
|
468
473
|
): Promise<Array<CredentialToSelectFromResult>> {
|
|
469
474
|
const { credentialBranding, locale, selectedCredentials /*, openID4VCIClientState*/, credentialsSupported } = args
|
|
@@ -675,7 +680,10 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
675
680
|
if (!credentialTypes || credentialTypes.length === 0) {
|
|
676
681
|
return Promise.reject(Error('cannot determine credential id to request'))
|
|
677
682
|
}
|
|
683
|
+
|
|
684
|
+
const credentialDefinition = this.getCredentialDefinition(issuanceOpt)
|
|
678
685
|
const credentialResponse = await client.acquireCredentials({
|
|
686
|
+
...(credentialDefinition && { context: credentialDefinition['@context'] }),
|
|
679
687
|
credentialTypes,
|
|
680
688
|
proofCallbacks: callbacks,
|
|
681
689
|
format: issuanceOpt.format,
|
|
@@ -1127,4 +1135,11 @@ export class OID4VCIHolder implements IAgentPlugin {
|
|
|
1127
1135
|
}
|
|
1128
1136
|
return undefined
|
|
1129
1137
|
}
|
|
1138
|
+
|
|
1139
|
+
private getCredentialDefinition(issuanceOpt: IssuanceOpts): CredentialDefinitionJwtVcJsonLdAndLdpVcV1_0_13 | undefined {
|
|
1140
|
+
if (issuanceOpt.format == 'ldp_vc' || issuanceOpt.format == 'jwt_vc_json-ld') {
|
|
1141
|
+
return (issuanceOpt as CredentialConfigurationSupportedJwtVcJsonLdAndLdpVcV1_0_13).credential_definition
|
|
1142
|
+
}
|
|
1143
|
+
return undefined
|
|
1144
|
+
}
|
|
1130
1145
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export { OID4VCIHolder, oid4vciHolderContextMethods, signCallback } from './agent/OID4VCIHolder'
|
|
6
|
-
export * from './
|
|
6
|
+
export * from './services/OID4VCIHolderService'
|
|
7
|
+
export * from './services/FirstPartyMachineServices'
|
|
7
8
|
export * from './types/IOID4VCIHolder'
|
|
8
|
-
export * from './
|
|
9
|
+
export * from './types/FirstPartyMachine'
|
|
10
|
+
export * from './listeners/headlessStateNavListener'
|
|
9
11
|
export * from './link-handler'
|
|
@@ -3,23 +3,28 @@ 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 {
|
|
6
|
+
import {
|
|
7
|
+
GetMachineArgs,
|
|
8
|
+
IOID4VCIHolder,
|
|
9
|
+
OID4VCIMachineEvents,
|
|
10
|
+
OID4VCIMachineStateNavigationListener
|
|
11
|
+
} from '../types/IOID4VCIHolder'
|
|
12
|
+
import { FirstPartyMachineStateNavigationListener } from '../types/FirstPartyMachine'
|
|
7
13
|
|
|
8
14
|
/**
|
|
9
15
|
* This handler only handles credential offer links (either by value or by reference)
|
|
10
16
|
*/
|
|
11
17
|
export class OID4VCIHolderLinkHandler extends LinkHandlerAdapter {
|
|
12
18
|
private readonly context: IAgentContext<IOID4VCIHolder & IMachineStatePersistence>
|
|
13
|
-
private readonly stateNavigationListener
|
|
14
|
-
|
|
15
|
-
| undefined
|
|
19
|
+
private readonly stateNavigationListener?: OID4VCIMachineStateNavigationListener
|
|
20
|
+
private readonly firstPartyStateNavigationListener?: FirstPartyMachineStateNavigationListener
|
|
16
21
|
private readonly noStateMachinePersistence: boolean
|
|
17
22
|
private readonly authorizationRequestOpts?: AuthorizationRequestOpts
|
|
18
23
|
private readonly clientOpts?: AuthorizationServerClientOpts
|
|
19
24
|
private readonly trustAnchors?: Array<string>
|
|
20
25
|
|
|
21
26
|
constructor(
|
|
22
|
-
args: Pick<GetMachineArgs, 'stateNavigationListener' | 'authorizationRequestOpts' | 'clientOpts' | 'trustAnchors'> & {
|
|
27
|
+
args: Pick<GetMachineArgs, 'stateNavigationListener' | 'authorizationRequestOpts' | 'clientOpts' | 'trustAnchors' | 'firstPartyStateNavigationListener'> & {
|
|
23
28
|
priority?: number | DefaultLinkPriorities
|
|
24
29
|
protocols?: Array<string | RegExp>
|
|
25
30
|
noStateMachinePersistence?: boolean
|
|
@@ -32,6 +37,7 @@ export class OID4VCIHolderLinkHandler extends LinkHandlerAdapter {
|
|
|
32
37
|
this.context = args.context
|
|
33
38
|
this.noStateMachinePersistence = args.noStateMachinePersistence === true
|
|
34
39
|
this.stateNavigationListener = args.stateNavigationListener
|
|
40
|
+
this.firstPartyStateNavigationListener = args.firstPartyStateNavigationListener
|
|
35
41
|
this.trustAnchors = args.trustAnchors
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -63,6 +69,7 @@ export class OID4VCIHolderLinkHandler extends LinkHandlerAdapter {
|
|
|
63
69
|
authorizationRequestOpts: { ...this.authorizationRequestOpts, ...opts?.authorizationRequestOpts },
|
|
64
70
|
...((clientOpts.clientId || clientOpts.clientAssertionType) && { clientOpts: clientOpts as AuthorizationServerClientOpts }),
|
|
65
71
|
stateNavigationListener: this.stateNavigationListener,
|
|
72
|
+
firstPartyStateNavigationListener: this.firstPartyStateNavigationListener
|
|
66
73
|
})
|
|
67
74
|
|
|
68
75
|
const interpreter = oid4vciMachine.interpreter
|
|
@@ -11,5 +11,9 @@
|
|
|
11
11
|
"oid4vci_machine_initiation_error_title": "Initiate OID4VCI provider",
|
|
12
12
|
"oid4vci_machine_credential_verification_failed_message": "The credential verification resulted in an error.",
|
|
13
13
|
"oid4vci_machine_credential_verification_schema_failed_message": "The credential schema verification resulted in an error.",
|
|
14
|
-
"oid4vci_machine_retrieve_federation_trust_error_title": "Retrieve federation trust"
|
|
14
|
+
"oid4vci_machine_retrieve_federation_trust_error_title": "Retrieve federation trust",
|
|
15
|
+
"oid4vci_machine_first_party_error_title": "First party flow",
|
|
16
|
+
"oid4vci_machine_send_authorization_challenge_request_error_title": "Sending authorization challenge request",
|
|
17
|
+
"oid4vci_machine_create_config_error_title": "Creating siopV2 config",
|
|
18
|
+
"oid4vci_machine_get_request_error_title": "Getting siopV2 request"
|
|
15
19
|
}
|
|
@@ -10,5 +10,9 @@
|
|
|
10
10
|
"oid4vci_machine_credential_selection_error_title": "Credential selectie",
|
|
11
11
|
"oid4vci_machine_initiation_error_title": "Initiëren OID4VCI provider",
|
|
12
12
|
"oid4vci_machine_credential_verification_failed_message": "Verificatie van de credential leidde tot een fout.",
|
|
13
|
-
"oid4vci_machine_retrieve_federation_trust_error_title": "Ophalen federatievertrouwen"
|
|
13
|
+
"oid4vci_machine_retrieve_federation_trust_error_title": "Ophalen federatievertrouwen",
|
|
14
|
+
"oid4vci_machine_first_party_error_title": "Eerste partijstroom",
|
|
15
|
+
"oid4vci_machine_send_authorization_challenge_request_error_title": "Versturen autorisatie-uitdaging aanvraag",
|
|
16
|
+
"oid4vci_machine_create_config_error_title": "SiopV2-configuratie aanmaken",
|
|
17
|
+
"oid4vci_machine_get_request_error_title": "SiopV2-verzoek ophalen"
|
|
14
18
|
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { assign, createMachine, DoneInvokeEvent, interpret } from 'xstate'
|
|
2
|
+
import {
|
|
3
|
+
AuthorizationChallengeCodeResponse,
|
|
4
|
+
AuthorizationChallengeError,
|
|
5
|
+
AuthorizationChallengeErrorResponse
|
|
6
|
+
} from '@sphereon/oid4vci-common'
|
|
7
|
+
import { DidAuthConfig } from '@sphereon/ssi-sdk.data-store'
|
|
8
|
+
import { CreateConfigResult } from '@sphereon/ssi-sdk.siopv2-oid4vp-op-auth'
|
|
9
|
+
import {
|
|
10
|
+
createConfig,
|
|
11
|
+
getSiopRequest,
|
|
12
|
+
sendAuthorizationChallengeRequest,
|
|
13
|
+
sendAuthorizationResponse
|
|
14
|
+
} from '../services/FirstPartyMachineServices'
|
|
15
|
+
import { translate } from '../localization/Localization'
|
|
16
|
+
import { ErrorDetails } from '../types/IOID4VCIHolder'
|
|
17
|
+
import {
|
|
18
|
+
CreateConfigArgs,
|
|
19
|
+
CreateFirstPartyMachineOpts,
|
|
20
|
+
FirstPartyMachineContext,
|
|
21
|
+
FirstPartyMachineEvents,
|
|
22
|
+
FirstPartyMachineEventTypes,
|
|
23
|
+
FirstPartyMachineInterpreter,
|
|
24
|
+
FirstPartyMachineServices,
|
|
25
|
+
FirstPartyMachineState,
|
|
26
|
+
FirstPartyMachineStatesConfig,
|
|
27
|
+
FirstPartyMachineStateTypes,
|
|
28
|
+
FirstPartyMachineServiceDefinitions,
|
|
29
|
+
FirstPartyStateMachine,
|
|
30
|
+
GetSiopRequestArgs,
|
|
31
|
+
InstanceFirstPartyMachineOpts,
|
|
32
|
+
SiopV2AuthorizationRequestData,
|
|
33
|
+
SendAuthorizationResponseArgs,
|
|
34
|
+
FirstPartySelectCredentialsEvent
|
|
35
|
+
} from '../types/FirstPartyMachine'
|
|
36
|
+
|
|
37
|
+
const firstPartyMachineStates: FirstPartyMachineStatesConfig = {
|
|
38
|
+
[FirstPartyMachineStateTypes.sendAuthorizationChallengeRequest]: {
|
|
39
|
+
id: FirstPartyMachineStateTypes.sendAuthorizationChallengeRequest,
|
|
40
|
+
invoke: {
|
|
41
|
+
src: FirstPartyMachineServices.sendAuthorizationChallengeRequest,
|
|
42
|
+
onDone: {
|
|
43
|
+
target: FirstPartyMachineStateTypes.done,
|
|
44
|
+
actions: assign({
|
|
45
|
+
authorizationCodeResponse: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeCodeResponse>) => _event.data
|
|
46
|
+
})
|
|
47
|
+
},
|
|
48
|
+
onError: [
|
|
49
|
+
{
|
|
50
|
+
target: FirstPartyMachineStateTypes.createConfig,
|
|
51
|
+
cond: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>): boolean => _event.data.error === AuthorizationChallengeError.insufficient_authorization,
|
|
52
|
+
actions: assign({
|
|
53
|
+
authSession: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>) => _event.data.auth_session,
|
|
54
|
+
presentationUri: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeErrorResponse>) => _event.data.presentation,
|
|
55
|
+
}),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
target: FirstPartyMachineStateTypes.error,
|
|
59
|
+
actions: assign({
|
|
60
|
+
error: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<Error>): ErrorDetails => ({
|
|
61
|
+
title: translate('oid4vci_machine_send_authorization_challenge_request_error_title'),
|
|
62
|
+
message: _event.data.message,
|
|
63
|
+
stack: _event.data.stack,
|
|
64
|
+
}),
|
|
65
|
+
}),
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
[FirstPartyMachineStateTypes.createConfig]: {
|
|
71
|
+
id: FirstPartyMachineStateTypes.createConfig,
|
|
72
|
+
invoke: {
|
|
73
|
+
src: FirstPartyMachineServices.createConfig,
|
|
74
|
+
onDone: {
|
|
75
|
+
target: FirstPartyMachineStateTypes.getSiopRequest,
|
|
76
|
+
actions: assign({
|
|
77
|
+
didAuthConfig: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<DidAuthConfig>) => _event.data,
|
|
78
|
+
}),
|
|
79
|
+
},
|
|
80
|
+
onError: {
|
|
81
|
+
target: FirstPartyMachineStateTypes.error,
|
|
82
|
+
actions: assign({
|
|
83
|
+
error: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<Error>): ErrorDetails => ({
|
|
84
|
+
title: translate('oid4vci_machine_create_config_error_title'),
|
|
85
|
+
message: _event.data.message,
|
|
86
|
+
stack: _event.data.stack,
|
|
87
|
+
}),
|
|
88
|
+
}),
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
[FirstPartyMachineStateTypes.getSiopRequest]: {
|
|
93
|
+
id: FirstPartyMachineStateTypes.getSiopRequest,
|
|
94
|
+
invoke: {
|
|
95
|
+
src: FirstPartyMachineServices.getSiopRequest,
|
|
96
|
+
onDone: {
|
|
97
|
+
target: FirstPartyMachineStateTypes.selectCredentials,
|
|
98
|
+
actions: assign({
|
|
99
|
+
authorizationRequestData: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<SiopV2AuthorizationRequestData>) => _event.data,
|
|
100
|
+
}),
|
|
101
|
+
},
|
|
102
|
+
onError: {
|
|
103
|
+
target: FirstPartyMachineStateTypes.error,
|
|
104
|
+
actions: assign({
|
|
105
|
+
error: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<Error>): ErrorDetails => ({
|
|
106
|
+
title: translate('siopV2_machine_get_request_error_title'),
|
|
107
|
+
message: _event.data.message,
|
|
108
|
+
stack: _event.data.stack,
|
|
109
|
+
}),
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
[FirstPartyMachineStateTypes.selectCredentials]: {
|
|
115
|
+
id: FirstPartyMachineStateTypes.selectCredentials,
|
|
116
|
+
on: {
|
|
117
|
+
[FirstPartyMachineEvents.SET_SELECTED_CREDENTIALS]: {
|
|
118
|
+
actions: assign({selectedCredentials: (_ctx: FirstPartyMachineContext, _event: FirstPartySelectCredentialsEvent) => _event.data}),
|
|
119
|
+
},
|
|
120
|
+
[FirstPartyMachineEvents.NEXT]: {
|
|
121
|
+
target: FirstPartyMachineStateTypes.sendAuthorizationResponse,
|
|
122
|
+
},
|
|
123
|
+
[FirstPartyMachineEvents.DECLINE]: {
|
|
124
|
+
target: FirstPartyMachineStateTypes.declined,
|
|
125
|
+
},
|
|
126
|
+
[FirstPartyMachineEvents.PREVIOUS]: {
|
|
127
|
+
target: FirstPartyMachineStateTypes.aborted,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
[FirstPartyMachineStateTypes.sendAuthorizationResponse]: {
|
|
132
|
+
id: FirstPartyMachineStateTypes.sendAuthorizationResponse,
|
|
133
|
+
invoke: {
|
|
134
|
+
src: FirstPartyMachineServices.sendAuthorizationResponse,
|
|
135
|
+
onDone: {
|
|
136
|
+
target: FirstPartyMachineStateTypes.sendAuthorizationChallengeRequest,
|
|
137
|
+
actions: assign({
|
|
138
|
+
presentationDuringIssuanceSession: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<string>) => _event.data,
|
|
139
|
+
}),
|
|
140
|
+
},
|
|
141
|
+
onError: {
|
|
142
|
+
target: FirstPartyMachineStateTypes.error,
|
|
143
|
+
actions: assign({
|
|
144
|
+
error: (_ctx: FirstPartyMachineContext, _event: DoneInvokeEvent<Error>): ErrorDetails => ({
|
|
145
|
+
title: translate('oid4vci_machine_get_request_error_title'),
|
|
146
|
+
message: _event.data.message,
|
|
147
|
+
stack: _event.data.stack,
|
|
148
|
+
}),
|
|
149
|
+
}),
|
|
150
|
+
},
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
[FirstPartyMachineStateTypes.aborted]: {
|
|
154
|
+
id: FirstPartyMachineStateTypes.aborted,
|
|
155
|
+
type: 'final'
|
|
156
|
+
},
|
|
157
|
+
[FirstPartyMachineStateTypes.declined]: {
|
|
158
|
+
id: FirstPartyMachineStateTypes.declined,
|
|
159
|
+
type: 'final'
|
|
160
|
+
},
|
|
161
|
+
[FirstPartyMachineStateTypes.error]: {
|
|
162
|
+
id: FirstPartyMachineStateTypes.error,
|
|
163
|
+
type: 'final',
|
|
164
|
+
},
|
|
165
|
+
[FirstPartyMachineStateTypes.done]: {
|
|
166
|
+
id: FirstPartyMachineStateTypes.done,
|
|
167
|
+
type: 'final',
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const createFirstPartyActivationMachine = (opts: CreateFirstPartyMachineOpts): FirstPartyStateMachine => {
|
|
172
|
+
const initialContext: FirstPartyMachineContext = {
|
|
173
|
+
openID4VCIClientState: opts.openID4VCIClientState,
|
|
174
|
+
contact: opts.contact,
|
|
175
|
+
selectedCredentials: [],
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
return createMachine<FirstPartyMachineContext, FirstPartyMachineEventTypes>(
|
|
179
|
+
{
|
|
180
|
+
id: opts?.machineId ?? 'FirstParty',
|
|
181
|
+
predictableActionArguments: true,
|
|
182
|
+
initial: FirstPartyMachineStateTypes.sendAuthorizationChallengeRequest,
|
|
183
|
+
context: initialContext,
|
|
184
|
+
states: firstPartyMachineStates,
|
|
185
|
+
schema: {
|
|
186
|
+
events: {} as FirstPartyMachineEventTypes,
|
|
187
|
+
services: {} as {
|
|
188
|
+
[FirstPartyMachineServices.sendAuthorizationChallengeRequest]: {
|
|
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
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export class FirstPartyMachine {
|
|
207
|
+
private static _instance: FirstPartyMachineInterpreter | undefined;
|
|
208
|
+
|
|
209
|
+
static hasInstance(): boolean {
|
|
210
|
+
return FirstPartyMachine._instance !== undefined;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static get instance(): FirstPartyMachineInterpreter {
|
|
214
|
+
if (!FirstPartyMachine._instance) {
|
|
215
|
+
throw Error('Please initialize ESIMActivation machine first');
|
|
216
|
+
}
|
|
217
|
+
return FirstPartyMachine._instance;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static clearInstance(opts: {stop: boolean}) {
|
|
221
|
+
const {stop} = opts;
|
|
222
|
+
if (FirstPartyMachine.hasInstance()) {
|
|
223
|
+
if (stop) {
|
|
224
|
+
FirstPartyMachine.stopInstance();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
FirstPartyMachine._instance = undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
static stopInstance(): void {
|
|
231
|
+
if (!FirstPartyMachine.hasInstance()) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
FirstPartyMachine.instance.stop();
|
|
235
|
+
FirstPartyMachine._instance = undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public static newInstance(opts: InstanceFirstPartyMachineOpts): FirstPartyMachineInterpreter {
|
|
239
|
+
const { agentContext } = opts
|
|
240
|
+
const services: FirstPartyMachineServiceDefinitions = {
|
|
241
|
+
[FirstPartyMachineServices.sendAuthorizationChallengeRequest]: sendAuthorizationChallengeRequest,
|
|
242
|
+
[FirstPartyMachineServices.createConfig]: (args: CreateConfigArgs) => createConfig(args, agentContext),
|
|
243
|
+
[FirstPartyMachineServices.getSiopRequest]: (args: GetSiopRequestArgs) => getSiopRequest(args, agentContext),
|
|
244
|
+
[FirstPartyMachineServices.sendAuthorizationResponse]: (args: SendAuthorizationResponseArgs) => sendAuthorizationResponse(args, agentContext),
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const newInst: FirstPartyMachineInterpreter = interpret(
|
|
248
|
+
createFirstPartyActivationMachine(opts).withConfig({
|
|
249
|
+
services: {
|
|
250
|
+
...services,
|
|
251
|
+
...opts?.services,
|
|
252
|
+
},
|
|
253
|
+
guards: {
|
|
254
|
+
...opts?.guards,
|
|
255
|
+
},
|
|
256
|
+
}),
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
if (typeof opts?.subscription === 'function') {
|
|
260
|
+
newInst.onTransition(opts.subscription);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (opts?.requireCustomNavigationHook !== true) {
|
|
264
|
+
newInst.onTransition((snapshot: FirstPartyMachineState): void => {
|
|
265
|
+
if (opts?.stateNavigationListener) {
|
|
266
|
+
void opts.stateNavigationListener(newInst, snapshot)
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return newInst;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static getInstance(
|
|
275
|
+
opts: InstanceFirstPartyMachineOpts & {
|
|
276
|
+
requireExisting?: boolean;
|
|
277
|
+
},
|
|
278
|
+
): FirstPartyMachineInterpreter {
|
|
279
|
+
if (!FirstPartyMachine._instance) {
|
|
280
|
+
if (opts?.requireExisting === true) {
|
|
281
|
+
throw Error(`Existing FirstPartyMachine instance requested, but none was created at this point!`);
|
|
282
|
+
}
|
|
283
|
+
FirstPartyMachine._instance = FirstPartyMachine.newInstance(opts);
|
|
284
|
+
}
|
|
285
|
+
return FirstPartyMachine._instance;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AuthorizationChallengeCodeResponse,
|
|
3
|
+
AuthzFlowType,
|
|
4
|
+
toAuthorizationResponsePayload
|
|
5
|
+
} from '@sphereon/oid4vci-common'
|
|
2
6
|
import { IBasicIssuerLocaleBranding, Identity, IIssuerLocaleBranding, Party } from '@sphereon/ssi-sdk.data-store'
|
|
3
7
|
import { assign, createMachine, DoneInvokeEvent, interpret } from 'xstate'
|
|
4
8
|
import { translate } from '../localization/Localization'
|
|
@@ -29,6 +33,7 @@ import {
|
|
|
29
33
|
SetAuthorizationCodeURLEvent,
|
|
30
34
|
VerificationCodeEvent,
|
|
31
35
|
} from '../types/IOID4VCIHolder'
|
|
36
|
+
import { FirstPartyMachineStateTypes } from '../types/FirstPartyMachine'
|
|
32
37
|
|
|
33
38
|
const oid4vciHasNoContactGuard = (_ctx: OID4VCIMachineContext, _event: OID4VCIMachineEventTypes): boolean => {
|
|
34
39
|
const { contact } = _ctx
|
|
@@ -117,6 +122,10 @@ const oid4vciHasAuthorizationResponse = (ctx: OID4VCIMachineContext, _event: OID
|
|
|
117
122
|
return !!ctx.openID4VCIClientState?.authorizationCodeResponse
|
|
118
123
|
}
|
|
119
124
|
|
|
125
|
+
const oid4vciIsFirstPartyApplication = (ctx: OID4VCIMachineContext, _event: OID4VCIMachineEventTypes): boolean => {
|
|
126
|
+
return !!ctx.serverMetadata?.authorization_challenge_endpoint
|
|
127
|
+
}
|
|
128
|
+
|
|
120
129
|
const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMachine => {
|
|
121
130
|
const initialContext: OID4VCIMachineContext = {
|
|
122
131
|
// TODO WAL-671 we need to store the data from OpenIdProvider here in the context and make sure we can restart the machine with it and init the OpenIdProvider
|
|
@@ -153,7 +162,8 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
153
162
|
| { type: OID4VCIMachineGuards.hasSelectedCredentialsGuard }
|
|
154
163
|
| { type: OID4VCIMachineGuards.hasAuthorizationResponse }
|
|
155
164
|
| { type: OID4VCIMachineGuards.isOIDFOriginGuard }
|
|
156
|
-
| { type: OID4VCIMachineGuards.contactHasLowTrustGuard }
|
|
165
|
+
| { type: OID4VCIMachineGuards.contactHasLowTrustGuard }
|
|
166
|
+
| { type: OID4VCIMachineGuards.isFirstPartyApplication },
|
|
157
167
|
services: {} as {
|
|
158
168
|
[OID4VCIMachineServices.start]: {
|
|
159
169
|
data: StartResult
|
|
@@ -188,6 +198,9 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
188
198
|
[OID4VCIMachineServices.getIssuerBranding]: {
|
|
189
199
|
data: Array<IIssuerLocaleBranding | IBasicIssuerLocaleBranding>
|
|
190
200
|
}
|
|
201
|
+
[OID4VCIMachineServices.startFirstPartApplicationFlow]: {
|
|
202
|
+
data: void
|
|
203
|
+
}
|
|
191
204
|
},
|
|
192
205
|
},
|
|
193
206
|
context: initialContext,
|
|
@@ -332,6 +345,10 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
332
345
|
target: OID4VCIMachineStates.selectCredentials,
|
|
333
346
|
cond: OID4VCIMachineGuards.credentialsToSelectRequiredGuard,
|
|
334
347
|
},
|
|
348
|
+
{
|
|
349
|
+
target: OID4VCIMachineStates.startFirstPartApplicationFlow,
|
|
350
|
+
cond: OID4VCIMachineGuards.isFirstPartyApplication,
|
|
351
|
+
},
|
|
335
352
|
{
|
|
336
353
|
target: OID4VCIMachineStates.initiateAuthorizationRequest,
|
|
337
354
|
cond: OID4VCIMachineGuards.requireAuthorizationGuard,
|
|
@@ -422,6 +439,10 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
422
439
|
target: OID4VCIMachineStates.selectCredentials,
|
|
423
440
|
cond: OID4VCIMachineGuards.credentialsToSelectRequiredGuard,
|
|
424
441
|
},
|
|
442
|
+
{
|
|
443
|
+
target: OID4VCIMachineStates.startFirstPartApplicationFlow,
|
|
444
|
+
cond: OID4VCIMachineGuards.isFirstPartyApplication,
|
|
445
|
+
},
|
|
425
446
|
{
|
|
426
447
|
target: OID4VCIMachineStates.initiateAuthorizationRequest,
|
|
427
448
|
cond: OID4VCIMachineGuards.requireAuthorizationGuard,
|
|
@@ -435,6 +456,41 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
435
456
|
},
|
|
436
457
|
],
|
|
437
458
|
},
|
|
459
|
+
[OID4VCIMachineStates.startFirstPartApplicationFlow] :{
|
|
460
|
+
id: OID4VCIMachineStates.startFirstPartApplicationFlow,
|
|
461
|
+
invoke: {
|
|
462
|
+
src: OID4VCIMachineServices.startFirstPartApplicationFlow,
|
|
463
|
+
onDone: [
|
|
464
|
+
{
|
|
465
|
+
target: OID4VCIMachineStates.aborted,
|
|
466
|
+
cond: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<FirstPartyMachineStateTypes>): boolean => _event.data === FirstPartyMachineStateTypes.aborted,
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
target: OID4VCIMachineStates.declined,
|
|
470
|
+
cond: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<FirstPartyMachineStateTypes>): boolean => _event.data === FirstPartyMachineStateTypes.declined,
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
target: OID4VCIMachineStates.getCredentials,
|
|
474
|
+
actions: assign({
|
|
475
|
+
openID4VCIClientState: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<AuthorizationChallengeCodeResponse>) => {
|
|
476
|
+
const authorizationCodeResponse = toAuthorizationResponsePayload(_event.data)
|
|
477
|
+
return { ..._ctx.openID4VCIClientState!, authorizationCodeResponse }
|
|
478
|
+
}
|
|
479
|
+
})
|
|
480
|
+
}
|
|
481
|
+
],
|
|
482
|
+
onError: {
|
|
483
|
+
target: OID4VCIMachineStates.handleError,
|
|
484
|
+
actions: assign({
|
|
485
|
+
error: (_ctx: OID4VCIMachineContext, _event: DoneInvokeEvent<ErrorDetails>): ErrorDetails => ({
|
|
486
|
+
title: _event.data.title ?? translate('oid4vci_machine_first_party_error_title'),
|
|
487
|
+
message: _event.data.message,
|
|
488
|
+
stack: _event.data.stack,
|
|
489
|
+
}),
|
|
490
|
+
}),
|
|
491
|
+
},
|
|
492
|
+
},
|
|
493
|
+
},
|
|
438
494
|
[OID4VCIMachineStates.selectCredentials]: {
|
|
439
495
|
id: OID4VCIMachineStates.selectCredentials,
|
|
440
496
|
on: {
|
|
@@ -453,6 +509,10 @@ const createOID4VCIMachine = (opts?: CreateOID4VCIMachineOpts): OID4VCIStateMach
|
|
|
453
509
|
[OID4VCIMachineStates.transitionFromSelectingCredentials]: {
|
|
454
510
|
id: OID4VCIMachineStates.transitionFromSelectingCredentials,
|
|
455
511
|
always: [
|
|
512
|
+
{
|
|
513
|
+
target: OID4VCIMachineStates.startFirstPartApplicationFlow,
|
|
514
|
+
cond: OID4VCIMachineGuards.isFirstPartyApplication,
|
|
515
|
+
},
|
|
456
516
|
{
|
|
457
517
|
target: OID4VCIMachineStates.verifyPin,
|
|
458
518
|
cond: OID4VCIMachineGuards.requirePinGuard,
|
|
@@ -726,6 +786,7 @@ export class OID4VCIMachine {
|
|
|
726
786
|
oid4vciHasAuthorizationResponse,
|
|
727
787
|
oid4vciIsOIDFOriginGuard,
|
|
728
788
|
oid4vciContactHasLowTrustGuard,
|
|
789
|
+
oid4vciIsFirstPartyApplication,
|
|
729
790
|
...opts?.guards,
|
|
730
791
|
},
|
|
731
792
|
}),
|
|
@@ -737,7 +798,7 @@ export class OID4VCIMachine {
|
|
|
737
798
|
if (opts?.requireCustomNavigationHook !== true) {
|
|
738
799
|
if (typeof opts?.stateNavigationListener === 'function') {
|
|
739
800
|
interpreter.onTransition((snapshot: OID4VCIMachineState): void => {
|
|
740
|
-
if (opts?.stateNavigationListener
|
|
801
|
+
if (opts?.stateNavigationListener) {
|
|
741
802
|
opts.stateNavigationListener(interpreter, snapshot)
|
|
742
803
|
}
|
|
743
804
|
})
|