Created
November 5, 2015 01:49
-
-
Save acamino/90d6638a1e03db2cd4e9 to your computer and use it in GitHub Desktop.
OneTouch Support
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Specialized; | |
using System.IO; | |
using System.Net; | |
using System.Text; | |
using Authy.Net; | |
using Newtonsoft.Json; | |
namespace Authy.Net | |
{ | |
public class OneTouchClient | |
{ | |
private readonly string _apiKey; | |
private readonly string _userId; | |
private readonly bool _useSandbox; | |
/// <summary> | |
/// Creates a new instance of the OneTouch client | |
/// </summary> | |
/// <param name="apiKey">The api key used to access the rest api</param> | |
/// <param name="userId">The user id used to send approval request</param> | |
public OneTouchClient(string apiKey, string userId, bool useSandbox = false) | |
{ | |
_apiKey = apiKey; | |
_userId = userId; | |
_useSandbox = useSandbox | |
} | |
/// <summary> | |
/// Send Approval Request to Authy | |
/// </summary> | |
/// <param name="message">Message to display in the device</param> | |
/// <param name="details">Details that will be shown to the user</param> | |
public SendApprovalRequestResult SendApprovalRequest(string message, NameValueCollection details) | |
{ | |
var url = string.Format("{0}/onetouch/json/users/{1}/approval_requests?api_key={2}&message={3}", | |
BaseUrl, _userId, _apiKey, message); | |
return Execute(client => | |
{ | |
var response = client.UploadValues(url, request); | |
var textResponse = Encoding.ASCII.GetString(response); | |
var apiResponse = JsonConvert.DeserializeObject<SendApprovalRequestResult>(textResponse); | |
apiResponse.RawResponse = textResponse; | |
apiResponse.Status = AuthyStatus.Success; | |
return apiResponse; | |
}); | |
} | |
private TResult Execute<TResult>(Func<WebClient, TResult> execute) | |
where TResult : AuthyResult, new() | |
{ | |
var client = new WebClient(); | |
var libraryVersion = AuthyHelpers.GetVersion(); | |
var runtimeVersion = AuthyHelpers.GetSystemInfo(); | |
var userAgent = string.Format("AuthyNet/{0} ({1})", libraryVersion, runtimeVersion); | |
// Set a custom user agent | |
client.Headers.Add("user-agent", userAgent); | |
try | |
{ | |
return execute(client); | |
} | |
catch (WebException webex) | |
{ | |
var response = webex.Response.GetResponseStream(); | |
string body; | |
using (var reader = new StreamReader(response)) | |
{ | |
body = reader.ReadToEnd(); | |
} | |
TResult result = JsonConvert.DeserializeObject<TResult>(body); | |
switch (((HttpWebResponse)webex.Response).StatusCode) | |
{ | |
case HttpStatusCode.ServiceUnavailable: | |
result.Status = AuthyStatus.ServiceUnavailable; | |
break; | |
case HttpStatusCode.Unauthorized: | |
result.Status = AuthyStatus.Unauthorized; | |
break; | |
default: | |
case HttpStatusCode.BadRequest: | |
result.Status = AuthyStatus.BadRequest; | |
break; | |
} | |
return result; | |
} | |
finally | |
{ | |
client.Dispose(); | |
} | |
} | |
private static string BaseUrl | |
{ | |
get { return _useSandbox ? "http://sandbox-api.authy.com" : "https://api.authy.com"; } | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Linq; | |
using System.Security.Cryptography; | |
using System.Text; | |
using System.Web; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
using WebGrease.Css.Extensions; | |
namespace Authy.Net | |
{ | |
public class OneTouchRequestValidator | |
{ | |
private readonly string _apiKey; | |
private readonly HttpRequestBase _request; | |
public OneTouchRequestValidator(string apiKey, HttpRequestBase request) | |
{ | |
_apiKey = apiKey; | |
_request = request; | |
} | |
public bool Validate() | |
{ | |
var nonce = _request.Headers["X-Authy-Signature-Nonce"]; | |
var url = string.Format("{0}://{1}{2}", | |
_request.Url.Scheme, _request.Headers["X-Original-Host"], _request.Url.AbsolutePath); | |
var serialized = Serialize(Sort(Parameters)).Trim('&'); | |
var data = string.Format("{0}|{1}|{2}|{3}", | |
nonce, _request.HttpMethod, url, serialized); | |
var digest = ComputeDigest(data, _apiKey); | |
var authySignature = _request.Headers["X-Authy-Signature"]; | |
return digest == authySignature; | |
} | |
private JObject Parameters | |
{ | |
get | |
{ | |
_request.InputStream.Position = 0; | |
return (JObject) JsonConvert.DeserializeObject(new StreamReader(_request.InputStream).ReadToEnd()); | |
} | |
} | |
private static JObject Sort(JObject content) | |
{ | |
var result = new JObject(); | |
var properties = content.Properties().OrderBy(property => property.Name); | |
properties.ForEach(property => | |
{ | |
var propertyValue = property.Value as JObject; | |
if (propertyValue != null) | |
{ | |
result.Add(property.Name, Sort(propertyValue)); | |
} | |
else | |
{ | |
result.Add(property); | |
} | |
}); | |
return result; | |
} | |
private static string Serialize(JObject content) | |
{ | |
var result = new StringBuilder(); | |
var properties = content.Properties(); | |
properties.ForEach(property => | |
{ | |
var propertyValue = property.Value as JObject; | |
if (propertyValue != null) | |
{ | |
result.Append(Serialize(propertyValue)); | |
} | |
else | |
{ | |
result.Append(string.Format("{0}={1}&", | |
FormatPath(property.Path), Encode(property.Value.ToString()))); | |
} | |
}); | |
return result.ToString(); | |
} | |
private static string FormatPath(string property) | |
{ | |
var pathComponents = property.Split('.'); | |
var head = pathComponents[0]; | |
if (pathComponents.Length == 1) | |
{ | |
return head; | |
} | |
var tail = pathComponents | |
.Skip(1) | |
.Select(component => string.Format("%5B{0}%5D", component)); | |
return string.Format("{0}{1}", head, string.Join("", tail)); | |
} | |
private static string ComputeDigest(string message, string secret) | |
{ | |
var encoding = new UTF8Encoding(); | |
using (var hmacsha256 = new HMACSHA256(encoding.GetBytes(secret))) | |
{ | |
var hashedMessage = hmacsha256.ComputeHash(encoding.GetBytes(message)); | |
return Convert.ToBase64String(hashedMessage); | |
} | |
} | |
private static string Encode(string content) | |
{ | |
return content | |
.Replace("@", "%40") | |
.Replace("=", "%3D") | |
.Replace("/", "%2F") | |
.Replace("+", "%2B") | |
.Replace(" ", "+") | |
.Replace("False", "false"); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using Authy.Net; | |
using Newtonsoft.Json; | |
namespace Authy.Net | |
{ | |
public class SendApprovalRequestResult : AuthyResult | |
{ | |
[JsonProperty("approval_request")] | |
public IDictionary<string, string> ApprovalRequest { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment