1

I have been trying to create an Iot Hub device from an Android phone for a while, and despite following every instruction or tutorial I can find, i keep getting:

{
"Message": "ErrorCode:IotHubUnauthorizedAccess;Unauthorized",
"ExceptionMessage": "Tracking ID:cc3e0c722b6040f89239c14c8bace4b9-G:0-TimeStamp:12/09/2021 23:29:46"

}

I have tried creating the SharedAccessSignature in Java in the Android code a couple of different ways:

    private static String GetSASToken(String resourceUri, String keyName, String key)
{
    long epoch = System.currentTimeMillis()/1000L;
    int week = 60*60*24*7;
    String expiry = Long.toString(epoch + week);
    Log.d(TAG, "GetSASToken: expiry: " + expiry);

    String sasToken = null;
    try {
        String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expiry;
        String signature = getHMAC256(key, stringToSign);
        sasToken = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8") +"&sig=" +
                URLEncoder.encode(signature, "UTF-8") + "&se=" + expiry + "&skn=" + keyName;
    } catch (UnsupportedEncodingException e) {

        e.printStackTrace();
    }

    return sasToken;
}

and

public static String generateSasToken(String resourceUri, String key) throws Exception {
    // Token will expire in one hour
    long expiry = Instant.now().getEpochSecond() + 3600;

    String stringToSign = URLEncoder.encode(resourceUri, "UTF-8") + "\n" + expiry;

    byte[] decodedKey = Base64.getDecoder().decode(key);

    Mac sha256HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secretKey = new SecretKeySpec(decodedKey, "HmacSHA256");
    sha256HMAC.init(secretKey);
    Base64.Encoder encoder = Base64.getEncoder();

    String signature = new String(encoder.encode(
            sha256HMAC.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8))), StandardCharsets.UTF_8);

    String token = "SharedAccessSignature sr=" + URLEncoder.encode(resourceUri, "UTF-8")
            + "&sig=" + URLEncoder.encode(signature, StandardCharsets.UTF_8.name()) + "&se=" + expiry;

    return token;
}

and then calling the usual way:

            try{
            URL finalURL = new URL(stringUrl);

            urlConnection = (HttpsURLConnection)finalURL.openConnection();
            urlConnection.setReadTimeout(10000);
            urlConnection.setConnectTimeout(0);
            urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            urlConnection.setRequestProperty("Accept","application/json");
            urlConnection.setRequestProperty("Authorization",token2);
            urlConnection.setRequestMethod("PUT");
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(true);
            int responseCode = urlConnection.getResponseCode();
        }catch (MalformedURLException e) {
            e.printStackTrace();
            Log.d(TAG, "doInBackground: error 1 " + e.toString());
        }catch(UnknownHostException e){
            Log.d(TAG, "doInBackground: e: " + e);
        }
        catch(Exception e){
            Log.d(TAG, "doInBackground: error 2 " + e.toString());
        }
        finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
        return null;
    }

My Sas token is in the form:

SharedAccessSignature sr=XXXXXXXXXXXXXXXX.azure-devices.net&sig=XXXXXXXXXXXXXXXXXXXXXXXB6%2BM6L0JR0UpgFxmvuX7g%3D&se=1639698883&skn=iothubowner

and the URL I am using in Postman is:

https://XXXXXXXXXX-westus2.azure-devices.net/devices/testDevice1?api-version=2020-03-13

with the Authorization header set to the above SAS

I have also used Python to create the SAS in case there was some issue with the encoding. But everything I do is hitting the same Unauthorized access message, and I'm starting to pull my hair out.

Geordie Wicks
  • 1,065
  • 1
  • 11
  • 27
  • One thing to try to see if the error is in your SAS code or the API call: generate a SAS token using the az cli. You can use `az iot hub generate-sas-token --hub-name {your-hub-name}` to generate a token. – Matthijs van der Veer Dec 10 '21 at 16:01
  • Thanks, still getting the same error, regardless of if I call it via Postman or via Java code. – Geordie Wicks Dec 15 '21 at 10:03

1 Answers1

0

The following screen snippet shows an example of the sending a telemetry data to the Iot Hub using the REST POST call:

enter image description here

for test purpose, use the Azure IoT Explorer included also generating a SaS token, see the following screen snippet:

enter image description here

UPDATE:

The following screen snippet shows an example of the creating an Azure IoT Hub device using the REST PUT request:

enter image description here

The sasToken for the above request has been generated by C# code described in the document based on the IoT Hub Shared access policy iothubowner:

string sasToken = generateSasToken("rk2019-iot.azure-devices.net", "****", "iothubowner");
Roman Kiss
  • 7,925
  • 1
  • 8
  • 21
  • Thanks, tried this as well, the error changed a bit at least: ```"Message": "ErrorCode:InvalidProtocolVersion;BadRequest",``` – Geordie Wicks Dec 15 '21 at 10:04
  • The screenshots show the creation of a SAS for a device. The question is about creating a device with the Service API. – Matthijs van der Veer Dec 15 '21 at 13:58
  • @MatthijsvanderVeer you are right, in this case should be used a tool like is a Device Explorer for test purposes and generating a sasToken https://github.com/fsautomata/azure-iot-sdks/blob/master/tools/DeviceExplorer/doc/how_to_use_device_explorer.md – Roman Kiss Dec 15 '21 at 18:30