Azure IOT Hub Rest API Unauthorized

7.7k views Asked by At

I am trying to use Azure Iot hub REST API to create device by following links

Create a new device identity

Control access to IoT Hub

And my http data is like

{
    "status":"connected",
    "authentication":{ "symmetricKey":{
                "primaryKey":"key in shared access policies",
                "secondaryKey":"key in shared access policies"}
             },
    "statusReason":"reason",
    "deviceId":"test123"
}

My header is like

 ["Content-Type": "application/json", "Authorization": "SharedAccessSignature sig=(key in shared access policies public key)=&se=1481687791&skn=iothubowner&sr=(my iot hub name).azure-devices.net%2fdevices%2ftest123"]

But i get error 401

{"Message":"ErrorCode:IotHubUnauthorizedAccess;Unauthorized","ExceptionMessage":"Tracking ID:(tracking id )-TimeStamp:12/14/2016 03:15:17"}

Anyone know how to fixed it , or to track the exceptionMessage ?

4

There are 4 answers

0
Fabio Maulo On

The problem of 401 is, probably, in the way you are calculating the SAS. The full process to calculate a SAS for the IoT Hub (in C#) is:

private static readonly DateTime epochTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

public static string SharedAccessSignature(string hostUrl, string policyName, string policyAccessKey, TimeSpan timeToLive)
{
  if (string.IsNullOrWhiteSpace(hostUrl))
  {
    throw new ArgumentNullException(nameof(hostUrl));
  }

  var expires = Convert.ToInt64(DateTime.UtcNow.Add(timeToLive).Subtract(epochTime).TotalSeconds).ToString(CultureInfo.InvariantCulture);
  var resourceUri = WebUtility.UrlEncode(hostUrl.ToLowerInvariant());
  var toSign = string.Concat(resourceUri, "\n", expires);
  var signed = Sign(toSign, policyAccessKey);

  var sb = new StringBuilder();
  sb.Append("sr=").Append(resourceUri)
    .Append("&sig=").Append(WebUtility.UrlEncode(signed))
    .Append("&se=").Append(expires);
  if (!string.IsNullOrEmpty(policyName))
  {
    sb.Append("&skn=").Append(WebUtility.UrlEncode(policyName));
  }
  return sb.ToString();
}

private static string Sign(string requestString, string key)
{
  using (var hmacshA256 = new HMACSHA256(Convert.FromBase64String(key)))
  {
    var hash = hmacshA256.ComputeHash(Encoding.UTF8.GetBytes(requestString));
    return Convert.ToBase64String(hash);
  }
}

If you want to create the device in the IoTHub you have to have a policy with full permissions that mean: Registry read and write, Service connect and Device connect. If you need a full functional example, in C#, about how use the IoT Hub REST API to create a device, check if a device exists and send messages to the IoT Hub I have wrote this post about it (the post is in spanish but I can imagine that what you need is just the code).

0
Naveen kumar Srimurthi On

//Following code is to generate the SAS token programatically.

string sasToken = new SharedAccessSignatureBuilder()
{  KeyName = name,
 Key = key,
 Target = target,
 TimeToLive = TimeSpan.FromDays(days)
}.ToSignature();

//use this sas token as authorization header before calling the iot restapi

0
Rita Han On

There are two edits you need to do:

  1. In your http data, only deviceId is required, other are optional, you can do it like this:

{ deviceId: "test123" }

Note that there are no double quotes around deviceId.

  1. Like @shachar said, you need remove "%2fdevices%2ftest123" in SAS token of the header. About generating SAS token you can utilize Device Explorer.

This is my test result:

enter image description here

1
shachar On

it looks like your SAS is wrong. It shouldn't include the devices part in the end. If you open the Iot Hub Device Explorer you can Generate SAS token to access the Iot Hub API. You should create the SAS for the IoT hub level and for a device level (which include the devive id in the SAS like you have). So your SAS should look like this - SharedAccessSignature sr={iot hub name}.azure-devices.net&sig={sig}&se={se}&skn=iothubowner