Search code examples
javascriptnode.jsanalyticsadobe-analyticssegments

Adobe Analytics Segments API auth issue with node.js client


I'm facing an authorization issue trying to use Segments APIs via a node.js client. Stop beating around the bush, below the part of it which manages the POST request and the authorization via the x-wsse headers:

var now = new Date();
var options = {
     method: "POST",
     hostname: "api3.omniture.com",
     path: "/admin/1.4/rest/?method=Segments.Get",
     json: true,
     headers: {
            "Content-Type": "application/json",
            "Content-Length" : Buffer.byteLength(JSON.stringify(body)),
            "x-wsse": 'UsernameToken Username="[username]:[company]", PasswordDigest="xxxxxxxxxxxxxxxxxxxxxxxxxx==", Nonce="yyyyyyyyyyyyyyyyyyyyyyyyyy", Created="'+now+'"'
     }
};

As you see, I'm trying to replicate the x-wsse generated by the API Explorer, dynamically specifying the Created timestap via Date() JS class. Node client is reporting me this error:
{"error":"Bad Request","error_description":"Unable to validate authentication.","error_uri":null}

I suppose the x-wsse PasswordDigest and Nonce values also continuously change at every request while here I put them static. If this was the reason for the issue, how dynamically insert also those parameters in the x-wsse header ?

Thanks a lot.


Solution

  • Yes, the PasswordDigest and Created values are also dynamically generated, because they are based on the value you generate. I don't know node.js well enough to show you a node.js example, but here is a php example for what I do, with some comments:

    $username='user:company';
    $secret='12345'; // api shared secret key for the user
    // The nonce should be a universally unique value. I use a timestamp based value and prefix with a namespace to help make it unique, because AA request digests have to be unique across everybody everywhere ever
    $nonce = 'FOO_'.dechex(time());
    // datetime stamp in ISO 8601 date format (e.g. '2004-02-12T15:19:21+00:00')
    $nonce_ts = date('c');
    // Adobe expects the PasswordDigest to be a concatenated string value of the nonce, datetimestamp, and api key. They expect it to be hashed (sha1) and then base64 encoded
    $digest = base64_encode(sha1($nonce.$nonce_ts.$secret));
    $server = "https://api.omniture.com";
    $path = "/admin/1.4/rest/";
    $rc=new SimpleRestClient();
    $rc->setOption(CURLOPT_HTTPHEADER, array("X-WSSE: UsernameToken Username=\"$username\", PasswordDigest=\"$digest\", Nonce=\"$nonce\", Created=\"$nonce_ts\""));