Skip to content

Commit

Permalink
WebSocketConnection can now check credentials via the Api
Browse files Browse the repository at this point in the history
  • Loading branch information
quietjoy committed Nov 7, 2016
1 parent 548decc commit b0a38eb
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 19 deletions.
83 changes: 80 additions & 3 deletions Api/WebSocketConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using QuantConnect.API;
using QuantConnect.Configuration;
using QuantConnect.Data;
using QuantConnect.Logging;
using QuantConnect.Orders;
using RestSharp;
using RestSharp.Authenticators;
using WebSocketSharp;
using WebSocketSharp.Net;

Expand All @@ -32,6 +38,7 @@ public class WebSocketConnection

private readonly string _liveDataUrl = Config.Get("live-data-url", "https://www.quantconnect.com/api/v2/live/data");
private readonly int _liveDataPort = Config.GetInt("live-data-port", 443);
private static string _apiEndpoint = "https://www.quantconnect.com/api/v2/";

/// <summary>
/// Initialize a new WebSocketConnection instance
Expand Down Expand Up @@ -198,10 +205,10 @@ private bool TryOpenSocketConnection()
{
if (webSocketSetupComplete) continue;

var timeStamp = DateTime.Now.ToString(DateFormat.TwelveCharacter);
var hash = Convert.ToBase64String((_token + ":" + timeStamp).ToSHA256().GetBytes());
var timeStamp = (int)Time.TimeStamp();
var hash = CreateSecureHash(timeStamp);

ws.SetCookie(new Cookie("timeStamp", timeStamp));
ws.SetCookie(new Cookie("TimeStamp", timeStamp.ToString()));
ws.SetCookie(new Cookie("token", hash));
ws.SetCookie(new Cookie("uid", _userId.ToString()));

Expand Down Expand Up @@ -345,5 +352,75 @@ private static IEnumerable<BaseData> DeserializeMessage(string serialized)
{
TypeNameHandling = TypeNameHandling.All
};

/// <summary>
/// Generate a secure hash for the authorization headers.
/// </summary>
/// <returns>Time based hash of user token and timestamp.</returns>
private string CreateSecureHash(int timestamp)
{
// Create a new hash using current UTC timestamp.
// Hash must be generated fresh each time.
var data = string.Format("{0}:{1}", _token, timestamp);
return SHA256(data);
}

/// <summary>
/// Encrypt the token:time data to make our API hash.
/// </summary>
/// <param name="data">Data to be hashed by SHA256</param>
/// <returns>Hashed string.</returns>
private string SHA256(string data)
{
var crypt = new SHA256Managed();
var hash = new StringBuilder();
var crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(data), 0, Encoding.UTF8.GetByteCount(data));
foreach (var theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString();
}


/// <summary>
/// Check a hash for a specified user and timeStamp
/// </summary>
/// <param name="tStamp">TimeStamp as int</param>
/// <param name="hash">Precomputed hash</param>
/// <param name="uid">User Id</param>
/// <returns></returns>
public static bool CheckCredentials(string uid, int tStamp, string hash)
{
var request = new RestRequest("authenticate", Method.GET);
var client = new RestClient(_apiEndpoint);
try
{
request.AddHeader("Timestamp", tStamp.ToString());
client.Authenticator = new HttpBasicAuthenticator(uid, hash);

// Execute the authenticated REST API Call
var restsharpResponse = client.Execute(request);

// Use custom converter for deserializing live results data
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = { new LiveAlgorithmResultsJsonConverter(), new OrderJsonConverter() }
};

//Verify success
var result = JsonConvert.DeserializeObject<RestResponse>(restsharpResponse.Content);
if (!result.Success)
{
return false;
}
}
catch (Exception err)
{
Log.Error(err, "Api.CheckCredentials(): Failed to make REST request.");
return false;
}
return true;
}
}
}
16 changes: 0 additions & 16 deletions Common/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,22 +106,6 @@ public static string ToMD5(this string str)
return builder.ToString();
}

/// <summary>
/// Extension method to convert a string to a SHA1 hash.
/// </summary>
/// <param name="str">String we want to SHA1 encode.</param>
/// <returns>SHA1 hash of a string</returns>
public static string ToSHA256(this string str)
{
var builder = new StringBuilder();
using (var sha = SHA256.Create())
{
var data = sha.ComputeHash(Encoding.UTF8.GetBytes(str));
foreach (var t in data) builder.Append(t.ToString("x2"));
}
return builder.ToString();
}

/// <summary>
/// Extension method to automatically set the update value to same as "add" value for TryAddUpdate.
/// This makes the API similar for traditional and concurrent dictionaries.
Expand Down

0 comments on commit b0a38eb

Please sign in to comment.