@sphereon/ssi-sdk-ext.identifier-resolution 0.24.1-unstable.75

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.
@@ -0,0 +1,69 @@
1
+ import { IAgentContext, IAgentPlugin, IDIDManager, IKeyManager } from '@veramo/core'
2
+ import { getManagedIdentifier } from '../functions'
3
+
4
+ import {
5
+ ManagedIdentifierResult,
6
+ ManagedIdentifierDidOpts,
7
+ ManagedIdentifierDidResult,
8
+ ManagedIdentifierJwkOpts,
9
+ ManagedIdentifierJwkResult,
10
+ ManagedIdentifierKidOpts,
11
+ ManagedIdentifierKidResult,
12
+ ManagedIdentifierOpts,
13
+ ManagedIdentifierX5cOpts,
14
+ ManagedIdentifierX5cResult,
15
+ schema,
16
+ } from '../index'
17
+ import { ExternalIdentifierOpts, IIdentifierResolution } from '../types/IIdentifierResolution'
18
+
19
+ /**
20
+ * @public
21
+ */
22
+ export class IdentifierResolution implements IAgentPlugin {
23
+ private readonly _crypto: Crypto
24
+
25
+ readonly schema = schema.IMnemonicInfoGenerator
26
+ readonly methods: IIdentifierResolution = {
27
+ identifierManagedGet: this.identifierGetManaged.bind(this),
28
+ identifierManagedGetByDid: this.identifierGetManagedByDid.bind(this),
29
+ identifierManagedGetByKid: this.identifierGetManagedByKid.bind(this),
30
+ identifierManagedGetByJwk: this.identifierGetManagedByJwk.bind(this),
31
+ identifierManagedGetByX5c: this.identifierGetManagedByX5c.bind(this),
32
+
33
+ identifierExternalResolve: this.identifierResolveExternal.bind(this),
34
+ }
35
+
36
+ /**
37
+ * TODO: Add a cache, as we are retrieving the same keys/info quite often
38
+ */
39
+ constructor({ crypto: cryptoArg }: { crypto: Crypto }) {
40
+ this._crypto = cryptoArg ?? global.crypto
41
+ }
42
+
43
+ private async identifierGetManaged(args: ManagedIdentifierOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierResult> {
44
+ return await getManagedIdentifier({ ...args, crypto: this._crypto }, context)
45
+ }
46
+
47
+ private async identifierGetManagedByDid(
48
+ args: ManagedIdentifierDidOpts,
49
+ context: IAgentContext<IKeyManager & IDIDManager>
50
+ ): Promise<ManagedIdentifierDidResult> {
51
+ return (await this.identifierGetManaged({ ...args, method: 'did' }, context)) as ManagedIdentifierDidResult
52
+ }
53
+
54
+ private async identifierGetManagedByKid(args: ManagedIdentifierKidOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierKidResult> {
55
+ return (await this.identifierGetManaged({ ...args, method: 'kid' }, context)) as ManagedIdentifierKidResult
56
+ }
57
+
58
+ private async identifierGetManagedByJwk(args: ManagedIdentifierJwkOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierJwkResult> {
59
+ return (await this.identifierGetManaged({ ...args, method: 'jwk' }, context)) as ManagedIdentifierJwkResult
60
+ }
61
+
62
+ private async identifierGetManagedByX5c(args: ManagedIdentifierX5cOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierX5cResult> {
63
+ return (await this.identifierGetManaged({ ...args, method: 'x5c' }, context)) as ManagedIdentifierX5cResult
64
+ }
65
+
66
+ private async identifierResolveExternal(args: ExternalIdentifierOpts, context: IAgentContext<IKeyManager>): Promise<any> {
67
+ return await getManagedIdentifier({ ...args, crypto: this._crypto }, context)
68
+ }
69
+ }
@@ -0,0 +1,267 @@
1
+ import { didDocumentToJwks, getAgentResolver, getFirstKeyWithRelation } from '@sphereon/ssi-sdk-ext.did-utils'
2
+ import { calculateJwkThumbprint, JWK, toJwk } from '@sphereon/ssi-sdk-ext.key-utils'
3
+ import { getSubjectDN, pemOrDerToX509Certificate, validateX509CertificateChain, X509ValidationResult } from '@sphereon/ssi-sdk-ext.x509-utils'
4
+ import { contextHasDidManager, contextHasKeyManager, contextHasPlugin } from '@sphereon/ssi-sdk.agent-config'
5
+ import { IParsedDID, parseDid } from '@sphereon/ssi-types'
6
+ import { IAgentContext, IDIDManager, IIdentifier, IKey, IKeyManager, IResolver } from '@veramo/core'
7
+ import { Certificate, CryptoEngine, setEngine } from 'pkijs'
8
+ import {
9
+ ExternalIdentifierDidOpts,
10
+ ExternalIdentifierDidResult,
11
+ ExternalIdentifierMethod,
12
+ ExternalIdentifierOpts,
13
+ ExternalIdentifierResult,
14
+ ExternalIdentifierX5cOpts,
15
+ ExternalIdentifierX5cResult,
16
+ ExternalJwkInfo,
17
+ isExternalIdentifierDidOpts,
18
+ isExternalIdentifierJwksUrlOpts,
19
+ isExternalIdentifierKidOpts,
20
+ isExternalIdentifierOidcDiscoveryOpts,
21
+ isExternalIdentifierX5cOpts,
22
+ isManagedIdentifierDidOpts,
23
+ isManagedIdentifierJwkOpts,
24
+ isManagedIdentifierKidOpts,
25
+ isManagedIdentifierX5cOpts,
26
+ ManagedIdentifierOpts,
27
+ ManagedIdentifierResult,
28
+ } from '../types/IIdentifierResolution'
29
+
30
+ export async function resolveExternalIdentifier(
31
+ opts: ExternalIdentifierOpts & {
32
+ crypto?: Crypto
33
+ },
34
+ context: IAgentContext<any>
35
+ ): Promise<ExternalIdentifierResult> {
36
+ let method: ExternalIdentifierMethod | undefined
37
+ if (isExternalIdentifierDidOpts(opts)) {
38
+ return resolveExternalDidIdentifier(opts, context)
39
+ } else if (isExternalIdentifierX5cOpts(opts)) {
40
+ return resolveExternalX5cIdentifier(opts, context)
41
+ } else if (isExternalIdentifierKidOpts(opts)) {
42
+ method = 'kid'
43
+ } else if (isExternalIdentifierJwksUrlOpts(opts)) {
44
+ method = 'jwks-url'
45
+ } else if (isExternalIdentifierOidcDiscoveryOpts(opts)) {
46
+ method = 'oidc-discovery'
47
+ }
48
+ throw Error(`External resolution method ${method} is not yet implemented`)
49
+ }
50
+
51
+ export async function resolveExternalX5cIdentifier(
52
+ opts: ExternalIdentifierX5cOpts & {
53
+ crypto?: Crypto
54
+ },
55
+ context: IAgentContext<IResolver & IDIDManager>
56
+ ): Promise<ExternalIdentifierX5cResult> {
57
+ if (!isExternalIdentifierX5cOpts(opts)) {
58
+ return Promise.reject('External x5c Identifier args need to be provided')
59
+ }
60
+ const verify = opts.verify ?? true
61
+ const x5c = opts.identifier
62
+ if (x5c.length === 0) {
63
+ return Promise.reject('Empty certification chain is now allowed')
64
+ }
65
+ const certificates = x5c.map(pemOrDerToX509Certificate)
66
+
67
+ let verificationResult: X509ValidationResult | undefined
68
+ let issuerJWK: JWK | undefined
69
+ let jwks: ExternalJwkInfo[] = []
70
+
71
+ if (verify) {
72
+ // We use the agent plugin if it is available as that is more powerful, but revert to the function otherwise
73
+ if (contextHasPlugin(context, 'verifyCertificateChain')) {
74
+ verificationResult = (await context.agent.verifyCertificateChain({
75
+ chain: opts.identifier,
76
+ trustAnchors: opts.trustAnchors ?? [],
77
+ verificationTime: opts.verificationTime,
78
+ })) as X509ValidationResult // We need to cast, as we know this is the value and we do not want to rely on the x509 plugin perse
79
+ } else {
80
+ verificationResult = await validateX509CertificateChain({
81
+ chain: opts.identifier,
82
+ trustAnchors: opts.trustAnchors ?? [],
83
+ verificationTime: opts.verificationTime,
84
+ })
85
+ }
86
+ if (verificationResult.certificateChain) {
87
+ jwks = verificationResult.certificateChain.map((cert) => {
88
+ return {
89
+ jwk: cert.publicKeyJWK,
90
+ kid: cert.subject.dn.DN,
91
+ jwkThumbprint: calculateJwkThumbprint(cert.publicKeyJWK),
92
+ } satisfies ExternalJwkInfo
93
+ })
94
+ }
95
+ }
96
+ if (!jwks) {
97
+ const cryptoEngine = new CryptoEngine({
98
+ name: 'identifier_resolver_external',
99
+ crypto: opts.crypto ?? global.crypto,
100
+ })
101
+ setEngine(cryptoEngine.name, cryptoEngine)
102
+ jwks = await Promise.all(
103
+ certificates.map(async (cert) => {
104
+ const pk = await cert.getPublicKey(undefined, cryptoEngine)
105
+ const jwk = (await cryptoEngine.exportKey('jwk', pk)) as JWK
106
+ return {
107
+ jwk,
108
+ kid: getSubjectDN(cert).DN,
109
+ jwkThumbprint: calculateJwkThumbprint({ jwk }),
110
+ } satisfies ExternalJwkInfo
111
+ })
112
+ )
113
+ }
114
+ if (jwks.length === 0) {
115
+ return Promise.reject('Empty certification chain is now allowed')
116
+ }
117
+ if (!issuerJWK) {
118
+ issuerJWK = jwks[0].jwk
119
+ }
120
+
121
+ return {
122
+ method: 'x5c',
123
+ verificationResult,
124
+ issuerJWK,
125
+ jwks,
126
+ certificates,
127
+ x5c,
128
+ }
129
+ }
130
+
131
+ export async function resolveExternalDidIdentifier(
132
+ opts: ExternalIdentifierDidOpts,
133
+ context: IAgentContext<IResolver & IDIDManager>
134
+ ): Promise<ExternalIdentifierDidResult> {
135
+ if (!isExternalIdentifierDidOpts(opts)) {
136
+ return Promise.reject('External DID Identifier args need to be provided')
137
+ } else if (!contextHasPlugin<IResolver & IDIDManager>(context, 'resolveDid')) {
138
+ return Promise.reject(Error(`Cannot get external DID identifier if DID resolver plugin is not enabled!`))
139
+ }
140
+ const { uniresolverResolution = false, localResolution = true, resolverResolution = true } = opts
141
+ const did = opts.identifier
142
+ let parsed: IParsedDID
143
+ try {
144
+ parsed = parseDid(did)
145
+ } catch (error: unknown) {
146
+ // Error from did resolution spec
147
+ return Promise.reject(error)
148
+ }
149
+ const didParsed = parsed
150
+ const didResolutionResult = await getAgentResolver(context, {
151
+ uniresolverResolution,
152
+ localResolution,
153
+ resolverResolution,
154
+ }).resolve(did)
155
+ const didDocument = didResolutionResult.didDocument ?? undefined
156
+ const didJwks = didDocument ? didDocumentToJwks(didDocument) : undefined
157
+ const jwks = didJwks
158
+ ? Array.from(new Set(Object.values(didJwks).flatMap((jwks) => jwks))).map((jwk) => {
159
+ return { jwk, jwkThumbprint: calculateJwkThumbprint({ jwk }), kid: jwk.kid }
160
+ })
161
+ : []
162
+
163
+ if (didResolutionResult?.didDocument) {
164
+ // @ts-ignore // Mandatory on the original object, but we already provide it directly
165
+ delete didResolutionResult['didDocument']
166
+ }
167
+ return {
168
+ method: 'did',
169
+ did,
170
+ jwks,
171
+ didJwks,
172
+ didDocument,
173
+ didResolutionResult,
174
+ didParsed,
175
+ }
176
+ }
177
+
178
+ export async function getManagedIdentifier(
179
+ opts: ManagedIdentifierOpts & {
180
+ crypto?: Crypto
181
+ },
182
+ context: IAgentContext<IKeyManager>
183
+ ): Promise<ManagedIdentifierResult> {
184
+ let { method } = opts
185
+ let identifier: IIdentifier | undefined = undefined
186
+ let keys: IKey[] | undefined = undefined
187
+ let key: IKey | undefined = undefined
188
+ let certificate: Certificate | undefined = undefined
189
+ let jwk: JWK | undefined = undefined
190
+ let jwkThumbprint: string | undefined = undefined
191
+ let x5c: string[] | undefined
192
+ let controllerKeyId: string | undefined = undefined
193
+ let did: string | undefined = undefined
194
+ const cryptoImpl = opts.crypto ?? crypto
195
+ if (isManagedIdentifierKidOpts(opts)) {
196
+ method = 'kid'
197
+ if (!contextHasKeyManager(context)) {
198
+ return Promise.reject(Error(`Cannot get Key/JWK identifier if KeyManager plugin is not enabled!`))
199
+ }
200
+ key = await context.agent.keyManagerGet({ kid: opts.kmsKeyRef ?? opts.identifier })
201
+ } else if (isManagedIdentifierDidOpts(opts)) {
202
+ method = 'did'
203
+ if (!contextHasDidManager(context)) {
204
+ return Promise.reject(Error(`Cannot get DID identifier if DID Manager plugin is not enabled!`))
205
+ }
206
+
207
+ if (typeof opts.identifier === 'string') {
208
+ identifier = await context.agent.didManagerGet({ did: opts.identifier.split('#')[0] })
209
+ } else {
210
+ identifier = opts.identifier
211
+ }
212
+ if (identifier) {
213
+ did = identifier.did
214
+ keys = identifier?.keys // fixme: We really want to return the vmRelationship keys here actually
215
+ key = await getFirstKeyWithRelation(
216
+ {
217
+ ...opts,
218
+ identifier,
219
+ vmRelationship: opts.vmRelationship ?? 'verificationMethod',
220
+ },
221
+ context
222
+ )
223
+ controllerKeyId = identifier.controllerKeyId
224
+ }
225
+ } else if (isManagedIdentifierJwkOpts(opts)) {
226
+ method = 'jwk'
227
+ if (!contextHasKeyManager(context)) {
228
+ return Promise.reject(Error(`Cannot get Key/JWK identifier if KeyManager plugin is not enabled!`))
229
+ }
230
+ key = await context.agent.keyManagerGet({ kid: opts.kmsKeyRef ?? calculateJwkThumbprint({ jwk: opts.identifier }) })
231
+ } else if (isManagedIdentifierX5cOpts(opts)) {
232
+ method = 'x5c'
233
+ x5c = opts.identifier
234
+ if (x5c.length === 0) {
235
+ return Promise.reject(`Cannot resolve x5c when an empty x5c is passed in`)
236
+ } else if (!contextHasKeyManager(context)) {
237
+ return Promise.reject(Error(`Cannot get X5c identifier if KeyManager plugin is not enabled!`))
238
+ }
239
+ certificate = pemOrDerToX509Certificate(x5c[0])
240
+ const cryptoEngine = new CryptoEngine({ name: 'identifier_resolver_managed', crypto: cryptoImpl })
241
+ setEngine(cryptoEngine.name, cryptoEngine)
242
+ const pk = await certificate.getPublicKey(undefined, cryptoEngine)
243
+ jwk = (await cryptoEngine.subtle.exportKey('jwk', pk)) as JWK
244
+ jwkThumbprint = calculateJwkThumbprint({ jwk })
245
+ key = await context.agent.keyManagerGet({ kid: opts.kmsKeyRef ?? jwkThumbprint })
246
+ } else {
247
+ return Promise.reject(Error(`Could not determine identifier method. Please provide explicitly`))
248
+ }
249
+ if (!key || (isManagedIdentifierDidOpts(opts) && !identifier)) {
250
+ console.log(`Cannot find identifier`, opts.identifier)
251
+ return Promise.reject(`Cannot find identifier ${opts.identifier}`)
252
+ }
253
+ jwk = jwk ?? toJwk(key.publicKeyHex, key.type, { key })
254
+ const thumbprint = jwkThumbprint ?? key.meta?.jwkThumbprint ?? calculateJwkThumbprint({ jwk })
255
+ return {
256
+ method,
257
+ jwk,
258
+ jwkThumbprint: thumbprint,
259
+ ...(identifier && { identifier }),
260
+ ...(did && { did }),
261
+ ...(controllerKeyId && { controllerKeyId }),
262
+ ...(keys && { keys }),
263
+ ...(certificate && { certificate: certificate.toJSON() }),
264
+ key,
265
+ kmsKeyRef: key.kid,
266
+ } as ManagedIdentifierResult
267
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ const schema = require('../plugin.schema.json')
5
+ export { schema }
6
+ /**
7
+ * @public
8
+ */
9
+ export { IdentifierResolution } from './agent/IdentifierResolution'
10
+ export * from './types/IIdentifierResolution'
11
+ export * from './functions'
@@ -0,0 +1,297 @@
1
+ import { DidDocumentJwks } from '@sphereon/ssi-sdk-ext.did-utils'
2
+ import { JWK } from '@sphereon/ssi-sdk-ext.key-utils'
3
+ import { X509ValidationResult } from '@sphereon/ssi-sdk-ext.x509-utils'
4
+ import { IParsedDID } from '@sphereon/ssi-types'
5
+ import {
6
+ DIDDocument,
7
+ DIDDocumentSection,
8
+ DIDResolutionResult,
9
+ IAgentContext,
10
+ IDIDManager,
11
+ IIdentifier,
12
+ IKey,
13
+ IKeyManager,
14
+ IPluginMethodMap,
15
+ TKeyType,
16
+ } from '@veramo/core'
17
+
18
+ /**
19
+ * @public
20
+ */
21
+ export interface IIdentifierResolution extends IPluginMethodMap {
22
+ identifierManagedGet(args: ManagedIdentifierOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierResult>
23
+
24
+ identifierManagedGetByDid(args: ManagedIdentifierDidOpts, context: IAgentContext<IKeyManager & IDIDManager>): Promise<ManagedIdentifierDidResult>
25
+
26
+ identifierManagedGetByKid(args: ManagedIdentifierKidOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierKidResult>
27
+
28
+ identifierManagedGetByJwk(args: ManagedIdentifierJwkOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierJwkResult>
29
+
30
+ identifierManagedGetByX5c(args: ManagedIdentifierX5cOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierX5cResult>
31
+
32
+ identifierExternalResolve(args: ExternalIdentifierOpts, context: IAgentContext<any>): Promise<any>
33
+ }
34
+
35
+ /**
36
+ * Use whenever we need to pass in an identifier. We can pass in kids, DIDs, IIdentifier objects and x5chains
37
+ *
38
+ * The functions below can be used to check the type, and they also provide the proper runtime types
39
+ */
40
+ export type ManagedIdentifierType = IIdentifier /*did*/ | string /*did or kid*/ | string[] /*x5c*/ | JWK
41
+
42
+ /**
43
+ * Use whenever we need to resolve an external identifier. We can pass in kids, DIDs, and x5chains
44
+ *
45
+ * The functions below can be used to check the type, and they also provide the proper runtime types
46
+ */
47
+ export type ExternalIdentifierType = string | string[] | JWK
48
+
49
+ export function isDidIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is IIdentifier | string {
50
+ return isIIdentifier(identifier) || (typeof identifier === 'string' && identifier.startsWith('did:'))
51
+ }
52
+
53
+ export function isIIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is IIdentifier {
54
+ return typeof identifier === 'object' && !Array.isArray(identifier) && 'did' in identifier && 'keys' in identifier
55
+ }
56
+
57
+ export function isJwkIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is JWK {
58
+ return typeof identifier === 'object' && !Array.isArray(identifier) && 'kty' in identifier
59
+ }
60
+
61
+ export function isOidcDiscoveryIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string {
62
+ return typeof identifier === 'string' && identifier.startsWith('http') && identifier.endsWith('/.well-known/openid-configuration')
63
+ }
64
+
65
+ export function isJwksUrlIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string {
66
+ return typeof identifier === 'string' && identifier.startsWith('http') && identifier.endsWith('jwks.json')
67
+ }
68
+
69
+ export function isKidIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string {
70
+ return typeof identifier === 'string' && !identifier.startsWith('did:')
71
+ }
72
+
73
+ export function isX5cIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string[] {
74
+ return Array.isArray(identifier) && identifier.length > 0 // todo: Do we want to do additional validation? We know it must be DER and thus hex for instance
75
+ }
76
+
77
+ export type ExternalIdentifierOptsBase = {
78
+ method?: ExternalIdentifierMethod // If provided always takes precedences otherwise it will be inferred from the identifier
79
+ identifier: ExternalIdentifierType
80
+ }
81
+
82
+ export type ExternalIdentifierDidOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
83
+ method?: 'did'
84
+ identifier: string
85
+ noVerificationMethodFallback?: boolean
86
+ vmRelationship?: DIDDocumentSection
87
+ localResolution?: boolean // Resolve identifiers hosted by the agent
88
+ uniresolverResolution?: boolean // Resolve identifiers using universal resolver
89
+ resolverResolution?: boolean // Use registered drivers
90
+ }
91
+
92
+ export function isExternalIdentifierDidOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierDidOpts {
93
+ const { identifier } = opts
94
+ return ('method' in opts && opts.method === 'did') || isDidIdentifier(identifier)
95
+ }
96
+
97
+ export type ExternalIdentifierOpts = (ExternalIdentifierJwkOpts | ExternalIdentifierX5cOpts | ExternalIdentifierDidOpts | ExternalIdentifierKidOpts) &
98
+ ExternalIdentifierOptsBase
99
+
100
+ export type ManagedIdentifierOpts = (ManagedIdentifierJwkOpts | ManagedIdentifierX5cOpts | ManagedIdentifierDidOpts | ManagedIdentifierKidOpts) &
101
+ ManagedIdentifierOptsBase
102
+
103
+ export type ManagedIdentifierOptsBase = {
104
+ method?: ManagedIdentifierMethod // If provided always takes precedences otherwise it will be inferred from the identifier
105
+ identifier: ManagedIdentifierType
106
+ kmsKeyRef?: string
107
+ }
108
+
109
+ export type ManagedIdentifierDidOpts = Omit<ManagedIdentifierOptsBase, 'method'> & {
110
+ method?: 'did'
111
+ identifier: IIdentifier | string
112
+ keyType?: TKeyType
113
+ offlineWhenNoDIDRegistered?: boolean
114
+ noVerificationMethodFallback?: boolean
115
+ controllerKey?: boolean
116
+ vmRelationship?: DIDDocumentSection
117
+ }
118
+
119
+ export function isManagedIdentifierDidOpts(opts: ManagedIdentifierOptsBase): opts is ManagedIdentifierDidOpts {
120
+ const { identifier } = opts
121
+ return ('method' in opts && opts.method === 'did') || isDidIdentifier(identifier)
122
+ }
123
+
124
+ export type ExternalIdentifierKidOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
125
+ method?: 'kid'
126
+ identifier: string
127
+ }
128
+
129
+ export function isExternalIdentifierKidOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierKidOpts {
130
+ const { identifier } = opts
131
+ return ('method' in opts && opts.method === 'kid') || isKidIdentifier(identifier)
132
+ }
133
+
134
+ export type ManagedIdentifierKidOpts = Omit<ManagedIdentifierOptsBase, 'method'> & {
135
+ method?: 'kid'
136
+ identifier: string
137
+ }
138
+
139
+ export function isManagedIdentifierKidOpts(opts: ManagedIdentifierOptsBase): opts is ManagedIdentifierKidOpts {
140
+ const { identifier } = opts
141
+ return ('method' in opts && opts.method === 'kid') || isKidIdentifier(identifier)
142
+ }
143
+
144
+ export type ExternalIdentifierJwkOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
145
+ method?: 'jwk'
146
+ identifier: JWK
147
+ }
148
+
149
+ export function isExternalIdentifierJwkOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierJwkOpts {
150
+ const { identifier } = opts
151
+ return ('method' in opts && opts.method === 'jwk') || isJwkIdentifier(identifier)
152
+ }
153
+
154
+ export type ExternalIdentifierOidcDiscoveryOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
155
+ method?: 'oidc-discovery'
156
+ identifier: string
157
+ }
158
+
159
+ export function isExternalIdentifierOidcDiscoveryOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierJwkOpts {
160
+ const { identifier } = opts
161
+ return ('method' in opts && opts.method === 'oidc-discovery') || isOidcDiscoveryIdentifier(identifier)
162
+ }
163
+
164
+ export type ExternalIdentifierJwksUrlOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
165
+ method?: 'jwks-url'
166
+ identifier: string
167
+ }
168
+
169
+ export function isExternalIdentifierJwksUrlOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierJwksUrlOpts {
170
+ const { identifier } = opts
171
+ return ('method' in opts && opts.method === 'oidc-discovery') || isJwksUrlIdentifier(identifier)
172
+ }
173
+
174
+ export type ManagedIdentifierJwkOpts = Omit<ManagedIdentifierOptsBase, 'method'> & {
175
+ method?: 'jwk'
176
+ identifier: JWK
177
+ }
178
+
179
+ export function isManagedIdentifierJwkOpts(opts: ManagedIdentifierOptsBase): opts is ManagedIdentifierJwkOpts {
180
+ const { identifier } = opts
181
+ return ('method' in opts && opts.method === 'jwk') || isJwkIdentifier(identifier)
182
+ }
183
+
184
+ export type ExternalIdentifierX5cOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
185
+ method?: 'x5c'
186
+ identifier: string[]
187
+ verify: boolean
188
+ verificationTime?: Date
189
+ trustAnchors?: string[]
190
+ }
191
+
192
+ export function isExternalIdentifierX5cOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierX5cOpts {
193
+ const { identifier } = opts
194
+ return ('method' in opts && opts.method === 'x5c') || isX5cIdentifier(identifier)
195
+ }
196
+
197
+ export type ManagedIdentifierX5cOpts = Omit<ManagedIdentifierOptsBase, 'method'> & {
198
+ method?: 'x5c'
199
+ identifier: string[]
200
+ }
201
+
202
+ export function isManagedIdentifierX5cOpts(opts: ManagedIdentifierOptsBase): opts is ManagedIdentifierX5cOpts {
203
+ const { identifier } = opts
204
+ return ('method' in opts && opts.method === 'x5c') || isX5cIdentifier(identifier)
205
+ }
206
+
207
+ export type ExternalIdentifierMethod = 'did' | 'jwk' | 'x5c' | 'kid' | 'oidc-discovery' | 'jwks-url' | 'oid4vci-issuer'
208
+
209
+ export type ExternalIdentifierResult = ExternalIdentifierDidResult | ExternalIdentifierX5cResult
210
+
211
+ export type ManagedIdentifierMethod = 'did' | 'jwk' | 'x5c' | 'kid'
212
+
213
+ export type ManagedIdentifierResult =
214
+ | ManagedIdentifierX5cResult
215
+ | ManagedIdentifierDidResult
216
+ | ManagedIdentifierJwkResult
217
+ | ManagedIdentifierKidResult
218
+
219
+ export interface IExternalIdentifierResultBase {
220
+ method: ExternalIdentifierMethod
221
+ jwks: Array<ExternalJwkInfo>
222
+ }
223
+
224
+ export interface JwkInfo {
225
+ jwk: JWK
226
+ jwkThumbprint: string
227
+ }
228
+
229
+ export interface ExternalJwkInfo extends JwkInfo {
230
+ kid?: string
231
+ }
232
+
233
+ export interface ManagedJwkInfo extends JwkInfo {
234
+ kmsKeyRef: string
235
+ }
236
+
237
+ export interface IManagedIdentifierResultBase extends ManagedJwkInfo {
238
+ method: ManagedIdentifierMethod
239
+ key: IKey
240
+ }
241
+
242
+ export function isManagedIdentifierDidResult(object: IManagedIdentifierResultBase): object is ManagedIdentifierDidResult {
243
+ return object!! && typeof object === 'object' && 'method' in object && object.method === 'did'
244
+ }
245
+
246
+ export function isManagedIdentifierX5cResult(object: IManagedIdentifierResultBase): object is ManagedIdentifierDidResult {
247
+ return object!! && typeof object === 'object' && 'method' in object && object.method === 'x5c'
248
+ }
249
+
250
+ export function isManagedIdentifierJwkResult(object: IManagedIdentifierResultBase): object is ManagedIdentifierJwkResult {
251
+ return object!! && typeof object === 'object' && 'method' in object && object.method === 'jwk'
252
+ }
253
+
254
+ export function isManagedIdentifierKidResult(object: IManagedIdentifierResultBase): object is ManagedIdentifierKidResult {
255
+ return object!! && typeof object === 'object' && 'method' in object && object.method === 'kid'
256
+ }
257
+
258
+ export interface ExternalIdentifierDidResult extends IExternalIdentifierResultBase {
259
+ method: 'did'
260
+ did: string
261
+ didDocument?: DIDDocument
262
+ didJwks?: DidDocumentJwks
263
+ didResolutionResult: Omit<DIDResolutionResult, 'didDocument'> // we already provide that directly
264
+ didParsed: IParsedDID
265
+ }
266
+
267
+ export interface ManagedIdentifierDidResult extends IManagedIdentifierResultBase {
268
+ method: 'did'
269
+ identifier: IIdentifier
270
+ did: string
271
+ // key: IKey // The key associated with the requested did method sections. Controller key in case of no DID method section requested
272
+ keys: Array<IKey> // If there is more than one key for the VM relationship.
273
+ verificationMethodSection?: DIDDocumentSection
274
+ controllerKeyId: string
275
+ }
276
+
277
+ export interface ManagedIdentifierJwkResult extends IManagedIdentifierResultBase {
278
+ method: 'jwk'
279
+ }
280
+
281
+ export interface ManagedIdentifierKidResult extends IManagedIdentifierResultBase {
282
+ method: 'kid'
283
+ }
284
+
285
+ export interface ExternalIdentifierX5cResult extends IExternalIdentifierResultBase {
286
+ method: 'x5c'
287
+ x5c: string[]
288
+ issuerJWK: JWK
289
+ verificationResult?: X509ValidationResult
290
+ certificates: any[] // for now since our schema generator trips on pkijs Certificate(Json) object //fixme
291
+ }
292
+
293
+ export interface ManagedIdentifierX5cResult extends IManagedIdentifierResultBase {
294
+ method: 'x5c'
295
+ x5c: string[]
296
+ certificate: any // Certificate(JSON_, but trips schema generator. Probably want to create our own DTO
297
+ }