@sphereon/ssi-sdk-ext.identifier-resolution 0.24.1-unstable.75 → 0.24.1-unstable.77
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/README.md +380 -1
- package/dist/agent/IdentifierResolution.d.ts +9 -1
- package/dist/agent/IdentifierResolution.d.ts.map +1 -1
- package/dist/agent/IdentifierResolution.js +22 -3
- package/dist/agent/IdentifierResolution.js.map +1 -1
- package/dist/functions/externalIdentifierFunctions.d.ts +10 -0
- package/dist/functions/externalIdentifierFunctions.d.ts.map +1 -0
- package/dist/functions/externalIdentifierFunctions.js +167 -0
- package/dist/functions/externalIdentifierFunctions.js.map +1 -0
- package/dist/functions/index.d.ts +2 -12
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +15 -237
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/managedIdentifierFunctions.d.ts +12 -0
- package/dist/functions/managedIdentifierFunctions.d.ts.map +1 -0
- package/dist/functions/managedIdentifierFunctions.js +168 -0
- package/dist/functions/managedIdentifierFunctions.js.map +1 -0
- package/dist/types/IIdentifierResolution.d.ts +18 -159
- package/dist/types/IIdentifierResolution.d.ts.map +1 -1
- package/dist/types/IIdentifierResolution.js +0 -95
- package/dist/types/IIdentifierResolution.js.map +1 -1
- package/dist/types/common.d.ts +16 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +32 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/externalIdentifierTypes.d.ts +80 -0
- package/dist/types/externalIdentifierTypes.d.ts.map +1 -0
- package/dist/types/externalIdentifierTypes.js +35 -0
- package/dist/types/externalIdentifierTypes.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/managedIdentifierTypes.d.ts +81 -0
- package/dist/types/managedIdentifierTypes.d.ts.map +1 -0
- package/dist/types/managedIdentifierTypes.js +41 -0
- package/dist/types/managedIdentifierTypes.js.map +1 -0
- package/package.json +13 -11
- package/plugin.schema.json +1209 -222
- package/src/agent/IdentifierResolution.ts +31 -8
- package/src/functions/externalIdentifierFunctions.ts +183 -0
- package/src/functions/index.ts +2 -267
- package/src/functions/managedIdentifierFunctions.ts +178 -0
- package/src/types/IIdentifierResolution.ts +35 -278
- package/src/types/common.ts +37 -0
- package/src/types/externalIdentifierTypes.ts +119 -0
- package/src/types/index.ts +4 -0
- package/src/types/managedIdentifierTypes.ts +126 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { getFirstKeyWithRelation } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
2
|
+
import { calculateJwkThumbprint, JWK, toJwk } from '@sphereon/ssi-sdk-ext.key-utils'
|
|
3
|
+
import { pemOrDerToX509Certificate } from '@sphereon/ssi-sdk-ext.x509-utils'
|
|
4
|
+
import { contextHasDidManager, contextHasKeyManager } from '@sphereon/ssi-sdk.agent-config'
|
|
5
|
+
import { IAgentContext, IIdentifier, IKeyManager } from '@veramo/core'
|
|
6
|
+
import { CryptoEngine, setEngine } from 'pkijs'
|
|
7
|
+
import {
|
|
8
|
+
isManagedIdentifierDidOpts,
|
|
9
|
+
isManagedIdentifierDidResult,
|
|
10
|
+
isManagedIdentifierJwkOpts,
|
|
11
|
+
isManagedIdentifierKidOpts,
|
|
12
|
+
isManagedIdentifierX5cOpts,
|
|
13
|
+
ManagedIdentifierDidOpts,
|
|
14
|
+
ManagedIdentifierDidResult,
|
|
15
|
+
ManagedIdentifierJwkOpts,
|
|
16
|
+
ManagedIdentifierJwkResult,
|
|
17
|
+
ManagedIdentifierKidOpts,
|
|
18
|
+
ManagedIdentifierKidResult,
|
|
19
|
+
ManagedIdentifierOpts,
|
|
20
|
+
ManagedIdentifierResult,
|
|
21
|
+
ManagedIdentifierX5cOpts,
|
|
22
|
+
ManagedIdentifierX5cResult,
|
|
23
|
+
} from '../types'
|
|
24
|
+
|
|
25
|
+
export async function getManagedKidIdentifier(
|
|
26
|
+
opts: ManagedIdentifierKidOpts,
|
|
27
|
+
context: IAgentContext<IKeyManager>
|
|
28
|
+
): Promise<ManagedIdentifierKidResult> {
|
|
29
|
+
const method = 'kid'
|
|
30
|
+
if (!contextHasKeyManager(context)) {
|
|
31
|
+
return Promise.reject(Error(`Cannot get Key/JWK identifier if KeyManager plugin is not enabled!`))
|
|
32
|
+
}
|
|
33
|
+
const key = await context.agent.keyManagerGet({ kid: opts.kmsKeyRef ?? opts.identifier })
|
|
34
|
+
const jwk = toJwk(key.publicKeyHex, key.type, { key })
|
|
35
|
+
const jwkThumbprint = (key.meta?.jwkThumbprint as string) ?? calculateJwkThumbprint({ jwk })
|
|
36
|
+
const kid = opts.kid ?? (key.meta?.verificationMethod?.id as string) ?? jwkThumbprint
|
|
37
|
+
const issuer = opts.issuer ?? kid // The different identifiers should set the value. Defaults to the kid
|
|
38
|
+
return {
|
|
39
|
+
method,
|
|
40
|
+
key,
|
|
41
|
+
jwk,
|
|
42
|
+
jwkThumbprint,
|
|
43
|
+
kid,
|
|
44
|
+
issuer,
|
|
45
|
+
kmsKeyRef: key.kid,
|
|
46
|
+
} satisfies ManagedIdentifierKidResult
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function getManagedDidIdentifier(opts: ManagedIdentifierDidOpts, context: IAgentContext<any>): Promise<ManagedIdentifierDidResult> {
|
|
50
|
+
const method = 'did'
|
|
51
|
+
if (!contextHasDidManager(context)) {
|
|
52
|
+
return Promise.reject(Error(`Cannot get DID identifier if DID Manager plugin is not enabled!`))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let identifier: IIdentifier
|
|
56
|
+
if (typeof opts.identifier === 'string') {
|
|
57
|
+
identifier = await context.agent.didManagerGet({ did: opts.identifier.split('#')[0] })
|
|
58
|
+
} else {
|
|
59
|
+
identifier = opts.identifier
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const did = identifier.did
|
|
63
|
+
const keys = identifier?.keys // fixme: We really want to return the vmRelationship keys here actually
|
|
64
|
+
const extendedKey = await getFirstKeyWithRelation(
|
|
65
|
+
{
|
|
66
|
+
...opts,
|
|
67
|
+
identifier,
|
|
68
|
+
vmRelationship: opts.vmRelationship ?? 'verificationMethod',
|
|
69
|
+
},
|
|
70
|
+
context
|
|
71
|
+
)
|
|
72
|
+
const key = extendedKey
|
|
73
|
+
const controllerKeyId = identifier.controllerKeyId
|
|
74
|
+
const jwk = toJwk(key.publicKeyHex, key.type, { key })
|
|
75
|
+
const jwkThumbprint = key.meta?.jwkThumbprint ?? calculateJwkThumbprint({ jwk })
|
|
76
|
+
const kid = opts.kid ?? extendedKey.meta?.verificationMethod?.id
|
|
77
|
+
const issuer = opts.issuer ?? did
|
|
78
|
+
return {
|
|
79
|
+
method,
|
|
80
|
+
key,
|
|
81
|
+
did,
|
|
82
|
+
kmsKeyRef: key.kid,
|
|
83
|
+
jwk,
|
|
84
|
+
jwkThumbprint,
|
|
85
|
+
controllerKeyId,
|
|
86
|
+
kid,
|
|
87
|
+
keys,
|
|
88
|
+
issuer,
|
|
89
|
+
identifier,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function getManagedJwkIdentifier(
|
|
94
|
+
opts: ManagedIdentifierJwkOpts,
|
|
95
|
+
context: IAgentContext<IKeyManager>
|
|
96
|
+
): Promise<ManagedIdentifierJwkResult> {
|
|
97
|
+
const method = 'jwk'
|
|
98
|
+
const { kid, issuer } = opts
|
|
99
|
+
if (!contextHasKeyManager(context)) {
|
|
100
|
+
return Promise.reject(Error(`Cannot get Key/JWK identifier if KeyManager plugin is not enabled!`))
|
|
101
|
+
}
|
|
102
|
+
const key = await context.agent.keyManagerGet({ kid: opts.kmsKeyRef ?? calculateJwkThumbprint({ jwk: opts.identifier }) })
|
|
103
|
+
const jwk = opts.identifier ?? toJwk(key.publicKeyHex, key.type, { key })
|
|
104
|
+
const jwkThumbprint = (key.meta?.jwkThumbprint as string) ?? calculateJwkThumbprint({ jwk })
|
|
105
|
+
// we explicitly do not set the kid and issuer, meaning it can remain null. Normally you do not provide a kid and issuer with Jwks.
|
|
106
|
+
return {
|
|
107
|
+
method,
|
|
108
|
+
key,
|
|
109
|
+
kmsKeyRef: key.kid,
|
|
110
|
+
jwk,
|
|
111
|
+
jwkThumbprint,
|
|
112
|
+
kid,
|
|
113
|
+
issuer,
|
|
114
|
+
} satisfies ManagedIdentifierJwkResult
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function getManagedX5cIdentifier(
|
|
118
|
+
opts: ManagedIdentifierX5cOpts & {
|
|
119
|
+
crypto?: Crypto
|
|
120
|
+
},
|
|
121
|
+
context: IAgentContext<IKeyManager>
|
|
122
|
+
): Promise<ManagedIdentifierX5cResult> {
|
|
123
|
+
const { kid, issuer } = opts
|
|
124
|
+
const method = 'x5c'
|
|
125
|
+
const x5c = opts.identifier
|
|
126
|
+
if (x5c.length === 0) {
|
|
127
|
+
return Promise.reject(`Cannot resolve x5c when an empty x5c is passed in`)
|
|
128
|
+
} else if (!contextHasKeyManager(context)) {
|
|
129
|
+
return Promise.reject(Error(`Cannot get X5c identifier if KeyManager plugin is not enabled!`))
|
|
130
|
+
}
|
|
131
|
+
const cryptoImpl = opts.crypto ?? crypto
|
|
132
|
+
const certificate = pemOrDerToX509Certificate(x5c[0])
|
|
133
|
+
const cryptoEngine = new CryptoEngine({ name: 'identifier_resolver_managed', crypto: cryptoImpl })
|
|
134
|
+
setEngine(cryptoEngine.name, cryptoEngine)
|
|
135
|
+
const pk = await certificate.getPublicKey(undefined, cryptoEngine)
|
|
136
|
+
const jwk = (await cryptoEngine.subtle.exportKey('jwk', pk)) as JWK
|
|
137
|
+
const jwkThumbprint = calculateJwkThumbprint({ jwk })
|
|
138
|
+
const key = await context.agent.keyManagerGet({ kid: opts.kmsKeyRef ?? jwkThumbprint })
|
|
139
|
+
// we explicitly do not set the kid and issuer, meaning it can remain null. Normally you do not provide a kid and issuer with x5c.
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
method,
|
|
143
|
+
x5c,
|
|
144
|
+
certificate,
|
|
145
|
+
jwk,
|
|
146
|
+
jwkThumbprint,
|
|
147
|
+
key,
|
|
148
|
+
kmsKeyRef: key.kid,
|
|
149
|
+
kid,
|
|
150
|
+
issuer,
|
|
151
|
+
} satisfies ManagedIdentifierX5cResult
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export async function getManagedIdentifier(
|
|
155
|
+
opts: ManagedIdentifierOpts & {
|
|
156
|
+
crypto?: Crypto
|
|
157
|
+
},
|
|
158
|
+
context: IAgentContext<IKeyManager>
|
|
159
|
+
): Promise<ManagedIdentifierResult> {
|
|
160
|
+
let resolutionResult: ManagedIdentifierResult
|
|
161
|
+
if (isManagedIdentifierKidOpts(opts)) {
|
|
162
|
+
resolutionResult = await getManagedKidIdentifier(opts, context)
|
|
163
|
+
} else if (isManagedIdentifierDidOpts(opts)) {
|
|
164
|
+
resolutionResult = await getManagedDidIdentifier(opts, context)
|
|
165
|
+
} else if (isManagedIdentifierJwkOpts(opts)) {
|
|
166
|
+
resolutionResult = await getManagedJwkIdentifier(opts, context)
|
|
167
|
+
} else if (isManagedIdentifierX5cOpts(opts)) {
|
|
168
|
+
resolutionResult = await getManagedX5cIdentifier(opts, context)
|
|
169
|
+
} else {
|
|
170
|
+
return Promise.reject(Error(`Could not determine identifier method. Please provide explicitly`))
|
|
171
|
+
}
|
|
172
|
+
const { key } = resolutionResult
|
|
173
|
+
if (!key || (isManagedIdentifierDidOpts(opts) && isManagedIdentifierDidResult(resolutionResult) && !resolutionResult.identifier)) {
|
|
174
|
+
console.log(`Cannot find identifier`, opts.identifier)
|
|
175
|
+
return Promise.reject(`Cannot find identifier ${opts.identifier}`)
|
|
176
|
+
}
|
|
177
|
+
return resolutionResult
|
|
178
|
+
}
|
|
@@ -1,24 +1,35 @@
|
|
|
1
|
-
import {
|
|
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'
|
|
1
|
+
import { IAgentContext, IDIDManager, IKeyManager, IPluginMethodMap } from '@veramo/core'
|
|
5
2
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
ExternalIdentifierDidOpts,
|
|
4
|
+
ExternalIdentifierDidResult,
|
|
5
|
+
ExternalIdentifierOpts,
|
|
6
|
+
ExternalIdentifierResult,
|
|
7
|
+
ExternalIdentifierX5cOpts,
|
|
8
|
+
ExternalIdentifierX5cResult,
|
|
9
|
+
} from './externalIdentifierTypes'
|
|
10
|
+
import {
|
|
11
|
+
ManagedIdentifierDidOpts,
|
|
12
|
+
ManagedIdentifierDidResult,
|
|
13
|
+
ManagedIdentifierJwkOpts,
|
|
14
|
+
ManagedIdentifierJwkResult,
|
|
15
|
+
ManagedIdentifierKidOpts,
|
|
16
|
+
ManagedIdentifierKidResult,
|
|
17
|
+
ManagedIdentifierOpts,
|
|
18
|
+
ManagedIdentifierResult,
|
|
19
|
+
ManagedIdentifierX5cOpts,
|
|
20
|
+
ManagedIdentifierX5cResult,
|
|
21
|
+
} from './managedIdentifierTypes'
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* @public
|
|
20
25
|
*/
|
|
21
26
|
export interface IIdentifierResolution extends IPluginMethodMap {
|
|
27
|
+
/**
|
|
28
|
+
* Main method for managed identifiers. We always go through this method (also the others) as we want to integrate a plugin for anomaly detection. Having a single method helps
|
|
29
|
+
* @param args
|
|
30
|
+
* @param context
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
22
33
|
identifierManagedGet(args: ManagedIdentifierOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierResult>
|
|
23
34
|
|
|
24
35
|
identifierManagedGetByDid(args: ManagedIdentifierDidOpts, context: IAgentContext<IKeyManager & IDIDManager>): Promise<ManagedIdentifierDidResult>
|
|
@@ -29,269 +40,15 @@ export interface IIdentifierResolution extends IPluginMethodMap {
|
|
|
29
40
|
|
|
30
41
|
identifierManagedGetByX5c(args: ManagedIdentifierX5cOpts, context: IAgentContext<IKeyManager>): Promise<ManagedIdentifierX5cResult>
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
}
|
|
43
|
+
/**
|
|
44
|
+
* Main method for external identifiers. We always go through this method (also the others) as we want to integrate a plugin for anomaly detection. Having a single method helps
|
|
45
|
+
* @param args
|
|
46
|
+
* @param context
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
identifierExternalResolve(args: ExternalIdentifierOpts, context: IAgentContext<any>): Promise<ExternalIdentifierResult>
|
|
158
50
|
|
|
159
|
-
|
|
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
|
-
}
|
|
51
|
+
identifierExternalResolveByDid(args: ExternalIdentifierDidOpts, context: IAgentContext<any>): Promise<ExternalIdentifierDidResult>
|
|
292
52
|
|
|
293
|
-
|
|
294
|
-
method: 'x5c'
|
|
295
|
-
x5c: string[]
|
|
296
|
-
certificate: any // Certificate(JSON_, but trips schema generator. Probably want to create our own DTO
|
|
53
|
+
identifierExternalResolveByX5c(args: ExternalIdentifierX5cOpts, context: IAgentContext<any>): Promise<ExternalIdentifierX5cResult>
|
|
297
54
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { JWK } from '@sphereon/ssi-sdk-ext.key-utils'
|
|
2
|
+
import { IIdentifier } from '@veramo/core'
|
|
3
|
+
import { ExternalIdentifierType } from './externalIdentifierTypes'
|
|
4
|
+
import { ManagedIdentifierType } from './managedIdentifierTypes'
|
|
5
|
+
|
|
6
|
+
export interface JwkInfo {
|
|
7
|
+
jwk: JWK
|
|
8
|
+
jwkThumbprint: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isDidIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is IIdentifier | string {
|
|
12
|
+
return isIIdentifier(identifier) || (typeof identifier === 'string' && identifier.startsWith('did:'))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isIIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is IIdentifier {
|
|
16
|
+
return typeof identifier === 'object' && !Array.isArray(identifier) && 'did' in identifier && 'keys' in identifier
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isJwkIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is JWK {
|
|
20
|
+
return typeof identifier === 'object' && !Array.isArray(identifier) && 'kty' in identifier
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isOidcDiscoveryIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string {
|
|
24
|
+
return typeof identifier === 'string' && identifier.startsWith('http') && identifier.endsWith('/.well-known/openid-configuration')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isJwksUrlIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string {
|
|
28
|
+
return typeof identifier === 'string' && identifier.startsWith('http') && identifier.endsWith('jwks.json')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isKidIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string {
|
|
32
|
+
return typeof identifier === 'string' && !identifier.startsWith('did:')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isX5cIdentifier(identifier: ManagedIdentifierType | ExternalIdentifierType): identifier is string[] {
|
|
36
|
+
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
|
|
37
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
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 { DIDDocument, DIDDocumentSection, DIDResolutionResult } from '@veramo/core'
|
|
6
|
+
import { isDidIdentifier, isJwkIdentifier, isJwksUrlIdentifier, isKidIdentifier, isOidcDiscoveryIdentifier, isX5cIdentifier, JwkInfo } from './common'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Use whenever we need to resolve an external identifier. We can pass in kids, DIDs, and x5chains
|
|
10
|
+
*
|
|
11
|
+
* The functions below can be used to check the type, and they also provide the proper runtime types
|
|
12
|
+
*/
|
|
13
|
+
export type ExternalIdentifierType = string | string[] | JWK
|
|
14
|
+
|
|
15
|
+
export type ExternalIdentifierOptsBase = {
|
|
16
|
+
method?: ExternalIdentifierMethod // If provided always takes precedences otherwise it will be inferred from the identifier
|
|
17
|
+
identifier: ExternalIdentifierType
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ExternalIdentifierDidOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
|
|
21
|
+
method?: 'did'
|
|
22
|
+
identifier: string
|
|
23
|
+
noVerificationMethodFallback?: boolean
|
|
24
|
+
vmRelationship?: DIDDocumentSection
|
|
25
|
+
localResolution?: boolean // Resolve identifiers hosted by the agent
|
|
26
|
+
uniresolverResolution?: boolean // Resolve identifiers using universal resolver
|
|
27
|
+
resolverResolution?: boolean // Use registered drivers
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isExternalIdentifierDidOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierDidOpts {
|
|
31
|
+
const { identifier } = opts
|
|
32
|
+
return ('method' in opts && opts.method === 'did') || isDidIdentifier(identifier)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type ExternalIdentifierOpts = (ExternalIdentifierJwkOpts | ExternalIdentifierX5cOpts | ExternalIdentifierDidOpts | ExternalIdentifierKidOpts) &
|
|
36
|
+
ExternalIdentifierOptsBase
|
|
37
|
+
|
|
38
|
+
export type ExternalIdentifierKidOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
|
|
39
|
+
method?: 'kid'
|
|
40
|
+
identifier: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isExternalIdentifierKidOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierKidOpts {
|
|
44
|
+
const { identifier } = opts
|
|
45
|
+
return ('method' in opts && opts.method === 'kid') || isKidIdentifier(identifier)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type ExternalIdentifierJwkOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
|
|
49
|
+
method?: 'jwk'
|
|
50
|
+
identifier: JWK
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function isExternalIdentifierJwkOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierJwkOpts {
|
|
54
|
+
const { identifier } = opts
|
|
55
|
+
return ('method' in opts && opts.method === 'jwk') || isJwkIdentifier(identifier)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type ExternalIdentifierOidcDiscoveryOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
|
|
59
|
+
method?: 'oidc-discovery'
|
|
60
|
+
identifier: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isExternalIdentifierOidcDiscoveryOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierJwkOpts {
|
|
64
|
+
const { identifier } = opts
|
|
65
|
+
return ('method' in opts && opts.method === 'oidc-discovery') || isOidcDiscoveryIdentifier(identifier)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type ExternalIdentifierJwksUrlOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
|
|
69
|
+
method?: 'jwks-url'
|
|
70
|
+
identifier: string
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isExternalIdentifierJwksUrlOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierJwksUrlOpts {
|
|
74
|
+
const { identifier } = opts
|
|
75
|
+
return ('method' in opts && opts.method === 'oidc-discovery') || isJwksUrlIdentifier(identifier)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type ExternalIdentifierX5cOpts = Omit<ExternalIdentifierOptsBase, 'method'> & {
|
|
79
|
+
method?: 'x5c'
|
|
80
|
+
identifier: string[]
|
|
81
|
+
verify?: boolean // defaults to true
|
|
82
|
+
verificationTime?: Date
|
|
83
|
+
trustAnchors?: string[]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function isExternalIdentifierX5cOpts(opts: ExternalIdentifierOptsBase): opts is ExternalIdentifierX5cOpts {
|
|
87
|
+
const { identifier } = opts
|
|
88
|
+
return ('method' in opts && opts.method === 'x5c') || isX5cIdentifier(identifier)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type ExternalIdentifierMethod = 'did' | 'jwk' | 'x5c' | 'kid' | 'oidc-discovery' | 'jwks-url' | 'oid4vci-issuer'
|
|
92
|
+
|
|
93
|
+
export type ExternalIdentifierResult = ExternalIdentifierDidResult | ExternalIdentifierX5cResult
|
|
94
|
+
|
|
95
|
+
export interface IExternalIdentifierResultBase {
|
|
96
|
+
method: ExternalIdentifierMethod
|
|
97
|
+
jwks: Array<ExternalJwkInfo>
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ExternalIdentifierX5cResult extends IExternalIdentifierResultBase {
|
|
101
|
+
method: 'x5c'
|
|
102
|
+
x5c: string[]
|
|
103
|
+
issuerJWK: JWK
|
|
104
|
+
verificationResult?: X509ValidationResult
|
|
105
|
+
certificates: any[] // for now since our schema generator trips on pkijs Certificate(Json) object //fixme
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface ExternalJwkInfo extends JwkInfo {
|
|
109
|
+
kid?: string
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface ExternalIdentifierDidResult extends IExternalIdentifierResultBase {
|
|
113
|
+
method: 'did'
|
|
114
|
+
did: string
|
|
115
|
+
didDocument?: DIDDocument
|
|
116
|
+
didJwks?: DidDocumentJwks
|
|
117
|
+
didResolutionResult: Omit<DIDResolutionResult, 'didDocument'> // we already provide that directly
|
|
118
|
+
didParsed: IParsedDID
|
|
119
|
+
}
|