@sphereon/ssi-sdk-ext.jwt-service 0.24.1-next.103 → 0.24.1-next.104
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/JwtService.d.ts +1 -0
- package/dist/agent/JwtService.d.ts.map +1 -1
- package/dist/agent/JwtService.js +7 -1
- package/dist/agent/JwtService.js.map +1 -1
- package/dist/functions/index.d.ts +17 -3
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +135 -7
- package/dist/functions/index.js.map +1 -1
- package/dist/types/IJwtService.d.ts +30 -8
- package/dist/types/IJwtService.d.ts.map +1 -1
- package/dist/types/IJwtService.js +15 -3
- package/dist/types/IJwtService.js.map +1 -1
- package/package.json +13 -13
- package/plugin.schema.json +1596 -50
- package/src/agent/JwtService.ts +9 -1
- package/src/functions/index.ts +161 -11
- package/src/types/IJwtService.ts +56 -13
package/src/agent/JwtService.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
CreateJwsJsonArgs,
|
|
7
7
|
createJwsJsonFlattened,
|
|
8
8
|
createJwsJsonGeneral,
|
|
9
|
+
IJwsValidationResult,
|
|
9
10
|
IJwtService,
|
|
10
11
|
IRequiredContext,
|
|
11
12
|
JwsCompactResult,
|
|
@@ -14,18 +15,21 @@ import {
|
|
|
14
15
|
PreparedJwsObject,
|
|
15
16
|
prepareJwsObject,
|
|
16
17
|
schema,
|
|
18
|
+
verifyJws,
|
|
19
|
+
VerifyJwsArgs,
|
|
17
20
|
} from '..'
|
|
18
21
|
|
|
19
22
|
/**
|
|
20
23
|
* @public
|
|
21
24
|
*/
|
|
22
25
|
export class JwtService implements IAgentPlugin {
|
|
23
|
-
readonly schema = schema.
|
|
26
|
+
readonly schema = schema.IJwtService
|
|
24
27
|
readonly methods: IJwtService = {
|
|
25
28
|
jwtPrepareJws: this.jwtPrepareJws.bind(this),
|
|
26
29
|
jwtCreateJwsJsonGeneralSignature: this.jwtCreateJwsJsonGeneralSignature.bind(this),
|
|
27
30
|
jwtCreateJwsJsonFlattenedSignature: this.jwtCreateJwsJsonFlattenedSignature.bind(this),
|
|
28
31
|
jwtCreateJwsCompactSignature: this.jwtCreateJwsCompactSignature.bind(this),
|
|
32
|
+
jwtVerifyJwsSignature: this.jwtVerifyJwsSignature.bind(this),
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
private async jwtPrepareJws(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject> {
|
|
@@ -44,4 +48,8 @@ export class JwtService implements IAgentPlugin {
|
|
|
44
48
|
// We wrap it in a json object for remote REST calls
|
|
45
49
|
return { jwt: await createJwsCompact(args, context) }
|
|
46
50
|
}
|
|
51
|
+
|
|
52
|
+
private async jwtVerifyJwsSignature(args: VerifyJwsArgs, context: IRequiredContext): Promise<IJwsValidationResult> {
|
|
53
|
+
return await verifyJws(args, context)
|
|
54
|
+
}
|
|
47
55
|
}
|
package/src/functions/index.ts
CHANGED
|
@@ -1,26 +1,50 @@
|
|
|
1
|
+
import { jwkTtoPublicKeyHex } from '@sphereon/ssi-sdk-ext.did-utils'
|
|
1
2
|
import {
|
|
3
|
+
ensureManagedIdentifierResult,
|
|
4
|
+
ExternalIdentifierDidOpts,
|
|
5
|
+
ExternalIdentifierX5cOpts,
|
|
6
|
+
IIdentifierResolution,
|
|
2
7
|
isManagedIdentifierDidResult,
|
|
3
8
|
isManagedIdentifierX5cResult,
|
|
4
9
|
ManagedIdentifierMethod,
|
|
5
10
|
ManagedIdentifierResult,
|
|
6
|
-
|
|
11
|
+
resolveExternalJwkIdentifier,
|
|
7
12
|
} from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
8
|
-
import {
|
|
13
|
+
import { keyTypeFromCryptographicSuite, verifySignatureWithSubtle } from '@sphereon/ssi-sdk-ext.key-utils'
|
|
14
|
+
import { contextHasPlugin } from '@sphereon/ssi-sdk.agent-config'
|
|
15
|
+
import { JWK } from '@sphereon/ssi-types'
|
|
16
|
+
import { IAgentContext } from '@veramo/core'
|
|
17
|
+
import { bytesToBase64url, decodeJoseBlob, encodeJoseBlob } from '@veramo/utils'
|
|
18
|
+
import { base64ToBytes } from '@veramo/utils'
|
|
9
19
|
import * as u8a from 'uint8arrays'
|
|
10
20
|
import {
|
|
11
21
|
CreateJwsCompactArgs,
|
|
12
22
|
CreateJwsFlattenedArgs,
|
|
13
23
|
CreateJwsJsonArgs,
|
|
14
|
-
|
|
24
|
+
IJwsValidationResult,
|
|
15
25
|
IRequiredContext,
|
|
26
|
+
isJwsCompact,
|
|
27
|
+
isJwsJsonFlattened,
|
|
28
|
+
isJwsJsonGeneral,
|
|
29
|
+
Jws,
|
|
16
30
|
JwsCompact,
|
|
31
|
+
JwsIdentifierMode,
|
|
17
32
|
JwsJsonFlattened,
|
|
18
33
|
JwsJsonGeneral,
|
|
34
|
+
JwsJsonGeneralWithIdentifiers,
|
|
19
35
|
JwsJsonSignature,
|
|
20
36
|
JwtHeader,
|
|
37
|
+
JwtPayload,
|
|
21
38
|
PreparedJwsObject,
|
|
39
|
+
VerifyJwsArgs,
|
|
22
40
|
} from '../types/IJwtService'
|
|
23
41
|
|
|
42
|
+
const payloadToBytes = (payload: string | JwtPayload | Uint8Array): Uint8Array => {
|
|
43
|
+
const isBytes = payload instanceof Uint8Array
|
|
44
|
+
const isString = typeof payload === 'string'
|
|
45
|
+
return isBytes ? payload : isString ? u8a.fromString(payload, 'base64url') : u8a.fromString(JSON.stringify(payload), 'utf-8')
|
|
46
|
+
}
|
|
47
|
+
|
|
24
48
|
export const prepareJwsObject = async (args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject> => {
|
|
25
49
|
const { existingSignatures, protectedHeader, unprotectedHeader, issuer, payload, mode = 'auto' } = args
|
|
26
50
|
|
|
@@ -31,7 +55,6 @@ export const prepareJwsObject = async (args: CreateJwsJsonArgs, context: IRequir
|
|
|
31
55
|
}
|
|
32
56
|
const identifier = await ensureManagedIdentifierResult(issuer, context)
|
|
33
57
|
await checkAndUpdateJwtHeader({ mode, identifier, noIdentifierInHeader, header: protectedHeader }, context)
|
|
34
|
-
|
|
35
58
|
const isBytes = payload instanceof Uint8Array
|
|
36
59
|
const isString = typeof payload === 'string'
|
|
37
60
|
if (!isBytes && !isString) {
|
|
@@ -39,7 +62,7 @@ export const prepareJwsObject = async (args: CreateJwsJsonArgs, context: IRequir
|
|
|
39
62
|
payload.iss = identifier.issuer
|
|
40
63
|
}
|
|
41
64
|
}
|
|
42
|
-
const payloadBytes =
|
|
65
|
+
const payloadBytes = payloadToBytes(payload)
|
|
43
66
|
const base64urlHeader = encodeJoseBlob(protectedHeader)
|
|
44
67
|
const base64urlPayload = bytesToBase64url(payloadBytes)
|
|
45
68
|
|
|
@@ -120,24 +143,24 @@ export const checkAndUpdateJwtHeader = async (
|
|
|
120
143
|
header,
|
|
121
144
|
noIdentifierInHeader = false,
|
|
122
145
|
}: {
|
|
123
|
-
mode?:
|
|
146
|
+
mode?: JwsIdentifierMode
|
|
124
147
|
identifier: ManagedIdentifierResult
|
|
125
148
|
noIdentifierInHeader?: boolean
|
|
126
149
|
header: JwtHeader
|
|
127
150
|
},
|
|
128
151
|
context: IRequiredContext
|
|
129
152
|
) => {
|
|
130
|
-
if (
|
|
153
|
+
if (isIdentifierMode(mode, identifier.method, 'did')) {
|
|
131
154
|
// kid is VM of the DID
|
|
132
155
|
// @see https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.4
|
|
133
156
|
await checkAndUpdateDidHeader({ header, identifier, noIdentifierInHeader }, context)
|
|
134
|
-
} else if (
|
|
157
|
+
} else if (isIdentifierMode(mode, identifier.method, 'x5c')) {
|
|
135
158
|
// Include the x5c in the header. No kid
|
|
136
159
|
// @see https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.6
|
|
137
160
|
await checkAndUpdateX5cHeader({ header, identifier, noIdentifierInHeader }, context)
|
|
138
|
-
} else if (
|
|
161
|
+
} else if (isIdentifierMode(mode, identifier.method, 'kid', false)) {
|
|
139
162
|
await checkAndUpdateKidHeader({ header, identifier, noIdentifierInHeader }, context)
|
|
140
|
-
} else if (
|
|
163
|
+
} else if (isIdentifierMode(mode, identifier.method, 'jwk', false)) {
|
|
141
164
|
// Include the JWK in the header as well as its kid if present
|
|
142
165
|
// @see https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.3
|
|
143
166
|
// @see https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.4
|
|
@@ -262,7 +285,7 @@ const checkAndUpdateKidHeader = async (
|
|
|
262
285
|
}
|
|
263
286
|
}
|
|
264
287
|
|
|
265
|
-
const
|
|
288
|
+
const isIdentifierMode = (mode: JwsIdentifierMode, identifierMethod: ManagedIdentifierMethod, checkMode: JwsIdentifierMode, loose = true) => {
|
|
266
289
|
if (loose && (checkMode === 'jwk' || checkMode === 'kid')) {
|
|
267
290
|
// we always have the kid and jwk at hand no matter the identifier method, so we are okay with that
|
|
268
291
|
// todo: check the impact on the above expressions, as this will now always return true for the both of them
|
|
@@ -277,3 +300,130 @@ const isMode = (mode: CreateJwsMode, identifierMethod: ManagedIdentifierMethod,
|
|
|
277
300
|
// we always have the kid and jwk at hand no matter the identifier method, so we are okay with that
|
|
278
301
|
return mode === 'auto' && identifierMethod === checkMode
|
|
279
302
|
}
|
|
303
|
+
|
|
304
|
+
export const verifyJws = async (args: VerifyJwsArgs, context: IAgentContext<IIdentifierResolution>): Promise<IJwsValidationResult> => {
|
|
305
|
+
const jws = await toJwsJsonGeneralWithIdentifiers(args, context)
|
|
306
|
+
|
|
307
|
+
let errorMessages: string[] = []
|
|
308
|
+
let index = 0
|
|
309
|
+
await Promise.all(
|
|
310
|
+
jws.signatures.map(async (sigWithId) => {
|
|
311
|
+
// If we have a specific KMS agent plugin that can do the verification prefer that over the generic verification
|
|
312
|
+
index++
|
|
313
|
+
let valid: boolean
|
|
314
|
+
const data = u8a.fromString(`${sigWithId.protected}.${jws.payload}`, 'utf-8')
|
|
315
|
+
const jwkInfo = sigWithId.identifier.jwks[0]
|
|
316
|
+
if (sigWithId.header?.alg === 'RSA' && contextHasPlugin(context, 'keyManagerVerify')) {
|
|
317
|
+
const publicKeyHex = jwkTtoPublicKeyHex(jwkInfo.jwk)
|
|
318
|
+
valid = await context.agent.keyManagerVerify({
|
|
319
|
+
signature: sigWithId.signature,
|
|
320
|
+
data,
|
|
321
|
+
publicKeyHex,
|
|
322
|
+
type: keyTypeFromCryptographicSuite({ suite: jwkInfo.jwk.crv ?? 'ES256' }),
|
|
323
|
+
// no kms arg, as the current key manager needs a bit more work
|
|
324
|
+
})
|
|
325
|
+
} else {
|
|
326
|
+
const signature = base64ToBytes(sigWithId.signature)
|
|
327
|
+
valid = await verifySignatureWithSubtle({ data, signature, key: jwkInfo.jwk })
|
|
328
|
+
}
|
|
329
|
+
if (!valid) {
|
|
330
|
+
errorMessages.push(`Signature ${index} was not valid`)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
sigWithId,
|
|
335
|
+
valid,
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
)
|
|
339
|
+
const error = errorMessages.length !== 0
|
|
340
|
+
return {
|
|
341
|
+
name: 'jws',
|
|
342
|
+
jws,
|
|
343
|
+
error,
|
|
344
|
+
critical: error,
|
|
345
|
+
message: error ? errorMessages.join(', ') : 'Signature validated',
|
|
346
|
+
verificationTime: new Date(),
|
|
347
|
+
} satisfies IJwsValidationResult
|
|
348
|
+
}
|
|
349
|
+
export const toJwsJsonGeneral = async ({ jws }: { jws: Jws }, context: IAgentContext<any>): Promise<JwsJsonGeneral> => {
|
|
350
|
+
let payload: string
|
|
351
|
+
let signatures: JwsJsonSignature[] = []
|
|
352
|
+
|
|
353
|
+
if (isJwsCompact(jws)) {
|
|
354
|
+
const split = jws.split('.')
|
|
355
|
+
payload = split[1]
|
|
356
|
+
signatures[0] = {
|
|
357
|
+
protected: split[0],
|
|
358
|
+
signature: split[2],
|
|
359
|
+
} satisfies JwsJsonSignature
|
|
360
|
+
} else if (isJwsJsonGeneral(jws)) {
|
|
361
|
+
payload = jws.payload
|
|
362
|
+
signatures = jws.signatures
|
|
363
|
+
} else if (isJwsJsonFlattened(jws)) {
|
|
364
|
+
const { payload: _payload, ...signature } = jws
|
|
365
|
+
payload = _payload
|
|
366
|
+
signatures = [signature]
|
|
367
|
+
} else {
|
|
368
|
+
return Promise.reject(Error(`Invalid JWS supplied`))
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
payload,
|
|
372
|
+
signatures,
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async function resolveExternalIdentifierFromJwsHeader(
|
|
377
|
+
protectedHeader: JwtHeader,
|
|
378
|
+
context: IAgentContext<IIdentifierResolution>,
|
|
379
|
+
args: {
|
|
380
|
+
jws: Jws
|
|
381
|
+
opts?: { x5c?: Omit<ExternalIdentifierX5cOpts, 'identifier'>; did?: Omit<ExternalIdentifierDidOpts, 'identifier'> }
|
|
382
|
+
}
|
|
383
|
+
) {
|
|
384
|
+
if (protectedHeader.x5c) {
|
|
385
|
+
const x5c = protectedHeader.x5c
|
|
386
|
+
return await context.agent.identifierExternalResolveByX5c({
|
|
387
|
+
...args.opts?.x5c,
|
|
388
|
+
identifier: x5c,
|
|
389
|
+
verify: true,
|
|
390
|
+
})
|
|
391
|
+
} else if (protectedHeader.jwk) {
|
|
392
|
+
const jwk = protectedHeader.jwk
|
|
393
|
+
const x5c = jwk.x5c // todo resolve x5u
|
|
394
|
+
return await context.agent.identifierExternalResolveByJwk({
|
|
395
|
+
identifier: protectedHeader.jwk,
|
|
396
|
+
...(x5c && {
|
|
397
|
+
x5c: {
|
|
398
|
+
...args?.opts?.x5c,
|
|
399
|
+
identifier: x5c,
|
|
400
|
+
},
|
|
401
|
+
}),
|
|
402
|
+
})
|
|
403
|
+
} else if (protectedHeader.kid && protectedHeader.kid.startsWith('did:')) {
|
|
404
|
+
return await context.agent.identifierExternalResolveByDid({ ...args?.opts?.did, identifier: protectedHeader.kid })
|
|
405
|
+
} else {
|
|
406
|
+
return Promise.reject(Error(`We can only process DIDs, X.509 certificate chains and JWKs for signature validation at present`))
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export const toJwsJsonGeneralWithIdentifiers = async (
|
|
411
|
+
args: {
|
|
412
|
+
jws: Jws
|
|
413
|
+
jwk?: JWK
|
|
414
|
+
opts?: { x5c?: Omit<ExternalIdentifierX5cOpts, 'identifier'>; did?: Omit<ExternalIdentifierDidOpts, 'identifier'> }
|
|
415
|
+
},
|
|
416
|
+
context: IAgentContext<IIdentifierResolution>
|
|
417
|
+
): Promise<JwsJsonGeneralWithIdentifiers> => {
|
|
418
|
+
const jws = await toJwsJsonGeneral(args, context)
|
|
419
|
+
const signatures = await Promise.all(
|
|
420
|
+
jws.signatures.map(async (signature) => {
|
|
421
|
+
const protectedHeader: JwtHeader = decodeJoseBlob(signature.protected)
|
|
422
|
+
const identifier = args.jwk
|
|
423
|
+
? await resolveExternalJwkIdentifier({ identifier: args.jwk }, context)
|
|
424
|
+
: await resolveExternalIdentifierFromJwsHeader(protectedHeader, context, args)
|
|
425
|
+
return { ...signature, identifier }
|
|
426
|
+
})
|
|
427
|
+
)
|
|
428
|
+
return { payload: jws.payload, signatures }
|
|
429
|
+
}
|
package/src/types/IJwtService.ts
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {
|
|
2
|
+
ExternalIdentifierDidOpts,
|
|
3
|
+
ExternalIdentifierResult,
|
|
4
|
+
ExternalIdentifierX5cOpts,
|
|
5
|
+
IIdentifierResolution,
|
|
6
|
+
ManagedIdentifierOptsOrResult,
|
|
7
|
+
ManagedIdentifierResult,
|
|
8
|
+
} from '@sphereon/ssi-sdk-ext.identifier-resolution'
|
|
9
|
+
import { IValidationResult, JoseSignatureAlgorithm, JoseSignatureAlgorithmString, JWK } from '@sphereon/ssi-types'
|
|
10
|
+
import { IAgentContext, IKeyManager, IPluginMethodMap } from '@veramo/core'
|
|
11
|
+
|
|
12
|
+
export type IRequiredContext = IAgentContext<IIdentifierResolution & IKeyManager> // could we still interop with Veramo?
|
|
7
13
|
|
|
8
14
|
export const jwtServiceContextMethods: Array<string> = [
|
|
9
15
|
'jwtPrepareJws',
|
|
10
16
|
'jwtCreateJwsJsonGeneralSignature',
|
|
11
17
|
'jwtCreateJwsJsonFlattenedSignature',
|
|
12
18
|
'jwtCreateJwsCompactSignature',
|
|
13
|
-
'
|
|
19
|
+
'jwtVerifyJwsSignature',
|
|
14
20
|
]
|
|
21
|
+
|
|
15
22
|
export interface IJwtService extends IPluginMethodMap {
|
|
16
23
|
jwtPrepareJws(args: CreateJwsJsonArgs, context: IRequiredContext): Promise<PreparedJwsObject>
|
|
17
24
|
|
|
@@ -21,11 +28,15 @@ export interface IJwtService extends IPluginMethodMap {
|
|
|
21
28
|
|
|
22
29
|
jwtCreateJwsCompactSignature(args: CreateJwsCompactArgs, context: IRequiredContext): Promise<JwsCompactResult>
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
jwtVerifyJwsSignature(args: VerifyJwsArgs, context: IRequiredContext): Promise<IJwsValidationResult>
|
|
25
32
|
|
|
26
33
|
// TODO: JWE/encryption
|
|
27
34
|
}
|
|
28
35
|
|
|
36
|
+
export type IJwsValidationResult = IValidationResult & {
|
|
37
|
+
jws: JwsJsonGeneralWithIdentifiers // We always translate to general as that is the most flexible format allowing multiple sigs
|
|
38
|
+
}
|
|
39
|
+
|
|
29
40
|
export interface PreparedJws {
|
|
30
41
|
protectedHeader: JwtHeader
|
|
31
42
|
payload: Uint8Array
|
|
@@ -39,6 +50,8 @@ export interface JwsJsonSignature {
|
|
|
39
50
|
signature: string
|
|
40
51
|
}
|
|
41
52
|
|
|
53
|
+
export type Jws = JwsCompact | JwsJsonFlattened | JwsJsonGeneral
|
|
54
|
+
|
|
42
55
|
export type JwsCompact = string
|
|
43
56
|
|
|
44
57
|
export interface JwsJsonFlattened {
|
|
@@ -53,6 +66,14 @@ export interface JwsJsonGeneral {
|
|
|
53
66
|
signatures: Array<JwsJsonSignature>
|
|
54
67
|
}
|
|
55
68
|
|
|
69
|
+
export interface JwsJsonGeneralWithIdentifiers extends JwsJsonGeneral {
|
|
70
|
+
signatures: Array<JwsJsonSignatureWithIdentifier>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface JwsJsonSignatureWithIdentifier extends JwsJsonSignature {
|
|
74
|
+
identifier: ExternalIdentifierResult
|
|
75
|
+
}
|
|
76
|
+
|
|
56
77
|
export interface PreparedJwsObject {
|
|
57
78
|
jws: PreparedJws
|
|
58
79
|
b64: { payload: string; protectedHeader: string } // header is always json, as it can only be used in JwsJson
|
|
@@ -64,6 +85,7 @@ export interface BaseJwtHeader {
|
|
|
64
85
|
alg?: string
|
|
65
86
|
kid?: string
|
|
66
87
|
}
|
|
88
|
+
|
|
67
89
|
export interface BaseJwtPayload {
|
|
68
90
|
iss?: string
|
|
69
91
|
sub?: string
|
|
@@ -87,14 +109,17 @@ export interface JwtPayload extends BaseJwtPayload {
|
|
|
87
109
|
}
|
|
88
110
|
|
|
89
111
|
export interface JwsHeaderOpts {
|
|
90
|
-
|
|
112
|
+
alg: JoseSignatureAlgorithm | JoseSignatureAlgorithmString
|
|
91
113
|
}
|
|
92
114
|
|
|
93
|
-
export type
|
|
115
|
+
export type JwsIdentifierMode = 'x5c' | 'kid' | 'jwk' | 'did' | 'auto'
|
|
94
116
|
|
|
95
117
|
export type CreateJwsArgs = {
|
|
96
|
-
mode?:
|
|
97
|
-
issuer: ManagedIdentifierOptsOrResult & {
|
|
118
|
+
mode?: JwsIdentifierMode
|
|
119
|
+
issuer: ManagedIdentifierOptsOrResult & {
|
|
120
|
+
noIssPayloadUpdate?: boolean
|
|
121
|
+
noIdentifierInHeader?: boolean
|
|
122
|
+
}
|
|
98
123
|
protectedHeader: JwtHeader
|
|
99
124
|
payload: JwtPayload | Uint8Array | string
|
|
100
125
|
}
|
|
@@ -103,6 +128,12 @@ export type CreateJwsCompactArgs = CreateJwsArgs
|
|
|
103
128
|
|
|
104
129
|
export type CreateJwsFlattenedArgs = Exclude<CreateJwsJsonArgs, 'existingSignatures'>
|
|
105
130
|
|
|
131
|
+
export type VerifyJwsArgs = {
|
|
132
|
+
jws: Jws
|
|
133
|
+
jwk?: JWK // Jwk will be resolved from jws, but you can also provide one
|
|
134
|
+
opts?: { x5c?: Omit<ExternalIdentifierX5cOpts, 'identifier'>; did?: Omit<ExternalIdentifierDidOpts, 'identifier'> }
|
|
135
|
+
}
|
|
136
|
+
|
|
106
137
|
/**
|
|
107
138
|
* @public
|
|
108
139
|
*/
|
|
@@ -118,4 +149,16 @@ export interface JwsCompactResult {
|
|
|
118
149
|
jwt: JwsCompact
|
|
119
150
|
}
|
|
120
151
|
|
|
121
|
-
|
|
152
|
+
export function isJwsCompact(jws: Jws): jws is JwsCompact {
|
|
153
|
+
return typeof jws === 'string' && jws.split('~')[0].match(COMPACT_JWS_REGEX) !== null
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function isJwsJsonFlattened(jws: Jws): jws is JwsJsonFlattened {
|
|
157
|
+
return typeof jws === 'object' && 'signature' in jws && 'protected' in jws
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function isJwsJsonGeneral(jws: Jws): jws is JwsJsonGeneral {
|
|
161
|
+
return typeof jws === 'object' && 'signatures' in jws
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const COMPACT_JWS_REGEX = /^([a-zA-Z0-9_=-]+)\.([a-zA-Z0-9_=-]+)?\.([a-zA-Z0-9_=-]+)$/
|