iink SDK Web

Custom hmac function for iink-ts via Cloudflare Workers returns WRONG_CREDENTIALS

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?

Login or Signup to post a comment