API Security¶
Overview¶
AgriSmart will provide you with a Key ID and a Secret. You’ll use the secret to construct a SHA256 HMAC digest of the parameters to the API for each call.
SSL Required¶
Calls to the API must be made using SSL. Any non-SSL calls will be rejected.
Secret¶
The production secret we provide you must be kept secure. This secret is never transmitted across the wire and should be treated like a private key. Anyone who has access to your Key ID and Secret can make calls to our API on your behalf.
Sample C# Code¶
Here is a simplistic sample C# client that can call any of our APIs:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace JobAPITest
{
class Client
{
public const bool DEV = true;
public string KeyID { get; set; }
public string Secret { get; set; }
public string Path { get; set; }
public string Method { get; set; }
public string Body { get; set; }
public SortedDictionary<string, string> Parameters { get; private set; }
public Client()
{
Method = "GET";
Parameters = new SortedDictionary<string, string>();
}
public string MakeRequest()
{
DateTime d = DateTime.Now.ToUniversalTime();
string ds = d.ToString("yyyyMMddHHmmss'Z'");
Debug.WriteLine(KeyID);
Debug.WriteLine(ds);
byte[] secretBytes = Encoding.UTF8.GetBytes(Secret);
byte[] contentBytes = Encoding.UTF8.GetBytes(KeyID);
HMACSHA256 sha256 = new HMACSHA256(secretBytes);
byte[] keyBytes = sha256.ComputeHash(contentBytes);
contentBytes = Encoding.UTF8.GetBytes(ds);
sha256 = new HMACSHA256(keyBytes);
keyBytes = sha256.ComputeHash(contentBytes);
foreach (var item in Parameters)
{
contentBytes = Encoding.UTF8.GetBytes(item.Value);
sha256 = new HMACSHA256(keyBytes);
keyBytes = sha256.ComputeHash(contentBytes);
}
if ("GET" != Method)
{
contentBytes = Encoding.UTF8.GetBytes(Body);
sha256 = new HMACSHA256(keyBytes);
keyBytes = sha256.ComputeHash(contentBytes);
}
contentBytes = Encoding.UTF8.GetBytes(Path);
sha256 = new HMACSHA256(keyBytes);
keyBytes = sha256.ComputeHash(contentBytes);
StringBuilder sb = new StringBuilder();
foreach (byte b in keyBytes)
{
sb.AppendFormat("{0:x2}", b);
}
Debug.WriteLine(sb.ToString());
StringBuilder urlBuilder = new StringBuilder();
string baseUrl = "https://staging.agrismartis.com";
if (DEV) baseUrl = "http://localdev.agrismartis.com:3000";
urlBuilder.AppendFormat("{0}{1}?kid={2}&date={3}&key={4}",
baseUrl,
Path,
KeyID,
ds,
sb.ToString()
);
if("GET" == Method)
{
foreach(var item in Parameters)
{
urlBuilder.AppendFormat("&{0}={1}", item.Key, item.Value);
}
}
string url = urlBuilder.ToString();
Debug.WriteLine(url);
HttpWebRequest wr = WebRequest.CreateHttp(url);
wr.Method = Method;
if("GET" != Method)
{
wr.ContentType = "application/json";
Debug.WriteLine(Body);
byte[] formBytes = Encoding.UTF8.GetBytes(Body);
wr.ContentLength = formBytes.Length;
Stream requestStream = wr.GetRequestStream();
requestStream.Write(formBytes, 0, formBytes.Length);
requestStream.Close();
}
HttpWebResponse resp = null;
try
{
resp = (HttpWebResponse)wr.GetResponse();
}
catch (WebException ex)
{
resp = (HttpWebResponse)ex.Response;
}
StreamReader sr = new StreamReader(resp.GetResponseStream());
string body = sr.ReadToEnd();
Debug.WriteLine(url);
Debug.WriteLine(body);
return body.Replace("\n", "\r\n");
}
}
}
This client can be used to call the POST method of the Jobs API like so:
Client client = new Client();
client.KeyID = KeyID;
client.Secret = Secret;
client.Path = "/api/jobs";
client.Method = "POST";
client.Body = requestTextBox.Text.Trim();
resultsTextBox.Text = client.MakeRequest();