Device Validation
裝置自我驗證,由 IoT Device 進行自我驗證,驗證裝置是否有效、是否過期、是否有開通授權
POST https://{Server Name}/api/Devices/Validation/{guid}
Request method
Request methods/headers | Value |
---|---|
Method | POST |
Authorization | CCP-HMAC-KEY <access_token> |
Request parameters
Name | Required/Optional | Type | Description |
---|---|---|---|
guid | Required | GUIUD | 該裝置註冊時 CCP 系統產生的唯一 GUID |
Response
Response headers | Value |
---|---|
status | 200: Success 400: Bad request401: Invalid access token500: Failure due to server error |
Content-Type | application/json |
失敗原因:
- 裝置被強制停用
- 裝置沒有綁定授權資料
- 裝置的有效使用期限已過期
- 無此裝置資料 未註冊、被刪除
Response body
{
"deviceId": "WillyNB",
"hostName": "CCP-IoTHub-Dev.azure-devices.net",
"symmetricKey": {
"primaryKey": "myoJyBj6YKkZZk7WwZgzmXNi/+tVBzMEM3XLWhIBv4w=",
"secondaryKey": "3lq24daPO51sk382haQl1WhZZbDBDXC/K8Jwm7yrQbY="
},
"azureIoTHubConnectionString": "HostName=CCP-IoTHub-Dev.azure-devices.net;DeviceId=WillyNB;SharedAccessKey=myoJyBj6YKkZZk7WwZgzmXNi/+tVBzMEM3XLWhIBv4w="
}
Name | Type | Value description | |
---|---|---|---|
deviceId | String | 該裝置的 IoTHub 裝置名稱 | |
symmetricKey | primaryKey | String | 對稱金鑰,主要金鑰 |
secondaryKey | String | 對稱金鑰,次要金鑰 | |
azureIoTHubConnectionString | String | Azure IoT Hub 連接字串 |
Unit Test Sample Code C#
Class : IoTDeviceValidationUnitTest
[TestClass]
public class IoTDeviceValidationUnitTest
{
// 測試主機
private const string ApiBaseAddress = "https://ccp-iot-api-dev.core-pcloud.com/";
// CCP 自訂的 Scheme
private const string AuthorizationHeaderScheme = "CCP-HMAC-KEY";
// 測試裝置的 GUID
private const string DeviceGuid = "956D5BE6-AFE0-499E-A579-F08CD684D23D";
// 測試裝置的 SecretKey,註冊時提供,一定要記錄下來,因無法再向系統取得
private const string DeviceSecretKey = "myoJyBj6YKkZZk7WwZgzmXNi/+tVBzMEM3XLWhIBv4w=";
/// <summary>
/// Validations the using hmac authentication test method.
/// </summary>
[TestMethod]
public void ValidationUsingHmacAuthenticationTestMethod()
{
ValidationAsync().Wait();
}
/// <summary>
/// Validations the asynchronous.
/// </summary>
private static async Task ValidationAsync()
{
Console.WriteLine("Calling the back-end API");
Console.WriteLine($"Back-end API Server: {ApiBaseAddress}");
var requestUri = $"{ApiBaseAddress}api/Devices/Validation/{DeviceGuid}";
Console.WriteLine($"Request Uri: {requestUri}");
Console.WriteLine();
var customDelegatingHandler = new HMACAuthenticationDelegatingHandler(DeviceGuid, DeviceSecretKey, AuthorizationHeaderScheme)
{
InnerHandler = new HttpClientHandler()
};
var client = new HttpClient(customDelegatingHandler);
var response = await client.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine();
Console.WriteLine(responseString);
Console.WriteLine("HTTP Status: {0}, Reason {1}. Press ENTER to exit", response.StatusCode,
response.ReasonPhrase);
}
else
{
Console.WriteLine("Failed to call the API. HTTP Status: {0}, Reason {1}", response.StatusCode, response.ReasonPhrase);
}
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
}
}
Class : HMACAuthenticationDelegatingHandler
/// <summary>
/// HMAC 驗證 Header 產生方式
/// </summary>
/// <seealso cref="DelegatingHandler" />
public class HMACAuthenticationDelegatingHandler : DelegatingHandler
{
private readonly string _deviceGuid;
private readonly string _deviceSecretKey;
private readonly string _authorizationHeaderScheme;
public HMACAuthenticationDelegatingHandler(string deviceGuid, string deviceSecretKey, string authorizationHeaderScheme)
{
_deviceGuid = deviceGuid;
_deviceSecretKey = deviceSecretKey;
_authorizationHeaderScheme = authorizationHeaderScheme;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var requestUri = HttpUtility.UrlEncode(request.RequestUri.ToString());
var requestHttpMethod = request.Method.Method;
//Create random nonce for each request
string nonce = Guid.NewGuid().ToString("N");
//Calculate UNIX time
var requestTimeStamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
//Creating the raw signature string
var signatureRawData = $"{_deviceGuid}{requestHttpMethod}{requestUri}{requestTimeStamp}{nonce}";
Console.WriteLine("Signature Raw Data : " + signatureRawData);
Console.WriteLine();
var secretKeyByteArray = Encoding.UTF8.GetBytes(_deviceSecretKey);
var signature = Encoding.UTF8.GetBytes(signatureRawData);
using (var hmac = new HMACSHA256(secretKeyByteArray))
{
var signatureBytes = hmac.ComputeHash(signature);
var requestSignatureBase64String = Convert.ToBase64String(signatureBytes);
//Setting the values in the Authorization header using custom scheme
request.Headers.Authorization = new AuthenticationHeaderValue(_authorizationHeaderScheme,
$"{_deviceGuid}:{requestSignatureBase64String}:{nonce}:{requestTimeStamp}");
Console.WriteLine("Headers Authorization : " + request.Headers.Authorization);
Console.WriteLine();
}
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
April 22, 2020