import crypto from 'crypto' import * as base64UrlSafe from './base64urlsafe.mjs' import defaults from '../defaults.mjs' export default function encode(orgHeader, orgBody, privateKeyPassword = null, disableAutofill = false) { if ( typeof orgHeader !== 'object' || typeof orgBody !== 'object' ) { throw new Error('both header and body should be of type object') } let header = defaults(orgHeader) let body = defaults(orgBody) if (!header.alg) { header.alg = 'HS256' } if (!header.typ) { header.typ = 'JWT' } let hmacAlgo = null switch (header.alg) { case 'HS256': hmacAlgo = 'sha256' break case 'HS384': hmacAlgo = 'sha384' break case 'HS512': hmacAlgo = 'sha512' break default: throw new Error( 'Only alg HS256, HS384 and HS512 are supported' ) } if (!body.iat && !disableAutofill) { body.iat = Math.floor(Date.now() / 1000) } if (!body.exp && !disableAutofill) { body.exp = body.iat + 300 } // Base64 encode header and body let headerBase64 = base64UrlSafe.encode(Buffer.from(JSON.stringify(header))) let bodyBase64 = base64UrlSafe.encode(Buffer.from(JSON.stringify(body))) let headerBodyBase64 = headerBase64 + '.' + bodyBase64 const hmac = crypto.createHmac(hmacAlgo, privateKeyPassword) hmac.update(headerBodyBase64) let signatureBuffer = hmac.digest() // Construct final JWT let signatureBase64 = base64UrlSafe.encode(signatureBuffer) return headerBodyBase64 + '.' + signatureBase64 }