I'm trying to connect to Apple's News API. When generating the signature the results all appear the same from each of the different examples. However, I keep getting this error:
{"errors":[{"code":"WRONG_SIGNATURE"}]}
Here is my c# code to generate the auth header.
public class Security
{
public static string AuthHeader(string method, string url, object content=null)
{
var apiKeyId = "<YOUR KEY HERE...>"; //we get this value from our settings file.
var apiKeySecret = "<YOUR SECRET HERE...>"; //we get this value from our settings file.
if ( string.IsNullOrEmpty(apiKeyId) || string.IsNullOrEmpty(apiKeySecret)) return string.Empty;
var encoding = new ASCIIEncoding();
var dt = DateTime.Now.ToString(Constants.DateFormat);
var canonicalRequest = string.Format("{0}{1}{2}", method, url, dt);
var key = Convert.FromBase64String(apiKeySecret);
var hmac = new HMACSHA256(key);
var hashed = hmac.ComputeHash(encoding.GetBytes(canonicalRequest));
var signature = Convert.ToBase64String(hashed);
var authorizaton = string.Format(@"HHMAC; key={0}; signature={1}; date={2}", apiKeyId, signature, dt);
return authorizaton;
}
}
Short version of Constants class
public static class Constants
{
public static readonly string ChannelId = "<YOUR CHANNEL ID HERE...>"; //again from our settings file
public static readonly string BaseUrl = "https://news-api.apple.com";
public static readonly string DateFormat = "yyyy-MM-ddTHH:mm:ssK";
}
Short version of Actions class (SendCommand is the method that performs the request)
public class Actions
{
public static string SendCommand(string action, string method)
{
var url = $"{Constants.BaseUrl}{action}";
var authheader = Security.AuthHeader(method, url, null);
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
request.Timeout = 1000;
request.Headers.Add("Authorization", authheader);
request.Accept = "application/json";
request.ContentType = "application/json";
var output = string.Empty;
try
{
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
output = reader.ReadToEnd();
}
}
catch (WebException e)
{
using (var reader = new StreamReader(e.Response.GetResponseStream()))
{
output = reader.ReadToEnd();
}
}
return output;
}
public static string ReadChannel()
{
var action = $"/channels/{Constants.ChannelId}";
const string method = "GET";
return SendCommand(action, method);
}
}
I'm using the ReadChannel method for testing.
I've also tried examples in php and ruby with no luck.
Any ideas how to do this correctly?