3

I'm trying to create a signature for the JW Platform API. It requires a URL parameter named "api_signature" that a SHA1 digest of every other URL parameter.

I tried creating the parameter with the SHA1 digest dynamic with a JS Script as its input. Here's the basic code from the JS Script:

function evaluate(context)
{
    var request = context.getCurrentRequest()
    var params  = request.getUrlParameters()
    var sbs     = ''

    for (key of params) {
        if (key === 'api_signature')
            continue;

        if (sbs.length > 0)
            sbs += '&'

        sbs += encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
    }

    return sbs + '<API SECRET GOES HERE>'
}

But with this I get the warning:

JS Script cannot be used in URL Parameter Value because this creates a self-dependency.

How can I get around this?

donut
  • 9,427
  • 5
  • 36
  • 53

1 Answers1

4

The reason this warning appears is because request.getURLParameters() has to evaluate all the url parameters of the request, including api_signature, and therefore has to call the method evaluate of the JS Script, thus creating an infinite recursion issue which is detected and blocked at the first iteration (the content of the dangerous url parameter is replaced by '').

In theory, one could avoid this issue by using request.getURLParameters(true), which returns a non-evaluated DynamicString for each url parameter. However, it seems that in practice, the detection is a bit too strong and it will still raise the warning.

Another solution could be to use request.getURLParametersNames() and request.getURLParameterByName(name) together. However, the detection is again too strong and a warning is raised.

Both of these solutions should in theory work without raising a warning, and we are working on a fix for this issue in Paw 3.0.13. In any case, although a warning is raised, the script still functions normally.

Example with request.getURLParameters(true)

function evaluate(context)
{
    var request = context.getCurrentRequest()
    var params  = request.getUrlParameters(true)
    var sbs     = []

    for (var key in params) {
        if (key === 'api_signature')
            continue;

        sbs.push(encodeURIComponent(key) + '=' +
                 encodeURIComponent(params[key].getEvaluatedString()))
    }

    return sbs.join('&') + '<API SECRET GOES HERE>'
}

Example with request.getURLParametersName()

function evaluate(context)
{
    var request = context.getCurrentRequest()
    var params  = request.getUrlParametersNames()
    var sbs     = []

    for (var param of params) {
        if (param === 'api_signature')
            continue;

        sbs.push(encodeURIComponent(param) + '=' +
                 encodeURIComponent(request.getUrlParameterByName(param)))
    }

    return sbs.join('&') + '<API SECRET GOES HERE>'
}
Jonathan Montane
  • 386
  • 3
  • 10