Issue JWT from lambda

I was messing around with dgraph lambdas for a side project and wanted to issue JWTs from this lambda (more or less to hide the secret used to sign with) and it took me a long time to get something to work. I am mostly a golang programmer these days so javascript was super annoying for me… but I wanted to share what I had in case it helps someone else save a few hours.

(disclaimer: no warranty, no support, no liability, not security advice)

const hdr = {"alg": "HS256","typ": "JWT"}
const tokenExpirySeconds = 900

// not to be registered directly as a lambda but called from a lambda registered function
async function CreateAndSignJWTWithClaims(claims, secretKey) {

   const now = ~~(Date.now()/1000)
   claims.iat=now
   claims.exp=now+tokenExpirySeconds

   const unsignedToken = base64url(JSON.stringify(hdr)) + "." + base64url(JSON.stringify(claims))
   const key = await crypto.subtle.importKey(
      "raw",
      new TextEncoder().encode(secretKey),
      {name: "HMAC", hash: "SHA-256" },
      false,
      ["sign"]
   )
   const sig = await crypto.subtle.sign(
      {name:"HMAC"},
      key,
      new TextEncoder().encode(unsignedToken)
   )
   return unsignedToken + "." + base64url(_arrayBufferToBinary(sig))
}

// this is used to change standard base64 to jwt-ready base64. Adapted from stackoverflow
function base64url(source) {
   encodedSource = btoa(source)
   encodedSource = encodedSource.replace(/=+$/, '')
   encodedSource = encodedSource.replace(/\+/g, '-')
   encodedSource = encodedSource.replace(/\//g, '_')
   return encodedSource
}

// this is modified from stackoverflow "how to turn an ArrayBuffer into an Uint8Array"
// I really hope there is some other way to do this....
function _arrayBufferToBinary( buffer ) {
   var binary = '';
   var bytes = new Uint8Array( buffer );
   var len = bytes.byteLength;
   for (var i = 0; i < len; i++) {
      binary += String.fromCharCode( bytes[ i ] );
   }
   return binary ;
}

Again, I do not know if there is a better way to do this, but I wanted a thing that would sign a jwt without using webpack. Sorry if there is already a better snippet out there that does this. The above will make a JWT that is usable with dgraph given the secretKey given as the VerificationKey in the annotation:

# Dgraph.Authorization {"VerificationKey":"SECRETKEY","Algo":"HS256"}

Also, for the record, javascript is infuriating.

Yes. There is a community made golang lambda server available. You might want to use that instead.

@Schartey Are you still working actively on that project?

yea I made the project expecting the $10/mo shared instance of dgraph cloud and using the built-in lambda support, but now that is $40 and I probably should have just went with golang from the get-go.

But yea, super cool library, thanks @Schartey