Do anyone here knows flex builder?
I'm a beginner in this language. I have written a code for cloudstack api request and signature generation using hmac to authenticate the user account. here the command is 'listzones'. The output will be in xml shwing the list of zones available in the cloudstack i have installed. No error is showing while compiling. But when i run, the browser opens blank. The url is correct, ie it includes alla the commands and parameters and also the signature is genetated. I can see it in the url.But the orginal output is xml command it is not showing. the page is simply left blank. Can anyone help me?

the url generated will like as below:

The signature generated may vary each time.

The code is as follows.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="" 
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:ns1="*">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.adobe.crypto.HMAC;
import com.adobe.crypto.SHA1;
import com.adobe.utils.StringUtil;
import flash.net.navigateToURL;
import mx.controls.Alert;
import mx.utils.Base64Encoder;
import mx.utils.StringUtil;
private var urlAPI:String;
private var commandString:String;
private var apiKey:String;
private var apiKeyString:String;
private var secretKey:String = "-kgkBuBUrGFeIC4gUvngSK_3Ypmi7fuF8XdVXIusnyyiEP2YUcG3FnPUGJGy3rp3Bw5ZNnqgS-9tIfyV1QnK1g";
private var signature:String;
private var urlRequestString:String
[Bindable]
private var encryptedString:String = "";
[Bindable]
private var encryptedByteArray:String = "";
private function generateRequest():void
{
    urlAPI = "";
    commandString = "command=listZones";
    apiKey = "";
    apiKey = encodeURI(apiKey.toLowerCase());
    apiKeyString = "apiKey=" + apiKey;
    signature = generateSignature();
    urlRequestString = urlAPI +"?"+commandString+"&"+apiKeyString+"&signature="+signature;// "command=listZones&apiKey=Qo9Qwfatwz9ARB328Btn9PftzL2Cf5LOWd8OFyJmiM513tpTIm-zKxJoWkWqf353Df397xcLdKXGk8_JO8nM3Q&signature=Lxx1DM40AjcXU%2FcaiK8RAP0O1hU%3D";
    var urlRequestObj:URLRequest = new URLRequest(urlRequestString);
    navigateToURL(urlRequestObj,"_blank");
}
private function generateSignature():String
{
    var tempSignature:String = apiKey +"&"+commandString;
    tempSignature = tempSignature.toLowerCase();
    return hashMessage(tempSignature,secretKey);
}
private function hashMessage(message:String, secretKey:String):String
{           
    var algorithm:Object = SHA1;
    var encoder:Base64Encoder = new Base64Encoder();
    if(message.length > 0)
    {
        encryptedString = HMAC.hash(secretKey,message,algorithm);
        var messageBytes:ByteArray = new ByteArray();
        messageBytes.writeMultiByte(message,"utf-8");
        encryptedByteArray = HMAC.hashBytes(getByteArray(),messageBytes,algorithm);
        encoder.encode(encryptedByteArray); 
    }
    //Alert.show(encoder.toString());
    return encoder.toString();      
}
private var byteArray:ByteArray;
[Bindable("dummyEventType")]
private function  getByteArray():ByteArray
{
    if(!byteArray)
    {
        byteArray = new ByteArray();
        byteArray.writeMultiByte(secretKey,"utf-8");
        //byteArray.
    }
    return byteArray;
}   
]]>
 </fx:Script>
<s:Button x="102" y="64" label="Button" click="generateRequest()"/>
<ns1:CloudInterfaceComp x="196" y="213">
</ns1:CloudInterfaceComp>
 </s:Application>

Dani AI

Generated

A short diagnostic summary for (and follow-up pointers from ): the Python client succeeds but the Flex run returns an HTTP 401 / blank page because the server is rejecting the request signature. That almost always comes from a mismatch between the exact canonical string that was signed and what the server expects (encoding, casing, sorting) or from incorrect Base64/byte handling on the ActionScript side.

CloudStack signing checklist (follow these steps exactly): percent-encode each parameter value (encode spaces as "%20" not "+"), build "key=value" pairs, lowercase the full command string and sort the pairs alphabetically by key, compute HMAC-SHA1 over that lowercased string using the secret key, Base64-encode the raw HMAC bytes, then URL-encode the Base64 result before appending it as the signature. The CloudStack developer guide has the same step-by-step algorithm and a Python example to compare against. (docs.cloudstack.apache.org)

ActionScript-specific fixes to apply:

  • Encode parameter values with a component-level encoder (encodeURIComponent semantics) before assembling the string-to-sign; do not rely on encodeURI for query values.
  • Build the canonical string exactly the same way as the Python example (encode values, then lowercase the full joined string, then sort).
  • Compute the HMAC over a ByteArray of the lowercased canonical string (use the HMAC.hashBytes API so the result is raw bytes).
  • Feed the raw HMAC ByteArray into mx.utils.Base64Encoder.encodeBytes (set encoder.insertNewLines = false) and call toString(). Finally URL-encode the base64 output (replace "+" -> "%2B", "/" -> "%2F", "=" -> "%3D") before adding it to the URL. The Base64Encoder docs explain encodeBytes and the insertNewLines behavior. (flex.apache.org)

Minimal debug workflow:

  • Log the canonical string (byte-for-byte) used by Python and by Flex; they must match exactly before HMAC.
  • Log the Base64 result (before URL-encoding) from both clients and compare.
  • Ensure the same secret bytes are used (writeUTFBytes/writeMultiByte consistently).
  • If the new window stays blank, capture the exact URL that navigateToURL sends and paste it into a normal browser tab to inspect the raw response (the blank window is often a client-side encoding/URL problem rather than a server-side rendering issue).

Example (core AS3 steps for encoding the HMAC bytes to the final, URL-safe signature):

// given: canonicalString (already percent-encoded, lowercased, sorted), secretKey:String
var msgBytes:ByteArray = new ByteArray();
msgBytes.writeUTFBytes(canonicalString);

var keyBytes:ByteArray = new ByteArray();
keyBytes.writeUTFBytes(secretKey);

var hmacBytes:ByteArray = HMAC.hashBytes(keyBytes, msgBytes, SHA1);

var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encodeBytes(hmacBytes);
var sigBase64:String = encoder.toString();

// URL-encode the Base64 result for inclusion in the query string
sigBase64 = sigBase64.replace(/\+/g, "%2B").replace(/\//g, "%2F").replace(/=/g, "%3D");

Following the exact CloudStack canonicalization and using Base64Encoder.encodeBytes (no newlines) will normally fix the 401 signature error; comparing the intermediate strings with the working Python run will pinpoint any remaining mismatch. (docs.cloudstack.apache.org)

Recommended Answers

All 6 Replies

Member Avatar for Member #949455

The url is correct, ie it includes alla the commands and parameters and also the signature is genetated. I can see it in the url.But the orginal output is xml command it is not showing. the page is simply left blank. Can anyone help me?

This address is local:

Try test it on a host server meaning on your actual website.

but when i use python, it works!! The same address is i'm using.In python the response is generated in xml format.. like

 This XML file does not appear to have any style information associated with it. The document tree is shown below.
<listzonesresponse cloud-stack-version="4.0.1.20130201075054">
<count>1</count>
<zone>
<id>2846f124-546b-4a6e-805b-035a7938606a</id>
<name>Zone1</name>
<dns1>172.16.51.1</dns1>
<dns2>172.16.51.5</dns2>
<internaldns1>172.16.38.254</internaldns1>
<networktype>Basic</networktype>
<securitygroupsenabled>true</securitygroupsenabled>
<allocationstate>Enabled</allocationstate>
<zonetoken>3e39c03d-cda1-336b-b89b-4db91fdee3a7</zonetoken>
<dhcpprovider>VirtualRouter</dhcpprovider>
<localstorageenabled>false</localstorageenabled>
</zone>
</listzonesresponse>

when I execute flex program i'm getting the response like

<?xml version="1.0" encoding="UTF-8"?>
-<listzonesresponse cloud-stack-version="4.0.1.20130201075054"><errorcode>401</errorcode><errortext>unable to verify user credentials and/or request signature</errortext></listzonesresponse>
Member Avatar for Member #949455

but when i use python, it works!! The same address is i'm using.In python the response is generated in xml format.. like

I assume you are using some sort of Python framework like this:

https://www.djangoproject.com/

I don't think you understand my question.

This address is local:

10.176.14.26:8080

meaning it's on your computer.

This is an example of a website using python:

http://pinterest.com/

As you can see it's an actual website address not a local address: 10.176.14.26:8080

Also take a look at this:

no im using python 27 and the output url is correct. i think there might be some error in the encoding area in the flex code but i can't identify the problem. can you please check the encoding area in this code???

Member Avatar for Member #949455

i think there might be some error in the encoding area in the flex code but i can't identify the problem. can you please check the encoding area in this code???

I did. Did you read the link I provided? There's code you need to implement to your code.

Thank you so much for the link :) let me try..
:)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.