verify.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { decode as base64url } from '../../runtime/base64url.js';
  2. import verify from '../../runtime/verify.js';
  3. import { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';
  4. import { concat, encoder, decoder } from '../../lib/buffer_utils.js';
  5. import isDisjoint from '../../lib/is_disjoint.js';
  6. import isObject from '../../lib/is_object.js';
  7. import checkKeyType from '../../lib/check_key_type.js';
  8. import validateCrit from '../../lib/validate_crit.js';
  9. import validateAlgorithms from '../../lib/validate_algorithms.js';
  10. export async function flattenedVerify(jws, key, options) {
  11. var _a;
  12. if (!isObject(jws)) {
  13. throw new JWSInvalid('Flattened JWS must be an object');
  14. }
  15. if (jws.protected === undefined && jws.header === undefined) {
  16. throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members');
  17. }
  18. if (jws.protected !== undefined && typeof jws.protected !== 'string') {
  19. throw new JWSInvalid('JWS Protected Header incorrect type');
  20. }
  21. if (jws.payload === undefined) {
  22. throw new JWSInvalid('JWS Payload missing');
  23. }
  24. if (typeof jws.signature !== 'string') {
  25. throw new JWSInvalid('JWS Signature missing or incorrect type');
  26. }
  27. if (jws.header !== undefined && !isObject(jws.header)) {
  28. throw new JWSInvalid('JWS Unprotected Header incorrect type');
  29. }
  30. let parsedProt = {};
  31. if (jws.protected) {
  32. try {
  33. const protectedHeader = base64url(jws.protected);
  34. parsedProt = JSON.parse(decoder.decode(protectedHeader));
  35. }
  36. catch {
  37. throw new JWSInvalid('JWS Protected Header is invalid');
  38. }
  39. }
  40. if (!isDisjoint(parsedProt, jws.header)) {
  41. throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');
  42. }
  43. const joseHeader = {
  44. ...parsedProt,
  45. ...jws.header,
  46. };
  47. const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options === null || options === void 0 ? void 0 : options.crit, parsedProt, joseHeader);
  48. let b64 = true;
  49. if (extensions.has('b64')) {
  50. b64 = parsedProt.b64;
  51. if (typeof b64 !== 'boolean') {
  52. throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
  53. }
  54. }
  55. const { alg } = joseHeader;
  56. if (typeof alg !== 'string' || !alg) {
  57. throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
  58. }
  59. const algorithms = options && validateAlgorithms('algorithms', options.algorithms);
  60. if (algorithms && !algorithms.has(alg)) {
  61. throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter not allowed');
  62. }
  63. if (b64) {
  64. if (typeof jws.payload !== 'string') {
  65. throw new JWSInvalid('JWS Payload must be a string');
  66. }
  67. }
  68. else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {
  69. throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');
  70. }
  71. let resolvedKey = false;
  72. if (typeof key === 'function') {
  73. key = await key(parsedProt, jws);
  74. resolvedKey = true;
  75. }
  76. checkKeyType(alg, key, 'verify');
  77. const data = concat(encoder.encode((_a = jws.protected) !== null && _a !== void 0 ? _a : ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);
  78. let signature;
  79. try {
  80. signature = base64url(jws.signature);
  81. }
  82. catch {
  83. throw new JWSInvalid('Failed to base64url decode the signature');
  84. }
  85. const verified = await verify(alg, key, signature, data);
  86. if (!verified) {
  87. throw new JWSSignatureVerificationFailed();
  88. }
  89. let payload;
  90. if (b64) {
  91. try {
  92. payload = base64url(jws.payload);
  93. }
  94. catch {
  95. throw new JWSInvalid('Failed to base64url decode the payload');
  96. }
  97. }
  98. else if (typeof jws.payload === 'string') {
  99. payload = encoder.encode(jws.payload);
  100. }
  101. else {
  102. payload = jws.payload;
  103. }
  104. const result = { payload };
  105. if (jws.protected !== undefined) {
  106. result.protectedHeader = parsedProt;
  107. }
  108. if (jws.header !== undefined) {
  109. result.unprotectedHeader = jws.header;
  110. }
  111. if (resolvedKey) {
  112. return { ...result, key };
  113. }
  114. return result;
  115. }