Log in or register to post comments

VWS Requests in C# from Unity - Authentication

February 4, 2013 - 1:54am #1

Hi All

I have been trying now for a bit to get some joy connecting from my Unity Application to the Cloud Target VWS. I have written a class that does (I think) all the required hoops and jumps to properly sign the API requests as documented. I'm obviously doing something wrong since its not working! My code is loosely based on the Java code supplied in the documentation. I'm going to post my code here in the hope that someone else is interested in achieving the same thing and will see what I have missed since I now have my frustration blinkers on.

NOTE: The following class relies on UniWeb on the Unity Asset store (sorry thats a slight barrier to helping me since its $55). If you have that then you can drop this script directly onto a gameobject and fill in your access and private keys, assign a texture and then hit play.

Problems: 

- For uploading Targets I get a json response ok, but I can;t get it to authenticate. eg. {"result_code":"AuthenticationFailure","transaction_id":"aa28a843f79546c7b27d222ebbada893"}

- For get requests - the first time I run one I get an empty response from VWS but a status of OK on the web request? Subsequent calls without waiting a period of time result in a  "System.Net.Sockets.SocketException: Connection refused" error. Note this may be to do with UniWeb, I'm not sure.

Hopefully someone can help.

Code:

//****************************************************************//

//CloudConnector.cs
//Tom Mulder.
//4/2/2013
//
//This code is loosely based on the java sample code provided in the vuforia VWS documentation.
//
//NOTE: This class references classes and functions provided by the UniWeb plugin available on the Unity Asset Store.


using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

//Simple class to describe a target to submit to the Cloud.
public class TargetData
{
	public TargetData(Texture2D tex, int width, string name)
	{
		SetImage(tex);
		this.width = width.ToString();
		this.name = name;
	}
		
	public string image = "";
	public string width = "500";
	public string name = "target_tom";
	public bool active_flag = true;
	
	public void SetImage(Texture2D tex)
	{
		image = System.Convert.ToBase64String(tex.EncodeToPNG());
	}
}

// Delegate template for callback functions passed to CloudConnector.Request
public delegate void CloudRequestCallback(HTTP.Response response);

//Singleton Cloud Connector Class.
public class CloudConnector : MonoBehaviour {
	private static CloudConnector instance = null;
	public static CloudConnector Instance {get {return instance;}}

	public string accessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Assign Access Key in the inspector
	public string secretKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Assign Secret Key in the inspector
	private const string md5Empty = "d41d8cd98f00b204e9800998ecf8427e";
	
	public string host = "vws.vuforia.com"; // Host
	
	public Rect buttonRect = new Rect(0,0,200,50);
	
	public Texture2D target; //Assign an RGB24 texture here
	public string targetName = "testTarget";
	
	public string demoTargetID = "1b439839e42d4d2e8e3d70a82f80afec";
	
	// Start
	void Start () {
		if(instance != null)
		{
			Destroy(this);
			return;
		}
		instance = this;
	}
	
	//Simple GUI Implementation to fire interaction with VWS 
	void OnGUI()
	{
		if(GUI.Button (buttonRect, "Upload New Target"))
		{
			if(target)
				AddTarget(target);
			else
				Debug.Log ("Assign an RGB24 image to 'target' in the inspector");
		}
		
		Rect b2 = buttonRect;
		
		b2.y += b2.height;
		if(GUI.Button (b2, "Get Summary"))
			GetSummary();
		
		b2.y += b2.height;
		if(GUI.Button (b2, "Get List"))
			GetTargetList();
		
		b2.y += b2.height;
		if(GUI.Button (b2, "Get Target Summary"))
			GetTargetSummary(demoTargetID);
	}
	
	
	//Call for adding a target to the cloud
	public void AddTarget(Texture2D targetTex)
	{
		//Create a Target Data Object
		//Conversion of the imageTarget to Base64 String is handled in the TargetData class.
		TargetData td = new TargetData(target, 500, "new_target");
		//Create the HTTP request - Serialize the TargetData and convert to json bytes with CreateRequestData()
		HTTP.Request request = new HTTP.Request("POST", "https://" + host + "/targets", CreateRequestData(td));
		//Start the Http Request
		//Headers are Assigned in the Request Coroutine
		//A callback is also passed to the Request Call to be called with the HTTP Response
		StartCoroutine(Request(request, AddTargetResponse));
	}
	
	//Pass in a class object.
	//Out comes a Byte[] of the json serialisation of the class
	private byte[] CreateRequestData(object toSerialize)
	{	
		//Serialize the object referenced
		string json = HTTP.JsonSerializer.Encode(toSerialize);
#if UNITY_EDITOR
		Debug.Log ("json:" + json);
#endif
		//Encode to byte[]
		return Encoding.UTF8.GetBytes(json);
	}
	
	//Callback for the AddTarget call
	public void AddTargetResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}
	
	/*public void UpdateTarget(Texture2D targetTex, string targetId)
	{
		
	}
	
	public void UpdateTargetResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}
	
	public void GetTarget(string targetID)
	{
		
	}
	
	public void GetTargetResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}*/
	
	public void GetTargetList()
	{
		HTTP.Request request = new HTTP.Request("GET", "http://" + host + "/targets");
		StartCoroutine(Request(request, GetTargetListResponse));
	}
	
	public void GetTargetListResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}
	
	/*public void DeleteTarget(string targetID)
	{

	}
	
	public void DeleteTargetResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}*/
	
	public void GetSummary()
	{
		HTTP.Request request = new HTTP.Request("GET", "http://" + host + "/summary");
		StartCoroutine(Request(request, GetSummaryResponse));
	}
	
	public void GetSummaryResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}
	
	public void GetTargetSummary(string targetID)
	{
		HTTP.Request request = new HTTP.Request("GET", "http://" + host + "/targets/" + targetID);
		StartCoroutine(Request(request, GetTargetSummaryResponse));
	}
	
	public void GetTargetSummaryResponse(HTTP.Response response)
	{
#if UNITY_EDITOR
		Debug.Log (response.Text);
		Debug.Log (response.message);
#endif
	}
	
	//Make a request using an Http Request
	//The callback will be called once the request is fullfilled successfully
	private IEnumerator Request(HTTP.Request request, CloudRequestCallback callback)
	{
		//Set the headers...
		SetHeaders(ref request);
		//Execute the request
		request.Send();
		//Wait until finished
		while (!request.isDone) 
			yield return null;
		
		//Was the request successful?
		if(request.exception != null)
		{
			yield break;
		}
		
		//Success ... maybe ... callback with the response
		callback(request.response);
	}

	//Set the headers for the HTTP request
	private void SetHeaders(ref HTTP.Request req)
	{
		string hash = md5Empty; // Deault to the hash for an empty string
		//Create a correctly formatted date and time string
		string dateTimeString = DateTime.UtcNow.ToString("R"); 
#if UNITY_EDITOR
		Debug.Log (dateTimeString);
#endif
		//Set the host header
		req.AddHeader("Host", host);
		req.AddHeader("Date", dateTimeString);
		
		if(req.method.Equals("POST"))
		{
	        hash = GetMd5Hash(req.bytes);
			req.AddHeader("Content-Type", "application/json");
		}
		else
			req.AddHeader("Content-Type", "");

		string stringToSign = req.method + "\n" + hash + "\n" + req.GetHeader("Content-Type") + "\n" + req.GetHeader("Date") + "\n" + req.uri;
#if UNITY_EDITOR
		Debug.Log ("String to sign: " + stringToSign);
#endif
		string authorisation = "VWS " + accessKey + ":" + BuildSignature(secretKey, stringToSign);
#if UNITY_EDITOR
		Debug.Log ("Authorization: " + authorisation);
#endif
		req.AddHeader("Authorization", authorisation);
		
	}
	
	//Build a signature given the private key and a string to sign.
	private string BuildSignature(string keyString, string stringToSign)
	{
		//Convert key and data to byte[]
		byte[] key = Encoding.UTF8.GetBytes(keyString);
		byte[] data = Encoding.UTF8.GetBytes(stringToSign);
		
		//Create the encryption thingee
		HMACSHA1 myhmacsha1 = new HMACSHA1(key);
		myhmacsha1.Initialize();
        MemoryStream stream = new MemoryStream(data);

		//Compute the sha1 hash
		byte[] hash = myhmacsha1.ComputeHash(stream);
		
		//Convert to Base64 string
		string signature = System.Convert.ToBase64String(hash);
#if UNITY_EDITOR
		Debug.Log ("SIG: " + signature);
#endif
		return signature;
	}
	
	
	//Get the MD5 hash string for a Byte[]
	static string GetMd5Hash(byte[] toHash)
    {
		byte[] data; 
		using (MD5 md5Hash = MD5.Create())
	    {
			data = md5Hash.ComputeHash(toHash);
		}
        // compute the hash. 
       
        // Create a new Stringbuilder to collect the bytes 
        // and create a string.
        StringBuilder sBuilder = new StringBuilder();

        // Loop through each byte of the hashed data  
        // and format each one as a hexadecimal string. 
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
		
        // Return the hexadecimal string. 
		string hash = sBuilder.ToString();
#if UNITY_EDITOR
		Debug.Log ("MD5Hash: " + hash);
#endif
        return hash;
    }
}

 

VWS Requests in C# from Unity - Authentication

March 7, 2019 - 12:20pm #28

Hello @nicolepodach,

Super cool add for our community! Thank you!

Note that I was able to access using this link: https://github.com/taylordigital13/VuforiaTools. Yours did not work for me for whatever reason.

Looking forward to sharing this with the Vuforia team. I'll let you know if there is any internal feedback.

Thanks again!

-Vuforia Engine Support

VWS Requests in C# from Unity - Authentication

March 7, 2019 - 7:55am #27

I have put together a tool for the Unity Editor that allows you to upload, modify, or delete your vuforia cloud image targets. Here is the Git repo. https://github.com/taylordigital13/VuforiaTools 

VWS Requests in C# from Unity - Authentication

January 22, 2018 - 11:23am #26

Hi, to all,

 

I've the same erro 403, any help??

VWS Requests in C# from Unity - Authentication

April 9, 2017 - 10:37am #25

Did you get the solution? I've used the same code but I'm getting an unauthorized access error 401. Any help, please, need the solution urgent. I'm using C# exactly the same code but keys are different. 

VWS Requests in C# from Unity - Authentication

December 22, 2016 - 5:15am #24

Hello every one 

I have create the CMS in .net C# , now i want to use Vuforia Web Service (VWS) in my CMS , i have gone through many links and implement some code and after debugging it says "The Remote Server returned an error (403) Forbidden";

Please suggest me. 

 

private static string access_key = "c523a5b2ad5920sdfsd4fb5c3bd1b6f8333b308495e0e";

        private static string secret_key = "81a3f51c552a6713234323b5374676d15a8de95edb105";

        private static string url = @"https://vws.vuforia.com";

        private static string targetName = "MyTarget";

        private static string imageLocation = "~/Image/myfile.jpg";

        private static byte[] requestBytesArray;

        public void VuforiaCall()

        {

            WebResponse response = null;

            try {

                string requestPath = "/targets";

                string serviceURI = url + requestPath;

                string httpAction = "POST";

                string contentType = "application/json";

                string date = string.Format("{0:r}", DateTime.Now.ToUniversalTime());  Type your code in the box. To create a new line within the box use SHIFT + ENTER. 

                //var imageFile =System.IO.File.Open(Server.MapPath(imageLocation), FileMode.Open);

                //byte[] image = Convert.FromBase64String(imageFile.ToString()).ToArray(); 

                byte[] image = System.IO.File.ReadAllBytes(Server.MapPath(imageLocation));

                string metadataStr = "metadata";

                byte[] metadata = System.Text.ASCIIEncoding.ASCII.GetBytes(metadataStr);

                PostNewTrackableRequest model = new PostNewTrackableRequest();

                model.name = targetName;

                model.width = "64.0";

                model.image = System.Convert.ToBase64String(image);

                model.active_flag = true;

                model.application_metadata = System.Convert.ToBase64String(metadata);

                string requestBody = new JavaScriptSerializer().Serialize(model);

          

                HttpWebRequest httpWReq = (HttpWebRequest)HttpWebRequest.Create(serviceURI);

                httpWReq.Method = httpAction;

                MethodInfo priMethod = httpWReq.Headers.GetType().GetMethod("AddWithoutValidate", BindingFlags.Instance | BindingFlags.NonPublic);

                priMethod.Invoke(httpWReq.Headers, new[] { "Date", date });

                httpWReq.ContentType = contentType;

                MD5 md5 = MD5.Create();

                var contentMD5bytes = md5.ComputeHash(System.Text.Encoding.ASCII.GetBytes(requestBody));

               

                System.Text.StringBuilder sb = new System.Text.StringBuilder();

                for (int i = 0; i < contentMD5bytes.Length; i++)

                {

                    sb.Append(contentMD5bytes[i].ToString("x2"));

                }



                string contentMD5 = sb.ToString();

                string stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}", httpAction, contentMD5, contentType, date, serviceURI);



                HMACSHA1 sha1 = new HMACSHA1(System.Text.Encoding.ASCII.GetBytes(secret_key));

                byte[] sha1Bytes = Encoding.ASCII.GetBytes(stringToSign);

                MemoryStream stream = new MemoryStream(sha1Bytes);

                byte[] sha1Hash = sha1.ComputeHash(stream);

                string signature = System.Convert.ToBase64String(sha1Hash);

                httpWReq.Headers.Add("Authorization", string.Format("VWS {0}:{1}", access_key, signature));

                MemoryStream streamWriter = new MemoryStream();

                streamWriter.Seek(0,SeekOrigin.Begin);

                streamWriter.CopyTo(httpWReq.GetRequestStream());

                //streamWriter = (MemoryStream)httpWReq.GetRequestStream();

               // Stream streamWriter = httpWReq.GetRequestStream();

                //var streamWriter = httpWReq.GetRequestStream();

                byte[] buffer = System.Text.Encoding.ASCII.GetBytes(requestBody);

                requestBytesArray = buffer;

                streamWriter.Write(buffer, 0, buffer.Length);

                streamWriter.Flush();

                streamWriter.Close();

                response = httpWReq.GetResponse();

                Stream receiveStream = response.GetResponseStream();

                StreamReader sr = new StreamReader(receiveStream, System.Text.Encoding.UTF8);

                string responseData = sr.ReadToEnd();

                response.Close();

                sr.Close();

               

          }

        catch(Exception ex)

            {

                string error = ex.Message;

            }

        }

VWS Requests in C# from Unity - Authentication

December 22, 2016 - 5:14am #23

Hello every one 

I have create the CMS in .net C# , now i want to use Vuforia Web Service (VWS) in my CMS , i have gone through many links and implement some code and after debugging it says "The Remote Server returned an error (403) Forbidden";

Please suggest me. 

VWS Requests in C# from Unity - Authentication

April 5, 2016 - 4:48am #22

I made a copy code from here, but it couldn't work.

Pls help me ,thx in advance.

using UnityEngine;
using System.Collections;
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

/// <summary>
/// Simple class to describe a target to submit to the Cloud.
/// </summary>
public class TargetData
{
    public TargetData(Texture2D tex, int width, string name)
    {
        SetImage(tex);
        this.width = width;
        this.name = name;
    }

    public string image = "";
    public int width = 500;
    public string name = "target_tom";
    public bool active_flag = true;

    public void SetImage(Texture2D tex)
    {
        image = System.Convert.ToBase64String(tex.EncodeToJPG());
    }
}

/// <summary>
/// Delegate template for callback functions passed to CloudConnector.Request
/// </summary>
public delegate void CloudRequestCallback(HTTP.Response response);

/// <summary>
/// Singleton Cloud Connector Class.
/// </summary>
public class CloudConnector : MonoBehaviour
{
    private static CloudConnector instance = null;
    public static CloudConnector Instance { get { return instance; } }

    public string accessKey = "e5bf8438baa8df16a9a4195eac7707d2a62f2bee"; // Assign Access Key in the inspector
    public string secretKey = "d07f0eb5530d0c2a7ccb5bdd42d1c135a6cbc195"; // Assign Secret Key in the inspector
    private const string md5Empty = "d41d8cd98f00b204e9800998ecf8427e";

    public string host = "vws.vuforia.com"; // Host

    public Rect buttonRect = new Rect(0, 0, 200, 50);

    public Texture2D target; //Assign an RGB24 texture here
    public string targetName = "testTarget";

    public string demoTargetID = "0b54b9cc35be446eb195fa728c40aa1e";

    void Start()
    {
        if (instance != null)
        {
            Destroy(this);
            return;
        }
        instance = this;
    }

    void OnGUI()
    {
        if (GUI.Button(buttonRect, "Upload New Target"))
        {
            if (target)
                AddTarget(target);
            else
                Debug.Log("Assign an RGB24 image to 'target' in the inspector");
        }

        Rect b2 = buttonRect;

        b2.y += b2.height;
        if (GUI.Button(b2, "Get Summary"))
            GetSummary();

        b2.y += b2.height;
        if (GUI.Button(b2, "Get List"))
            GetTargetList();

        b2.y += b2.height;
        if (GUI.Button(b2, "Get Target Summary"))
            GetTargetSummary(demoTargetID);
    }

   /// <summary>
    /// Call for adding a target to the cloud
   /// </summary>
    public void AddTarget(Texture2D targetTex)
    {
        //Create a Target Data Object
        //Conversion of the imageTarget to Base64 String is handled in the TargetData class.
        TargetData td = new TargetData(target, 500, "new_target");
        //Create the HTTP request - Serialize the TargetData and convert to json bytes with CreateRequestData()
        HTTP.Request request = new HTTP.Request("POST", "https://" + host + "/targets", CreateRequestData(td));
        //Start the Http Request
        //Headers are Assigned in the Request Coroutine
        //A callback is also passed to the Request Call to be called with the HTTP Response
        StartCoroutine(Request(request, AddTargetResponse));
    }

    /// <summary>
    ///  Pass in a class object.Out comes a Byte[] of the json serialisation of the class
    /// </summary>
    private byte[] CreateRequestData(object toSerialize)
    {
        //Serialize the object referenced
        string json = HTTP.JsonSerializer.Encode(toSerialize);
#if UNITY_EDITOR
        Debug.Log("json:" + json);
#endif
        //Encode to byte[]
        return Encoding.UTF8.GetBytes(json);
    }

    /// <summary>
    /// Callback for the AddTarget call
    /// </summary>
    public void AddTargetResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log(response.Text);
        Debug.Log(response.message);
#endif
    }

    /*public void UpdateTarget(Texture2D targetTex, string targetId)
    {
         
    }
     
    public void UpdateTargetResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log (response.Text);
        Debug.Log (response.message);
#endif
    }
     
    public void GetTarget(string targetID)
    {
         
    }
     
    public void GetTargetResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log (response.Text);
        Debug.Log (response.message);
#endif
    }*/

    public void GetTargetList()
    {
        HTTP.Request request = new HTTP.Request("GET", "http://" + host + "/targets");
        StartCoroutine(Request(request, GetTargetListResponse));
    }

    public void GetTargetListResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log(response.Text);
        Debug.Log(response.message);
#endif
    }

    /*public void DeleteTarget(string targetID)
    {
 
    }
     
    public void DeleteTargetResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log (response.Text);
        Debug.Log (response.message);
#endif
    }*/

    public void GetSummary()
    {
        HTTP.Request request = new HTTP.Request("GET", "https://" + host + "/summary");
        StartCoroutine(Request(request, GetSummaryResponse));
    }

    public void GetSummaryResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log(response.Text);
        Debug.Log(response.message);
#endif
    }

    public void GetTargetSummary(string targetID)
    {
        HTTP.Request request = new HTTP.Request("GET", "https://" + host + "/targets/" + targetID);
        StartCoroutine(Request(request, GetTargetSummaryResponse));
    }

    public void GetTargetSummaryResponse(HTTP.Response response)
    {
#if UNITY_EDITOR
        Debug.Log(response.Text);
        Debug.Log(response.message);
#endif
    }

    /// <summary>
    ///Make a request using an Http Request
    ///The callback will be called once the request is fullfilled successfully
    /// </summary>
    /// <returns></returns>
    private IEnumerator Request(HTTP.Request request, CloudRequestCallback callback)
    {
        //Set the headers...
        SetHeaders(ref request);
        //Execute the request
        request.Send();
        //Wait until finished
        while (!request.isDone)
            yield return null;

        //Was the request successful?
        if (request.exception != null)
        {
            yield break;
        }

        //Success ... maybe ... callback with the response
        callback(request.response);
    }
    
    /// <summary>
    /// Set the headers for the HTTP request
    /// </summary>
    private void SetHeaders(ref HTTP.Request req)
    {
        string hash = md5Empty; // Deault to the hash for an empty string
        //Create a correctly formatted date and time string
        string dateTimeString = DateTime.UtcNow.ToString("R");
        //Set the host header
        req.headers.Add("Host", host);
        req.headers.Add("Date", dateTimeString);
        string stringToSign = req.method + "\n" + hash + "\n" + req.headers.Get("Content-Type") + "\n" + req.headers.Get("Date") + "\n" + req.uri;
        bool check = req.method.Equals("post", StringComparison.OrdinalIgnoreCase) || req.method.Equals("delete", StringComparison.OrdinalIgnoreCase);
        string authorisation = "VWS " + accessKey + ":" + (check?secretKey:BuildSignature(secretKey, stringToSign));
        //string authorisation = "VWS " + accessKey + ":" + secretKey;
        req.headers.Add("Authorization", authorisation);
        string requestPath = "/" + req.uri.Segments[req.uri.Segments.Length - 1];//Last segment is the request path
        Debug.Log("requestPath="+requestPath);
        //req.headers.Add("Request-Path", requestPath);
        
        if (req.method.Equals("POST"))
        {
            hash = GetMd5Hash(req.Bytes);
            req.headers.Add("Content-Type", "application/json");
        }
        else
            req.headers.Add("Content-Type", "");
    }

    /// <summary>
    /// Build a signature given the private key and a string to sign.
    /// </summary>
    /// <returns></returns>
    private string BuildSignature(string keyString, string stringToSign)
    {
        //Convert key and data to byte[]
        byte[] key = Encoding.UTF8.GetBytes(keyString);
        byte[] data = Encoding.UTF8.GetBytes(stringToSign);

        //Create the encryption thingee
        HMACSHA1 myhmacsha1 = new HMACSHA1(key);
        myhmacsha1.Initialize();
        MemoryStream stream = new MemoryStream(data);

        //Compute the sha1 hash
        byte[] hash = myhmacsha1.ComputeHash(stream);

        //Convert to Base64 string
        string signature = System.Convert.ToBase64String(hash);

        return signature;
    }

    /// <summary>
    /// Get the MD5 hash string for a Byte[]
    /// </summary>
    /// <param name="toHash"></param>
    /// <returns></returns>
    static string GetMd5Hash(byte[] toHash)
    {
        byte[] data;
        using (MD5 md5Hash = MD5.Create())
        {
            data = md5Hash.ComputeHash(toHash);
        }
        // compute the hash. 

        // Create a new Stringbuilder to collect the bytes 
        // and create a string.
        StringBuilder sBuilder = new StringBuilder();

        // Loop through each byte of the hashed data  
        // and format each one as a hexadecimal string. 
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        // Return the hexadecimal string. 
        string hash = sBuilder.ToString();
#if UNITY_EDITOR
        Debug.Log("MD5Hash: " + hash);
#endif
        return hash;
    }
}

 

VWS Requests in C# from Unity - Authentication

October 15, 2015 - 3:04pm #21

Hi, I still use Vuforia! - I just don't access VWS from the app anymore, it makes more sense to have that server based (for what i use it for).

Cheers

Tom

VWS Requests in C# from Unity - Authentication

October 15, 2015 - 3:00pm #20

Thank you, Mulder.

 

I will keep working on it and update this thread with my conclusions once I test it.

 

PS. [Totally off-topic, so apologies in advance] I am curious, what AR engine are you working with now? (assuming you are still working with AR)

VWS Requests in C# from Unity - Authentication

October 15, 2015 - 2:34pm #19

Hi @alvaroem. I've not tried this on the latest Vuforia sorry. I moved away from using VWS in my application and I haven't used that code since I wrote it way back then so can't give you any guarantees:)

Cheers

Tom

VWS Requests in C# from Unity - Authentication

October 15, 2015 - 5:16am #18

Hi, @mulder_ltd.

I just found this amazing post and I am willing to test your code, but before purchasing the UniWeb asset, I just wanted to ask if you know wether your code is working with the latest versions of Vuforia (5.0.5) and Unity (5.2). Could you please give me a hand?

Great job, BTW!

Regards!

 

VWS Requests in C# from Unity - Authentication

February 19, 2013 - 8:29am #17

Hi, have you checked our VWS Java samples ?

I would invite you to use them to access your Cloud Database; you can find them here:

https://developer.vuforia.com/resources/dev-guide/managing-targets-cloud-database-using-developer-api

 

VWS Requests in C# from Unity - Authentication

February 18, 2013 - 11:01pm #16

 

Hi,
I am from India, I am not getting proper output when I am accessing my own cloud database.
Please help
 
 
 
 
 
 
package com.qualcomm.vuforia.VisualSearch.utils;
 
import android.annotation.SuppressLint;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.SignatureException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
 
@SuppressLint("DefaultLocale")
public class SignatureBuilder {
 
public String tmsSignature(HttpUriRequest request, String secretKey) {
String method = request.getMethod();
String contentType = "";
String hexDigest = "d41d8cd98f00b204e9800998ecf8427e"; // Hex digest of an empty string
 
if (method.equalsIgnoreCase("GET") || method.equalsIgnoreCase("DELETE")) {
// Do nothing because the strings are already set correctly
} else if (method.equalsIgnoreCase("POST") || method.equalsIgnoreCase("PUT")) {
contentType = "application/json";
// If this is a POST or PUT the request should have a request body
hexDigest = contentMD5((HttpEntityEnclosingRequestBase) request);
} else {
System.out.println("ERROR: Invalid content type passed to Sig Builder");
}
 
// Date in the header and date used to calculate the hash must be the same
String dateValue = request.getFirstHeader("Date").getValue();
String requestPath = request.getURI().getPath();
String toDigest = new String(method + "\n" + hexDigest + "\n" + contentType + "\n" + dateValue + "\n" + requestPath);
String shaHashed = "";
try {
System.out.println(toDigest);
shaHashed = calculateRFC2104HMAC(secretKey, toDigest);
} catch (SignatureException e) {
e.printStackTrace();
}
return new String(shaHashed);
}
 
private String contentMD5(HttpEntityEnclosingRequestBase httpMethod) {
ByteArrayOutputStream requestOutputStream = new ByteArrayOutputStream();
try {
httpMethod.getEntity().writeTo(requestOutputStream);
} catch (IOException e) {
System.out.println("ERROR: IOException caught when writing Content MD5 hash");
e.printStackTrace();
}
return DigestUtils.md5Hex(requestOutputStream.toByteArray()).toLowerCase();
}
 
public static String calculateRFC2104HMAC(String key, String data) throws java.security.SignatureException {
String result = "";
try {
// get an hmac_sha1 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
 
// get an hmac_sha1 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
 
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(data.getBytes());
 
// base64-encode the hmac
result = new String(Base64.encodeBase64(rawHmac, false));
 
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
 

 

VWS Requests in C# from Unity - Authentication

February 18, 2013 - 10:41pm #15

The only way to access the cloud database other than the vws is to use the web interface or the target finder on the client.

Authentication error

February 18, 2013 - 10:39pm #14

Hi,

One thing I want to ask from you, when we don't use vws, I just want to access my own cloud database, would you tell me how can I do it

 

VWS Requests in C# from Unity - Authentication

February 18, 2013 - 10:28pm #13

It's not a copy pate code, but this should give an idea on how to do it.

 

During the initialization of vuforia client i initialize some header values

 

Request = (HttpWebRequest)WebRequest.Create(new Uri( new Uri("https://vws.vuforia.com"), message.Path));

Request.Method = message.Method;

Request.ContentType = message.ContentType;

Request.Date = DateTime.Now;

 

 

When i build the signature (note the date):

 

 

            var builder = new StringBuilder();

            builder.AppendFormat("{0}\n", Message.Method);

            builder.AppendFormat("{0}\n", (Message.Content ?? string.Empty).ToMD5Encoded());

            builder.AppendFormat("{0}\n", Message.ContentType);

            builder.AppendFormat("{0}\n", Request.Date.ToUniversalTime().ToString("R"));

            builder.Append(Message.Path);

 

            var signature = SignString(builder.ToString());

            var authString = "VWS " + AccessKey + ":" + signature;

 

VWS Requests in C# from Unity - Authentication

February 18, 2013 - 10:10pm #12

Hi,

Would you explain it in briefly, which type of changes I have to do in in

 

VWS Requests in C# from Unity - Authentication

February 18, 2013 - 10:06pm #11

It means that you have a bad signature. Check that you use exactly the same date both in the header and in the signature, that is usually the most common error.

VWS Requests in android from Unity - Authentication

February 18, 2013 - 4:10am #10

 

hi,
My program is showing this type of error and I am not getting proper answer,
{"result_code":"AuthenticationFailure","transaction_id":"3843253bade440058aec6c51ca225c9c"}

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:41am #9

One last thing - the GET requests are not working yet in the code below. I'll update once I have sorted those.

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:40am #8

Just a note - It would be helpful in the documentation if the Request-Path was documented - Looks like there was an omission there.

on the page: 

Setting Up the API

An explanation of Request-Path is missing.

 

Thanks 

Tom

 

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:36am #7

Sounds great! Glad that you figured out the issue. (And thanks for sharing the udpated code).

 

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:35am #6

 

Ok so the issue with the target uploading part of my script was as simple as this:

 

Where the StringToSign was built I was using:

Request-Path = vws.vuforia.com/targets

instead of:

Request-Path = /targets

After making this change I could upload targets successfully.

Revised SetHeaders Function here:

	//Set the headers for the HTTP request
	private void SetHeaders(ref HTTP.Request req)
	{
		string hash = md5Empty; // Deault to the hash for an empty string
		string requestPath = "/" + req.uri.Segments[req.uri.Segments.Length-1];//Last segment is the request path
		//Create a correctly formatted date and time string
		string dateTimeString = DateTime.UtcNow.ToString("R"); 
#if UNITY_EDITOR
		Debug.Log (dateTimeString);
#endif
		//Set the host header
		req.AddHeader("Host", host);
		req.AddHeader("Date", dateTimeString);
		
		if(req.method.Equals("POST"))
		{
	        hash = GetMd5Hash(req.bytes);
			req.AddHeader("Content-Type", "application/json");
		}
		else
			req.AddHeader("Content-Type", "");
		
		req.AddHeader("Request-Path", requestPath);

		string stringToSign = req.method + "\n" + hash + "\n" + req.GetHeader("Content-Type") + "\n" + req.GetHeader("Date") + "\n" + requestPath;
#if UNITY_EDITOR
		Debug.Log ("String to sign: " + stringToSign);
#endif
		string authorisation = "VWS " + accessKey + ":" + BuildSignature(secretKey, stringToSign);
#if UNITY_EDITOR
		Debug.Log ("Authorization: " + authorisation);
#endif
		req.AddHeader("Authorization", authorisation);
		
	}
 

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:33am #5

Woops posted comment as the wrong user:)

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:24am #4

You're welcome.

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 1:03am #3

Thanks AllesandoB - Much appreciated!

 

Regards

Tom

VWS Requests in C# from Unity - Authentication

February 5, 2013 - 12:50am #2

Hi,

currently we only support the Java sample implementation  for VWS API, but you could be interested in having a look at this thread, where C# sample code (working) is shared / discussed among other devs:

https://developer.vuforia.com/forum/cloud-reco-beta/problem-connecting-web-service

 

Log in or register to post comments