generateSignatureIfSecret.js 1.2 KB

12345678910111213141516171819202122232425262728293031323334
  1. const enc = new TextEncoder('utf-8')
  2. async function sign (secret, body) {
  3. const algorithm = { name: 'HMAC', hash: 'SHA-384' }
  4. const key = await crypto.subtle.importKey('raw', enc.encode(secret), algorithm, false, ['sign', 'verify'])
  5. const signature = await crypto.subtle.sign(algorithm.name, key, enc.encode(body))
  6. return `sha384:${Array.from(new Uint8Array(signature), x => x.toString(16).padStart(2, '0')).join('')}`
  7. }
  8. function getExpiration (future) {
  9. return new Date(Date.now() + future)
  10. .toISOString()
  11. .replace('T', ' ')
  12. .replace(/\.\d+Z$/, '+00:00')
  13. }
  14. /**
  15. * Adds an expiration date and signs the params object if a secret is passed to
  16. * it. If no secret is given, it returns the same object.
  17. *
  18. * @param {string | undefined} secret
  19. * @param {object} params
  20. * @returns {Promise<{ params: string, signature?: string }>}
  21. */
  22. export default async function generateSignatureIfSecret (secret, params) {
  23. let signature
  24. if (secret) {
  25. // eslint-disable-next-line no-param-reassign
  26. params.auth.expires = getExpiration(5 * 60 * 1000)
  27. // eslint-disable-next-line no-param-reassign
  28. params = JSON.stringify(params)
  29. signature = await sign(secret, params)
  30. }
  31. return { params, signature }
  32. }