Custom hmac function for iink-ts via Cloudflare Workers returns WRONG_CREDENTIALS
H
Hs160227
started a topic
2 minutes ago
Hi MyScript team,
I'm building a web app using iink-ts (v4.1.0) and hosting it on Cloudflare Pages. For security reasons, I do not want to expose the hmacKey in the frontend. Therefore, I am trying to use the custom hmac function provided in the server configuration to calculate the HMAC signature on my own Cloudflare Worker backend ( /api/hmac ).
However, when the client tries to connect, it fails with the error: Application credentials are invalid. Please check or regenerate your application key and hmackey.
Hs160227
Hi MyScript team,
I'm building a web app using iink-ts (v4.1.0) and hosting it on Cloudflare Pages. For security reasons, I do not want to expose the hmacKey in the frontend. Therefore, I am trying to use the custom hmac function provided in the server configuration to calculate the HMAC signature on my own Cloudflare Worker backend ( /api/hmac ).
However, when the client tries to connect, it fails with the error: Application credentials are invalid. Please check or regenerate your application key and hmackey.
Here is my frontend setup:
canvas = await iink.Canvas.load(editorEl, "INTERACTIVE_INK", {
configuration: {
server: {
applicationKey: 'MY_APP_KEY',
hmacKey: 'placeholder', // to bypass the internal validation
hmac: async (challenge) => {
const response = await fetch('/api/hmac', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ challenge })
});
const data = await response.json();
return data.hmac;
}
}
}
});
Here is my Cloudflare Worker backend (/api/hmac):
export async function onRequestPost(context) {
const APP_KEY = context.env.MYSCRIPT_APP_KEY;
const HMAC_KEY = context.env.MYSCRIPT_HMAC_KEY;
const { challenge } = await context.request.json();
const encoder = new TextEncoder();
// Attempt 1: Using APP_KEY + HMAC_KEY as the key
const combinedKey = APP_KEY + HMAC_KEY;
const key = await crypto.subtle.importKey(
'raw',
encoder.encode(combinedKey),
{ name: 'HMAC', hash: 'SHA-512' },
false,
['sign']
);
const signature = await crypto.subtle.sign(
'HMAC',
key,
encoder.encode(challenge)
);
// Converting to Hex
const hex = Array.from(new Uint8Array(signature))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
return new Response(JSON.stringify({ hmac: hex }), {
headers: { 'Content-Type': 'application/json' },
});
}
I have tried different variations (using just HMAC_KEY as the key, using Base64 instead of Hex, etc.), but all of them return WRONG_CREDENTIALS.
Could you please clarify the exact algorithm used by iink-ts internally for computeHmac?
Should the secret key be the applicationKey, the hmacKey, or a concatenation of both?
What is the exact string being signed? Is it just the challenge?
Should the final output returned to iink-ts be Hex encoded or Base64 encoded?