UNPKG

3.27 kBJavaScriptView Raw
1const isObject = require('../help/is_object')
2let validateCrit = require('../help/validate_crit')
3const { JWSInvalid } = require('../errors')
4
5validateCrit = validateCrit.bind(undefined, JWSInvalid)
6
7const compactSerializer = (payload, [recipient]) => {
8 return `${recipient.protected}.${payload}.${recipient.signature}`
9}
10compactSerializer.validate = (jws, { 0: { unprotectedHeader, protectedHeader }, length }) => {
11 if (length !== 1 || unprotectedHeader) {
12 throw new JWSInvalid('JWS Compact Serialization doesn\'t support multiple recipients or JWS unprotected headers')
13 }
14 validateCrit(protectedHeader, unprotectedHeader, protectedHeader ? protectedHeader.crit : undefined)
15}
16
17const flattenedSerializer = (payload, [recipient]) => {
18 const { header, signature, protected: prot } = recipient
19
20 return {
21 payload,
22 ...prot ? { protected: prot } : undefined,
23 ...header ? { header } : undefined,
24 signature
25 }
26}
27flattenedSerializer.validate = (jws, { 0: { unprotectedHeader, protectedHeader }, length }) => {
28 if (length !== 1) {
29 throw new JWSInvalid('Flattened JWS JSON Serialization doesn\'t support multiple recipients')
30 }
31 validateCrit(protectedHeader, unprotectedHeader, protectedHeader ? protectedHeader.crit : undefined)
32}
33
34const generalSerializer = (payload, recipients) => {
35 return {
36 payload,
37 signatures: recipients.map(({ header, signature, protected: prot }) => {
38 return {
39 ...prot ? { protected: prot } : undefined,
40 ...header ? { header } : undefined,
41 signature
42 }
43 })
44 }
45}
46generalSerializer.validate = (jws, recipients) => {
47 let validateB64 = false
48 recipients.forEach(({ protectedHeader, unprotectedHeader }) => {
49 if (protectedHeader && !validateB64 && 'b64' in protectedHeader) {
50 validateB64 = true
51 }
52 validateCrit(protectedHeader, unprotectedHeader, protectedHeader ? protectedHeader.crit : undefined)
53 })
54
55 if (validateB64) {
56 const values = recipients.map(({ protectedHeader }) => protectedHeader && protectedHeader.b64)
57 if (!values.every((actual, i, [expected]) => actual === expected)) {
58 throw new JWSInvalid('the "b64" Header Parameter value MUST be the same for all recipients')
59 }
60 }
61}
62
63const isJSON = (input) => {
64 return isObject(input) && (typeof input.payload === 'string' || Buffer.isBuffer(input.payload))
65}
66
67const isValidRecipient = (recipient) => {
68 return isObject(recipient) && typeof recipient.signature === 'string' &&
69 (recipient.header === undefined || isObject(recipient.header)) &&
70 (recipient.protected === undefined || typeof recipient.protected === 'string')
71}
72
73const isMultiRecipient = (input) => {
74 if (Array.isArray(input.signatures) && input.signatures.every(isValidRecipient)) {
75 return true
76 }
77
78 return false
79}
80
81const detect = (input) => {
82 if (typeof input === 'string' && input.split('.').length === 3) {
83 return 'compact'
84 }
85
86 if (isJSON(input)) {
87 if (isMultiRecipient(input)) {
88 return 'general'
89 }
90
91 if (isValidRecipient(input)) {
92 return 'flattened'
93 }
94 }
95
96 throw new JWSInvalid('JWS malformed or invalid serialization')
97}
98
99module.exports = {
100 compact: compactSerializer,
101 flattened: flattenedSerializer,
102 general: generalSerializer,
103 detect
104}