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.