Microsoft Azure IoTHub client AMQP transport

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more

This library implements the AMQP transport for Microsoft Azure IoTHub client. The code is replicated from https://github.com/Azure/azure-iot-sdks

Revision:
34:51d158b409d2
Parent:
31:adadaef857c1
Child:
41:71c01aa3df1a
--- a/iothubtransport_amqp_cbs_auth.c	Fri Apr 21 14:49:45 2017 -0700
+++ b/iothubtransport_amqp_cbs_auth.c	Mon May 08 10:49:54 2017 -0700
@@ -17,42 +17,32 @@
 #define DEFAULT_SAS_TOKEN_LIFETIME_SECS           3600
 #define DEFAULT_SAS_TOKEN_REFRESH_TIME_SECS       1800
 
-typedef enum CREDENTIAL_TYPE_TAG
-{
-	CREDENTIAL_TYPE_NONE,
-	DEVICE_PRIMARY_KEY,
-	DEVICE_SECONDARY_KEY,
-	USER_PROVIDED_SAS_TOKEN
-} CREDENTIAL_TYPE;
-
 typedef struct AUTHENTICATION_INSTANCE_TAG 
 {
-	STRING_HANDLE device_id;
-	STRING_HANDLE iothub_host_fqdn;
-	
-	STRING_HANDLE device_sas_token;
-	STRING_HANDLE device_primary_key;
-	STRING_HANDLE device_secondary_key;
-
-	ON_AUTHENTICATION_STATE_CHANGED_CALLBACK on_state_changed_callback;
-	void* on_state_changed_callback_context;
+    const char* device_id;
+    STRING_HANDLE iothub_host_fqdn;
+    
+    ON_AUTHENTICATION_STATE_CHANGED_CALLBACK on_state_changed_callback;
+    void* on_state_changed_callback_context;
 
-	ON_AUTHENTICATION_ERROR_CALLBACK on_error_callback;
-	void* on_error_callback_context;
-	
-	size_t cbs_request_timeout_secs;
-	size_t sas_token_lifetime_secs;
-	size_t sas_token_refresh_time_secs;
+    ON_AUTHENTICATION_ERROR_CALLBACK on_error_callback;
+    void* on_error_callback_context;
+    
+    size_t cbs_request_timeout_secs;
+    size_t sas_token_lifetime_secs;
+    size_t sas_token_refresh_time_secs;
 
-	AUTHENTICATION_STATE state;
-	CBS_HANDLE cbs_handle;
+    AUTHENTICATION_STATE state;
+    CBS_HANDLE cbs_handle;
+
+    bool is_cbs_put_token_in_progress;
+    bool is_sas_token_refresh_in_progress;
 
-	bool is_cbs_put_token_in_progress;
-	bool is_sas_token_refresh_in_progress;
+    time_t current_sas_token_put_time;
 
-	time_t current_sas_token_put_time;
-
-	CREDENTIAL_TYPE current_credential_in_use;
+    // Auth module used to generating handle authorization
+    // with either SAS Token, x509 Certs, and Device SAS Token
+    IOTHUB_AUTHORIZATION_HANDLE authorization_module;
 } AUTHENTICATION_INSTANCE;
 
 
@@ -60,923 +50,780 @@
 
 static int get_seconds_since_epoch(double *seconds)
 {
-	int result;
-	time_t current_time;
+    int result;
+    time_t current_time;
 
-	if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
-	{
-		LogError("Failed getting the current local time (get_time() failed)");
-		result = __FAILURE__;
-	}
-	else
-	{
-		*seconds = get_difftime(current_time, (time_t)0);
+    if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+    {
+        LogError("Failed getting the current local time (get_time() failed)");
+        result = __FAILURE__;
+    }
+    else
+    {
+        *seconds = get_difftime(current_time, (time_t)0);
 
-		result = RESULT_OK;
-	}
+        result = RESULT_OK;
+    }
 
-	return result;
+    return result;
 }
 
 static void update_state(AUTHENTICATION_INSTANCE* instance, AUTHENTICATION_STATE new_state)
 {
-	if (new_state != instance->state)
-	{
-		AUTHENTICATION_STATE previous_state = instance->state;
-		instance->state = new_state;
+    if (new_state != instance->state)
+    {
+        AUTHENTICATION_STATE previous_state = instance->state;
+        instance->state = new_state;
 
-		if (instance->on_state_changed_callback != NULL)
-		{
-			instance->on_state_changed_callback(instance->on_state_changed_callback_context, previous_state, new_state);
-		}
-	}
+        if (instance->on_state_changed_callback != NULL)
+        {
+            instance->on_state_changed_callback(instance->on_state_changed_callback_context, previous_state, new_state);
+        }
+    }
 }
 
 static void notify_error(AUTHENTICATION_INSTANCE* instance, AUTHENTICATION_ERROR_CODE error_code)
 {
-	if (instance->on_error_callback != NULL)
-	{
-		instance->on_error_callback(instance->on_error_callback_context, error_code);
-	}
+    if (instance->on_error_callback != NULL)
+    {
+        instance->on_error_callback(instance->on_error_callback_context, error_code);
+    }
 }
 
 static int verify_cbs_put_token_timeout(AUTHENTICATION_INSTANCE* instance, bool* is_timed_out)
 {
-	int result;
+    int result;
 
-	if (instance->current_sas_token_put_time == INDEFINITE_TIME)
-	{
-		result = __FAILURE__;
-		LogError("Failed verifying if cbs_put_token has timed out (current_sas_token_put_time is not set)");
-	}
-	else
-	{
-		time_t current_time;
+    if (instance->current_sas_token_put_time == INDEFINITE_TIME)
+    {
+        result = __FAILURE__;
+        LogError("Failed verifying if cbs_put_token has timed out (current_sas_token_put_time is not set)");
+    }
+    else
+    {
+        time_t current_time;
 
-		if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
-		{
-			result = __FAILURE__;
-			LogError("Failed verifying if cbs_put_token has timed out (get_time failed)");
-		}
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_083: [authentication_do_work() shall check for authentication timeout comparing the current time since `instance->current_sas_token_put_time` to `instance->cbs_request_timeout_secs`]
-		else if ((uint32_t)get_difftime(current_time, instance->current_sas_token_put_time) >= instance->cbs_request_timeout_secs)
-		{
-			*is_timed_out = true;
-			result = RESULT_OK;
-		}
-		else
-		{
-			*is_timed_out = false;
-			result = RESULT_OK;
-		}
-	}
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            result = __FAILURE__;
+            LogError("Failed verifying if cbs_put_token has timed out (get_time failed)");
+        }
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_083: [authentication_do_work() shall check for authentication timeout comparing the current time since `instance->current_sas_token_put_time` to `instance->cbs_request_timeout_secs`]
+        else if ((uint32_t)get_difftime(current_time, instance->current_sas_token_put_time) >= instance->cbs_request_timeout_secs)
+        {
+            *is_timed_out = true;
+            result = RESULT_OK;
+        }
+        else
+        {
+            *is_timed_out = false;
+            result = RESULT_OK;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 static int verify_sas_token_refresh_timeout(AUTHENTICATION_INSTANCE* instance, bool* is_timed_out)
 {
-	int result;
-
-	if (instance->current_sas_token_put_time == INDEFINITE_TIME)
-	{
-		result = __FAILURE__;
-		LogError("Failed verifying if SAS token refresh timed out (current_sas_token_put_time is not set)");
-	}
-	else
-	{
-		time_t current_time;
+    int result;
 
-		if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
-		{
-			result = __FAILURE__;
-			LogError("Failed verifying if SAS token refresh timed out (get_time failed)");
-		}
-		else if ((uint32_t)get_difftime(current_time, instance->current_sas_token_put_time) >= instance->sas_token_refresh_time_secs)
-		{
-			*is_timed_out = true;
-			result = RESULT_OK;
-		}
-		else
-		{
-			*is_timed_out = false;
-			result = RESULT_OK;
-		}
-	}
-
-	return result;
-}
-
-static STRING_HANDLE create_devices_path(STRING_HANDLE iothub_host_fqdn, STRING_HANDLE device_id)
-{
-	STRING_HANDLE devices_path;
-
-	if ((devices_path = STRING_new()) == NULL)
-	{
-		LogError("Failed creating devices_path (STRING_new failed)");
-	}
+    if (instance->current_sas_token_put_time == INDEFINITE_TIME)
+    {
+        result = __FAILURE__;
+        LogError("Failed verifying if SAS token refresh timed out (current_sas_token_put_time is not set)");
+    }
     else
     {
-        const char* device_id_c_str = STRING_c_str(device_id);
-        const char* iothub_host_fqdn_c_str = STRING_c_str(iothub_host_fqdn);
-        
-        if (STRING_sprintf(devices_path, IOTHUB_DEVICES_PATH_FMT, iothub_host_fqdn_c_str, device_id_c_str) != RESULT_OK)
+        time_t current_time;
+
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
         {
-            STRING_delete(devices_path);
-            devices_path = NULL;
-            LogError("Failed creating devices_path (STRING_sprintf failed)");
+            result = __FAILURE__;
+            LogError("Failed verifying if SAS token refresh timed out (get_time failed)");
+        }
+        else if ((uint32_t)get_difftime(current_time, instance->current_sas_token_put_time) >= instance->sas_token_refresh_time_secs)
+        {
+            *is_timed_out = true;
+            result = RESULT_OK;
+        }
+        else
+        {
+            *is_timed_out = false;
+            result = RESULT_OK;
         }
     }
 
-	return devices_path;
-}
-
-
-static bool are_device_keys_used_for_authentication(AUTHENTICATION_INSTANCE* instance)
-{
-	return (instance->current_credential_in_use == DEVICE_PRIMARY_KEY || instance->current_credential_in_use == DEVICE_SECONDARY_KEY);
+    return result;
 }
 
-// @returns  0 there is one more device key to be attempted, !=0 otherwise.
-static int mark_current_device_key_as_invalid(AUTHENTICATION_INSTANCE* instance)
+static STRING_HANDLE create_devices_path(STRING_HANDLE iothub_host_fqdn, const char* device_id)
 {
-	int result;
-
-	if (instance->current_credential_in_use == DEVICE_PRIMARY_KEY)
-	{
-		if (instance->device_secondary_key != NULL)
-		{
-			instance->current_credential_in_use = DEVICE_SECONDARY_KEY;
-			LogError("Primary key of device '%s' was marked as invalid. Using secondary key now", STRING_c_str(instance->device_id));
-			result = 0;
-		}
-		else
-		{
-			instance->current_credential_in_use = CREDENTIAL_TYPE_NONE;
-			LogError("Primary key of device '%s' was marked as invalid. No other device keys available", STRING_c_str(instance->device_id));
-			result = __FAILURE__;
-		}
-	}
-	else if (instance->current_credential_in_use == DEVICE_SECONDARY_KEY)
-	{
-		instance->current_credential_in_use = CREDENTIAL_TYPE_NONE;
-		LogError("Secondary key of device '%s' was marked as invalid. No other device keys available", STRING_c_str(instance->device_id));
-		result = __FAILURE__;
-	}
-	else
-	{
-		result = __FAILURE__;
-	}
-
-	return result;
-}
-
-static STRING_HANDLE get_current_valid_device_key(AUTHENTICATION_INSTANCE* instance)
-{
-	STRING_HANDLE device_key;
-
-	switch (instance->current_credential_in_use)
-	{
-	case DEVICE_PRIMARY_KEY:
-		device_key = instance->device_primary_key;
-		break;
-	case DEVICE_SECONDARY_KEY:
-		device_key = instance->device_secondary_key;
-		break;
-	default:
-		device_key = NULL;
-		break;
-	}
-
-	return device_key;
+    STRING_HANDLE devices_path;
+    if ((devices_path = STRING_construct_sprintf(IOTHUB_DEVICES_PATH_FMT, STRING_c_str(iothub_host_fqdn), device_id)) == NULL)
+    {
+        LogError("Failed creating devices_path (STRING_new failed)");
+    }
+    return devices_path;
 }
 
 static void on_cbs_put_token_complete_callback(void* context, CBS_OPERATION_RESULT operation_result, unsigned int status_code, const char* status_description)
 {
 #ifdef NO_LOGGING
-	UNUSED(status_code);
-	UNUSED(status_description);
+    UNUSED(status_code);
+    UNUSED(status_description);
 #endif
-	AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)context;
+    AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)context;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_095: [`instance->is_sas_token_refresh_in_progress` and `instance->is_cbs_put_token_in_progress` shall be set to FALSE]
-	instance->is_cbs_put_token_in_progress = false;
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_095: [`instance->is_sas_token_refresh_in_progress` and `instance->is_cbs_put_token_in_progress` shall be set to FALSE]
+    instance->is_cbs_put_token_in_progress = false;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_091: [If `result` is CBS_OPERATION_RESULT_OK `instance->state` shall be set to AUTHENTICATION_STATE_STARTED and `instance->on_state_changed_callback` invoked]
-	if (operation_result == CBS_OPERATION_RESULT_OK)
-	{
-		update_state(instance, AUTHENTICATION_STATE_STARTED);
-	}
-	else
-	{
-		LogError("CBS reported status code %u, error: '%s' for put-token operation for device '%s'", status_code, status_description, STRING_c_str(instance->device_id));
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_091: [If `result` is CBS_OPERATION_RESULT_OK `instance->state` shall be set to AUTHENTICATION_STATE_STARTED and `instance->on_state_changed_callback` invoked]
+    if (operation_result == CBS_OPERATION_RESULT_OK)
+    {
+        update_state(instance, AUTHENTICATION_STATE_STARTED);
+    }
+    else
+    {
+        LogError("CBS reported status code %u, error: '%s' for put-token operation for device '%s'", status_code, status_description, instance->device_id);
 
-		if (mark_current_device_key_as_invalid(instance) != 0)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_092: [If `result` is not CBS_OPERATION_RESULT_OK `instance->state` shall be set to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
-			update_state(instance, AUTHENTICATION_STATE_ERROR);
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_092: [If `result` is not CBS_OPERATION_RESULT_OK `instance->state` shall be set to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
+        update_state(instance, AUTHENTICATION_STATE_ERROR);
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_094: [If `result` is not CBS_OPERATION_RESULT_OK and `instance->is_sas_token_refresh_in_progress` is TRUE, `instance->on_error_callback`shall be invoked with AUTHENTICATION_ERROR_SAS_REFRESH_FAILED]
-			if (instance->is_sas_token_refresh_in_progress)
-			{
-				notify_error(instance, AUTHENTICATION_ERROR_SAS_REFRESH_FAILED);
-			}
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_093: [If `result` is not CBS_OPERATION_RESULT_OK and `instance->is_sas_token_refresh_in_progress` is FALSE, `instance->on_error_callback`shall be invoked with AUTHENTICATION_ERROR_AUTH_FAILED]
-			else
-			{
-				notify_error(instance, AUTHENTICATION_ERROR_AUTH_FAILED);
-			}
-		}
-	}
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_094: [If `result` is not CBS_OPERATION_RESULT_OK and `instance->is_sas_token_refresh_in_progress` is TRUE, `instance->on_error_callback`shall be invoked with AUTHENTICATION_ERROR_SAS_REFRESH_FAILED]
+        if (instance->is_sas_token_refresh_in_progress)
+        {
+            notify_error(instance, AUTHENTICATION_ERROR_SAS_REFRESH_FAILED);
+        }
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_093: [If `result` is not CBS_OPERATION_RESULT_OK and `instance->is_sas_token_refresh_in_progress` is FALSE, `instance->on_error_callback`shall be invoked with AUTHENTICATION_ERROR_AUTH_FAILED]
+        else
+        {
+            notify_error(instance, AUTHENTICATION_ERROR_AUTH_FAILED);
+        }
+    }
 
-	instance->is_sas_token_refresh_in_progress = false;
+    instance->is_sas_token_refresh_in_progress = false;
 }
 
-static int put_SAS_token_to_cbs(AUTHENTICATION_INSTANCE* instance, STRING_HANDLE cbs_audience, STRING_HANDLE sas_token)
+static int put_SAS_token_to_cbs(AUTHENTICATION_INSTANCE* instance, STRING_HANDLE cbs_audience, char* sas_token)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_043: [authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to TRUE]
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_057: [authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to TRUE]
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_075: [authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to TRUE]
-	instance->is_cbs_put_token_in_progress = true;
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_043: [authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to TRUE]
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_057: [authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to TRUE]
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_075: [authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to TRUE]
+    instance->is_cbs_put_token_in_progress = true;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_046: [The SAS token provided shall be sent to CBS using cbs_put_token(), using `servicebus.windows.net:sastoken` as token type, `devices_path` as audience and passing on_cbs_put_token_complete_callback]
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_058: [The SAS token shall be sent to CBS using cbs_put_token(), using `servicebus.windows.net:sastoken` as token type, `devices_path` as audience and passing on_cbs_put_token_complete_callback]
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_076: [The SAS token shall be sent to CBS using cbs_put_token(), using `servicebus.windows.net:sastoken` as token type, `devices_path` as audience and passing on_cbs_put_token_complete_callback]
-    const char* sas_token_c_str = STRING_c_str(sas_token);
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_046: [The SAS token provided shall be sent to CBS using cbs_put_token(), using `servicebus.windows.net:sastoken` as token type, `devices_path` as audience and passing on_cbs_put_token_complete_callback]
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_058: [The SAS token shall be sent to CBS using cbs_put_token(), using `servicebus.windows.net:sastoken` as token type, `devices_path` as audience and passing on_cbs_put_token_complete_callback]
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_076: [The SAS token shall be sent to CBS using cbs_put_token(), using `servicebus.windows.net:sastoken` as token type, `devices_path` as audience and passing on_cbs_put_token_complete_callback]
     const char* cbs_audience_c_str = STRING_c_str(cbs_audience);
-	if (cbs_put_token_async(instance->cbs_handle, SAS_TOKEN_TYPE, cbs_audience_c_str, sas_token_c_str, on_cbs_put_token_complete_callback, instance) != RESULT_OK)
-	{
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_048: [If cbs_put_token() failed, authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to FALSE, destroy `devices_path` and return]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_060: [If cbs_put_token() fails, `instance->is_cbs_put_token_in_progress` shall be set to FALSE]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_078: [If cbs_put_token() fails, `instance->is_cbs_put_token_in_progress` shall be set to FALSE]
-		instance->is_cbs_put_token_in_progress = false;
-		result = __FAILURE__;
-		LogError("Failed putting SAS token to CBS for device '%s' (cbs_put_token failed)", STRING_c_str(instance->device_id));
-	}
-	else
-	{
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_047: [If cbs_put_token() succeeds, authentication_do_work() shall set `instance->current_sas_token_put_time` with current time]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_059: [If cbs_put_token() succeeds, authentication_do_work() shall set `instance->current_sas_token_put_time` with current time]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_077: [If cbs_put_token() succeeds, authentication_do_work() shall set `instance->current_sas_token_put_time` with the current time]
-		time_t current_time;
+    if (cbs_put_token_async(instance->cbs_handle, SAS_TOKEN_TYPE, cbs_audience_c_str, sas_token, on_cbs_put_token_complete_callback, instance) != RESULT_OK)
+    {
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_048: [If cbs_put_token() failed, authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to FALSE, destroy `devices_path` and return]
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_060: [If cbs_put_token() fails, `instance->is_cbs_put_token_in_progress` shall be set to FALSE]
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_078: [If cbs_put_token() fails, `instance->is_cbs_put_token_in_progress` shall be set to FALSE]
+        instance->is_cbs_put_token_in_progress = false;
+        result = __FAILURE__;
+        LogError("Failed putting SAS token to CBS for device '%s' (cbs_put_token failed)", instance->device_id);
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_047: [If cbs_put_token() succeeds, authentication_do_work() shall set `instance->current_sas_token_put_time` with current time]
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_059: [If cbs_put_token() succeeds, authentication_do_work() shall set `instance->current_sas_token_put_time` with current time]
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_077: [If cbs_put_token() succeeds, authentication_do_work() shall set `instance->current_sas_token_put_time` with the current time]
+        time_t current_time;
 
-		if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
-		{
-			LogError("Failed setting current_sas_token_put_time for device '%s' (get_time() failed)", STRING_c_str(instance->device_id));
-		}
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            LogError("Failed setting current_sas_token_put_time for device '%s' (get_time() failed)", instance->device_id);
+        }
 
-		instance->current_sas_token_put_time = current_time; // If it failed, fear not. `current_sas_token_put_time` shall be checked for INDEFINITE_TIME wherever it is used.
+        instance->current_sas_token_put_time = current_time; // If it failed, fear not. `current_sas_token_put_time` shall be checked for INDEFINITE_TIME wherever it is used.
 
-		result = RESULT_OK;
-	}
+        result = RESULT_OK;
+    }
 
-	return result;
+    return result;
 }
 
-static int create_and_put_SAS_token_to_cbs(AUTHENTICATION_INSTANCE* instance, STRING_HANDLE device_key)
+static int create_and_put_SAS_token_to_cbs(AUTHENTICATION_INSTANCE* instance)
 {
-	int result;
-	double seconds_since_epoch;
+    int result;
+    char* sas_token;
+    STRING_HANDLE devices_path;
 
-	if (get_seconds_since_epoch(&seconds_since_epoch) != RESULT_OK)
-	{
-		result = __FAILURE__;
-		LogError("Failed creating a SAS token (get_seconds_since_epoch() failed)");
-	}
-	else
-	{
-		STRING_HANDLE devices_path = NULL;
-		STRING_HANDLE sasTokenKeyName = NULL;
-		STRING_HANDLE sas_token = NULL;
-
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_052: [The SAS token expiration time shall be calculated adding `instance->sas_token_lifetime_secs` to the current number of seconds since epoch time UTC]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_070: [The SAS token expiration time shall be calculated adding `instance->sas_token_lifetime_secs` to the current number of seconds since epoch time UTC]
-		size_t sas_token_expiration_time_secs = (size_t)seconds_since_epoch + instance->sas_token_lifetime_secs;
+    if ((devices_path = create_devices_path(instance->iothub_host_fqdn, instance->device_id)) == NULL)
+    {
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_054: [If `devices_path` failed to be created, authentication_do_work() shall fail and return]
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_072: [If `devices_path` failed to be created, authentication_do_work() shall fail and return]
+        result = __FAILURE__;
+        sas_token = NULL;
+        LogError("Failed creating a SAS token (create_devices_path() failed)");
+    }
+    else
+    {
+        /* Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_07_001: [ authentication_do_work() shall determine what credential type is used SAS_TOKEN or DEVICE_KEY by calling IoTHubClient_Auth_Get_Credential_Type ] */
+        IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(instance->authorization_module);
+        if (cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY)
+        {
+            double seconds_since_epoch;
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_053: [A STRING_HANDLE, referred to as `devices_path`, shall be created from the following parts: iothub_host_fqdn + "/devices/" + device_id]
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_071: [A STRING_HANDLE, referred to as `devices_path`, shall be created from the following parts: iothub_host_fqdn + "/devices/" + device_id]
+            if (get_seconds_since_epoch(&seconds_since_epoch) != RESULT_OK)
+            {
+                result = __FAILURE__;
+                sas_token = NULL;
+                LogError("Failed creating a SAS token (get_seconds_since_epoch() failed)");
+            }
+            else
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_052: [The SAS token expiration time shall be calculated adding `instance->sas_token_lifetime_secs` to the current number of seconds since epoch time UTC]
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_070: [The SAS token expiration time shall be calculated adding `instance->sas_token_lifetime_secs` to the current number of seconds since epoch time UTC]
+                size_t sas_token_expiration_time_secs = (size_t)seconds_since_epoch + instance->sas_token_lifetime_secs;
 
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_053: [A STRING_HANDLE, referred to as `devices_path`, shall be created from the following parts: iothub_host_fqdn + "/devices/" + device_id]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_071: [A STRING_HANDLE, referred to as `devices_path`, shall be created from the following parts: iothub_host_fqdn + "/devices/" + device_id]
-		if ((devices_path = create_devices_path(instance->iothub_host_fqdn, instance->device_id)) == NULL)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_054: [If `devices_path` failed to be created, authentication_do_work() shall fail and return]
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_072: [If `devices_path` failed to be created, authentication_do_work() shall fail and return]		
-			result = __FAILURE__;
-			LogError("Failed creating a SAS token (create_devices_path() failed)");
-		}
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_115: [An empty STRING_HANDLE, referred to as `sasTokenKeyName`, shall be created using STRING_new()]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_117: [An empty STRING_HANDLE, referred to as `sasTokenKeyName`, shall be created using STRING_new()]
-		else if ((sasTokenKeyName = STRING_new()) == NULL)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_116: [If `sasTokenKeyName` failed to be created, authentication_do_work() shall fail and return]
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_118: [If `sasTokenKeyName` failed to be created, authentication_do_work() shall fail and return]
-			result = __FAILURE__;
-			LogError("Failed creating a SAS token (STRING_new() failed)");
-		}
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_055: [The SAS token shall be created using SASToken_Create(), passing the selected device key, `device_path`, `sasTokenKeyName` and expiration time as arguments]
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_073: [The SAS token shall be created using SASToken_Create(), passing the selected device key, device_path, sasTokenKeyName and expiration time as arguments]
-		else if ((sas_token = SASToken_Create(device_key, devices_path, sasTokenKeyName, (size_t)sas_token_expiration_time_secs)) == NULL)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_056: [If SASToken_Create() fails, authentication_do_work() shall fail and return]
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_074: [If SASToken_Create() fails, authentication_do_work() shall fail and return]
-			result = __FAILURE__;
-			LogError("Failed creating a SAS token (SASToken_Create() failed)");
-		}
-		else if (put_SAS_token_to_cbs(instance, devices_path, sas_token) != RESULT_OK)
-		{
-			result = __FAILURE__;
-			LogError("Failed putting SAS token to CBS");
-		}
-		else
-		{
-			result = RESULT_OK;
-		}
+                /* Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_049: [authentication_do_work() shall create a SAS token using IoTHubClient_Auth_Get_SasToken, unless it has failed previously] */
+                sas_token = IoTHubClient_Auth_Get_SasToken(instance->authorization_module, STRING_c_str(devices_path), sas_token_expiration_time_secs);
+                if (sas_token == NULL)
+                {
+                    LogError("failure getting sas token.");
+                    result = __FAILURE__;
+                }
+                else
+                {
+                    result = RESULT_OK;
+                }
+            }
+        }
+        else if (cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
+        {
+            /* Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_07_002: [ If credential Type is SAS_TOKEN authentication_do_work() shall validate the sas_token, and fail if it's not valid. ] */
+            SAS_TOKEN_STATUS token_status = IoTHubClient_Auth_Is_SasToken_Valid(instance->authorization_module);
+            if (token_status == SAS_TOKEN_STATUS_INVALID)
+            {
+                LogError("sas token is invalid.");
+                sas_token = NULL;
+                result = __FAILURE__;
+            }
+            else if (token_status == SAS_TOKEN_STATUS_FAILED)
+            {
+                LogError("testing Sas Token failed.");
+                sas_token = NULL;
+                result = __FAILURE__;
+            }
+            else
+            {
+                /* Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_049: [authentication_do_work() shall create a SAS token using IoTHubClient_Auth_Get_SasToken, unless it has failed previously] */
+                sas_token = IoTHubClient_Auth_Get_SasToken(instance->authorization_module, NULL, 0);
+                if (sas_token == NULL)
+                {
+                    LogError("failure getting sas Token.");
+                    result = __FAILURE__;
+                }
+                else
+                {
+                    result = RESULT_OK;
+                }
+            }
+        }
+        else if (cred_type == IOTHUB_CREDENTIAL_TYPE_X509)
+        {
+            sas_token = NULL;
+            result = RESULT_OK;
+        }
+        else
+        {
+            LogError("failure unknown credential type found.");
+            sas_token = NULL;
+            result = __FAILURE__;
+        }
 
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_081: [authentication_do_work() shall free the memory it allocated for `devices_path`, `sasTokenKeyName` and SAS token]
-		if (devices_path != NULL)
-			STRING_delete(devices_path);
-		if (sasTokenKeyName != NULL)
-			STRING_delete(sasTokenKeyName);
-		if (sas_token != NULL)
-			STRING_delete(sas_token);
-	}
 
-	return result;
+        if (sas_token != NULL)
+        {
+            if (put_SAS_token_to_cbs(instance, devices_path, sas_token) != RESULT_OK)
+            {
+                result = __FAILURE__;
+                LogError("Failed putting SAS token to CBS");
+            }
+            else
+            {
+                result = RESULT_OK;
+            }
+            free(sas_token);
+        }
+
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_081: [authentication_do_work() shall free the memory it allocated for `devices_path`, `sasTokenKeyName` and SAS token]
+        STRING_delete(devices_path);
+    }
+    return result;
 }
 
-
 // ---------- Set/Retrieve Options Helpers ----------//
-
 static void* authentication_clone_option(const char* name, const void* value)
 {
-	void* result;
+    void* result;
 
-	if (name == NULL)
-	{
-		LogError("Failed to clone authentication option (name is NULL)"); 
-		result = NULL;
-	}
-	else if (value == NULL)
-	{
-		LogError("Failed to clone authentication option (value is NULL)");
-		result = NULL;
-	}
-	else
-	{
-		if (strcmp(AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0 ||
-			strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0 ||
-			strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0 ||
-			strcmp(AUTHENTICATION_OPTION_SAVED_OPTIONS, name) == 0)
-		{
-			result = (void*)value;
-		}
-		else
-		{
-			LogError("Failed to clone authentication option (option with name '%s' is not suppported)", name);
-			result = NULL;
-		}
-	}
+    if (name == NULL)
+    {
+        LogError("Failed to clone authentication option (name is NULL)"); 
+        result = NULL;
+    }
+    else if (value == NULL)
+    {
+        LogError("Failed to clone authentication option (value is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        if (strcmp(AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0 ||
+            strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0 ||
+            strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0 ||
+            strcmp(AUTHENTICATION_OPTION_SAVED_OPTIONS, name) == 0)
+        {
+            result = (void*)value;
+        }
+        else
+        {
+            LogError("Failed to clone authentication option (option with name '%s' is not suppported)", name);
+            result = NULL;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 static void authentication_destroy_option(const char* name, const void* value)
 {
-	if (name == NULL)
-	{
-		LogError("Failed to destroy authentication option (name is NULL)");
-	}
-	else if (value == NULL)
-	{
-		LogError("Failed to destroy authentication option (value is NULL)");
-	}
-	else
-	{
-		if (strcmp(name, AUTHENTICATION_OPTION_SAVED_OPTIONS) == 0)
-		{
-			OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
-		}
-	}
+    if (name == NULL)
+    {
+        LogError("Failed to destroy authentication option (name is NULL)");
+    }
+    else if (value == NULL)
+    {
+        LogError("Failed to destroy authentication option (value is NULL)");
+    }
+    else
+    {
+        if (strcmp(name, AUTHENTICATION_OPTION_SAVED_OPTIONS) == 0)
+        {
+            OptionHandler_Destroy((OPTIONHANDLER_HANDLE)value);
+        }
+    }
 }
 
-
 // Public APIs:
-
 int authentication_start(AUTHENTICATION_HANDLE authentication_handle, const CBS_HANDLE cbs_handle)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_025: [If authentication_handle is NULL, authentication_start() shall fail and return __FAILURE__ as error code]
-	if (authentication_handle == NULL)
-	{
-		result = __FAILURE__;
-		LogError("authentication_start failed (authentication_handle is NULL)");
-	}
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_026: [If `cbs_handle` is NULL, authentication_start() shall fail and return __FAILURE__ as error code]
-	else if (cbs_handle == NULL)
-	{
-		result = __FAILURE__;
-		LogError("authentication_start failed (cbs_handle is NULL)");
-	}
-	else
-	{
-		AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_027: [If authenticate state has been started already, authentication_start() shall fail and return __FAILURE__ as error code]
-		if (instance->state != AUTHENTICATION_STATE_STOPPED)
-		{
-			result = __FAILURE__;
-			LogError("authentication_start failed (messenger has already been started; current state: %d)", instance->state);
-		}
-		else
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_028: [authentication_start() shall save `cbs_handle` on `instance->cbs_handle`]
-			instance->cbs_handle = cbs_handle;
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_025: [If authentication_handle is NULL, authentication_start() shall fail and return __FAILURE__ as error code]
+    if (authentication_handle == NULL)
+    {
+        result = __FAILURE__;
+        LogError("authentication_start failed (authentication_handle is NULL)");
+    }
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_026: [If `cbs_handle` is NULL, authentication_start() shall fail and return __FAILURE__ as error code]
+    else if (cbs_handle == NULL)
+    {
+        result = __FAILURE__;
+        LogError("authentication_start failed (cbs_handle is NULL)");
+    }
+    else
+    {
+        AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
+        
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_027: [If authenticate state has been started already, authentication_start() shall fail and return __FAILURE__ as error code]
+        if (instance->state != AUTHENTICATION_STATE_STOPPED)
+        {
+            result = __FAILURE__;
+            LogError("authentication_start failed (messenger has already been started; current state: %d)", instance->state);
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_028: [authentication_start() shall save `cbs_handle` on `instance->cbs_handle`]
+            instance->cbs_handle = cbs_handle;
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_029: [If no failures occur, `instance->state` shall be set to AUTHENTICATION_STATE_STARTING and `instance->on_state_changed_callback` invoked]
-			update_state(instance, AUTHENTICATION_STATE_STARTING);
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_029: [If no failures occur, `instance->state` shall be set to AUTHENTICATION_STATE_STARTING and `instance->on_state_changed_callback` invoked]
+            update_state(instance, AUTHENTICATION_STATE_STARTING);
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_030: [If no failures occur, authentication_start() shall return 0]
-			result = RESULT_OK;
-		}
-	}
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_030: [If no failures occur, authentication_start() shall return 0]
+            result = RESULT_OK;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 int authentication_stop(AUTHENTICATION_HANDLE authentication_handle)
 {
-	int result;
-	
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_031: [If `authentication_handle` is NULL, authentication_stop() shall fail and return __FAILURE__]
-	if (authentication_handle == NULL)
-	{
-		result = __FAILURE__;
-		LogError("authentication_stop failed (authentication_handle is NULL)");
-	}
-	else
-	{
-		AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
+    int result;
+    
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_031: [If `authentication_handle` is NULL, authentication_stop() shall fail and return __FAILURE__]
+    if (authentication_handle == NULL)
+    {
+        result = __FAILURE__;
+        LogError("authentication_stop failed (authentication_handle is NULL)");
+    }
+    else
+    {
+        AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
 
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_032: [If `instance->state` is AUTHENTICATION_STATE_STOPPED, authentication_stop() shall fail and return __FAILURE__]
-		if (instance->state == AUTHENTICATION_STATE_STOPPED)
-		{
-			result = __FAILURE__;
-			LogError("authentication_stop failed (messenger is already stopped)");
-		}
-		else
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_033: [`instance->cbs_handle` shall be set to NULL]
-			instance->cbs_handle = NULL;
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_032: [If `instance->state` is AUTHENTICATION_STATE_STOPPED, authentication_stop() shall fail and return __FAILURE__]
+        if (instance->state == AUTHENTICATION_STATE_STOPPED)
+        {
+            result = __FAILURE__;
+            LogError("authentication_stop failed (messenger is already stopped)");
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_033: [`instance->cbs_handle` shall be set to NULL]
+            instance->cbs_handle = NULL;
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_034: [`instance->state` shall be set to AUTHENTICATION_STATE_STOPPED and `instance->on_state_changed_callback` invoked]
-			update_state(instance, AUTHENTICATION_STATE_STOPPED);
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_034: [`instance->state` shall be set to AUTHENTICATION_STATE_STOPPED and `instance->on_state_changed_callback` invoked]
+            update_state(instance, AUTHENTICATION_STATE_STOPPED);
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_035: [authentication_stop() shall return success code 0]
-			result = RESULT_OK;
-		}
-	}
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_035: [authentication_stop() shall return success code 0]
+            result = RESULT_OK;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 void authentication_destroy(AUTHENTICATION_HANDLE authentication_handle)
 {
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_106: [If authentication_handle is NULL, authentication_destroy() shall return]
-	if (authentication_handle == NULL)
-	{
-		LogError("authentication_destroy failed (authentication_handle is NULL)");
-	}
-	else
-	{
-		AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
-
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_107: [If `instance->state` is AUTHENTICATION_STATE_STARTING or AUTHENTICATION_STATE_STARTED, authentication_stop() shall be invoked and its result ignored]
-		if (instance->state != AUTHENTICATION_STATE_STOPPED)
-		{
-			(void)authentication_stop(authentication_handle);
-		}
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_108: [authentication_destroy() shall destroy `instance->device_id` using STRING_delete()]
-		if (instance->device_id != NULL)
-			STRING_delete(instance->device_id);
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_106: [If authentication_handle is NULL, authentication_destroy() shall return]
+    if (authentication_handle == NULL)
+    {
+        LogError("authentication_destroy failed (authentication_handle is NULL)");
+    }
+    else
+    {
+        AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
 
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_109: [authentication_destroy() shall destroy `instance->device_sas_token` using STRING_delete()]
-		if (instance->device_sas_token != NULL)
-			STRING_delete(instance->device_sas_token);
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_110: [authentication_destroy() shall destroy `instance->device_primary_key` using STRING_delete()]
-		if (instance->device_primary_key != NULL)
-			STRING_delete(instance->device_primary_key);
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_111: [authentication_destroy() shall destroy `instance->device_secondary_key` using STRING_delete()]
-		if (instance->device_secondary_key != NULL)
-			STRING_delete(instance->device_secondary_key);
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_112: [authentication_destroy() shall destroy `instance->iothub_host_fqdn` using STRING_delete()]
-		if (instance->iothub_host_fqdn != NULL)
-			STRING_delete(instance->iothub_host_fqdn);
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_113: [authentication_destroy() shall destroy `instance` using free()]
-		free(instance);
-	}
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_107: [If `instance->state` is AUTHENTICATION_STATE_STARTING or AUTHENTICATION_STATE_STARTED, authentication_stop() shall be invoked and its result ignored]
+        if (instance->state != AUTHENTICATION_STATE_STOPPED)
+        {
+            (void)authentication_stop(authentication_handle);
+        }
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_108: [authentication_destroy() shall destroy all resouces used by this module]
+        if (instance->iothub_host_fqdn != NULL)
+            STRING_delete(instance->iothub_host_fqdn);
+
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_108: [authentication_destroy() shall destroy all resouces used by this module]
+        free(instance);
+    }
 }
 
 AUTHENTICATION_HANDLE authentication_create(const AUTHENTICATION_CONFIG* config)
 {
-	AUTHENTICATION_HANDLE result;
+    AUTHENTICATION_HANDLE result;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_001: [If parameter `config` or `config->device_id` are NULL, authentication_create() shall fail and return NULL.]
-	if (config == NULL)
-	{
-		result = NULL;
-		LogError("authentication_create failed (config is NULL)");
-	}
-	else if (config->device_id == NULL)
-	{
-		result = NULL;
-		LogError("authentication_create failed (config->device_id is NULL)");
-	}
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_002: [If device keys and SAS token are NULL, authentication_create() shall fail and return NULL.]
-	else if (config->device_sas_token == NULL && config->device_primary_key == NULL)
-	{
-		result = NULL;
-		LogError("authentication_create failed (either config->device_sas_token or config->device_primary_key must be provided; config->device_secondary_key is optional)");
-	}
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_003: [If device keys and SAS token are both provided, authentication_create() shall fail and return NULL.]
-	else if (config->device_sas_token != NULL && (config->device_primary_key != NULL || config->device_secondary_key != NULL))
-	{
-		result = NULL;
-		LogError("authentication_create failed (both config->device_sas_token and device device keys were provided; must provide only one)");
-	}
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_004: [If `config->iothub_host_fqdn` is NULL, authentication_create() shall fail and return NULL.]
-	else if (config->iothub_host_fqdn == NULL)
-	{
-		result = NULL;
-		LogError("authentication_create failed (config->iothub_host_fqdn is NULL)");
-	}
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_005: [If `config->on_state_changed_callback` is NULL, authentication_create() shall fail and return NULL]
-	else if (config->on_state_changed_callback == NULL)
-	{
-		result = NULL;
-		LogError("authentication_create failed (config->on_state_changed_callback is NULL)");
-	}
-	else
-	{
-		AUTHENTICATION_INSTANCE* instance;
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_001: [If parameter `config` is NULL, authentication_create() shall fail and return NULL.]
+    if (config == NULL)
+    {
+        result = NULL;
+        LogError("authentication_create failed (config is NULL)");
+    }
+    else if (config->authorization_module == NULL)
+    {
+        result = NULL;
+        LogError("authentication_create failed (config->authorization_module is NULL)");
+    }
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_004: [If `config->iothub_host_fqdn` is NULL, authentication_create() shall fail and return NULL.]
+    else if (config->iothub_host_fqdn == NULL)
+    {
+        result = NULL;
+        LogError("authentication_create failed (config->iothub_host_fqdn is NULL)");
+    }
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_005: [If `config->on_state_changed_callback` is NULL, authentication_create() shall fail and return NULL]
+    else if (config->on_state_changed_callback == NULL)
+    {
+        result = NULL;
+        LogError("authentication_create failed (config->on_state_changed_callback is NULL)");
+    }
+    else
+    {
+        AUTHENTICATION_INSTANCE* instance;
 
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_006: [authentication_create() shall allocate memory for a new authenticate state structure AUTHENTICATION_INSTANCE.]
-		if ((instance = (AUTHENTICATION_INSTANCE*)malloc(sizeof(AUTHENTICATION_INSTANCE))) == NULL)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_007: [If malloc() fails, authentication_create() shall fail and return NULL.]
-			result = NULL;
-			LogError("authentication_create failed (malloc failed)");
-		}
-		else
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_123: [authentication_create() shall initialize all fields of `instance` with 0 using memset().]
-			memset(instance, 0, sizeof(AUTHENTICATION_INSTANCE));
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_006: [authentication_create() shall allocate memory for a new authenticate state structure AUTHENTICATION_INSTANCE.]
+        if ((instance = (AUTHENTICATION_INSTANCE*)malloc(sizeof(AUTHENTICATION_INSTANCE))) == NULL)
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_007: [If malloc() fails, authentication_create() shall fail and return NULL.]
+            result = NULL;
+            LogError("authentication_create failed (malloc failed)");
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_123: [authentication_create() shall initialize all fields of `instance` with 0 using memset().]
+            memset(instance, 0, sizeof(AUTHENTICATION_INSTANCE));
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_008: [authentication_create() shall save a copy of `config->device_id` into the `instance->device_id`]
-			if ((instance->device_id = STRING_construct(config->device_id)) == NULL)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_009: [If STRING_construct() fails, authentication_create() shall fail and return NULL]
-				result = NULL;
-				LogError("authentication_create failed (config->device_id could not be copied; STRING_construct failed)");
-			}
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_010: [If `device_config->device_sas_token` is not NULL, authentication_create() shall save a copy into the `instance->device_sas_token`]
-			else if (config->device_sas_token != NULL && (instance->device_sas_token = STRING_construct(config->device_sas_token)) == NULL)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_011: [If STRING_construct() fails, authentication_create() shall fail and return NULL]
-				result = NULL;
-				LogError("authentication_create failed (config->device_sas_token could not be copied; STRING_construct failed)");
-			}
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_012: [If provided, authentication_create() shall save a copy of `config->device_primary_key` into the `instance->device_primary_key`]
-			else if (config->device_primary_key != NULL && (instance->device_primary_key = STRING_construct(config->device_primary_key)) == NULL)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_013: [If STRING_construct() fails to copy `config->device_primary_key`, authentication_create() shall fail and return NULL]
-				result = NULL;
-				LogError("authentication_create failed (config->device_primary_key could not be copied; STRING_construct failed)");
-			}
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_014: [If provided, authentication_create() shall save a copy of `config->device_secondary_key` into `instance->device_secondary_key`]
-			else if (config->device_secondary_key != NULL && (instance->device_secondary_key = STRING_construct(config->device_secondary_key)) == NULL)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_015: [If STRING_construct() fails to copy `config->device_secondary_key`, authentication_create() shall fail and return NULL]
-				result = NULL;
-				LogError("authentication_create failed (config->device_secondary_key could not be copied; STRING_construct failed)");
-			}
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_016: [If provided, authentication_create() shall save a copy of `config->iothub_host_fqdn` into `instance->iothub_host_fqdn`]
-			else if ((instance->iothub_host_fqdn = STRING_construct(config->iothub_host_fqdn)) == NULL)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_017: [If STRING_clone() fails to copy `config->iothub_host_fqdn`, authentication_create() shall fail and return NULL]
-				result = NULL;
-				LogError("authentication_create failed (config->iothub_host_fqdn could not be copied; STRING_construct failed)");
-			}
-			else
-			{
-				instance->state = AUTHENTICATION_STATE_STOPPED;
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_008: [authentication_create() shall save the device_id into the `instance->device_id`]
+            if ((instance->device_id = IoTHubClient_Auth_Get_DeviceId(config->authorization_module) ) == NULL)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_009: [If STRING_construct() fails, authentication_create() shall fail and return NULL]
+                result = NULL;
+                LogError("authentication_create failed (config->device_id could not be copied; STRING_construct failed)");
+            }
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_016: [If provided, authentication_create() shall save a copy of `config->iothub_host_fqdn` into `instance->iothub_host_fqdn`]
+            else if ((instance->iothub_host_fqdn = STRING_construct(config->iothub_host_fqdn)) == NULL)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_017: [If STRING_clone() fails to copy `config->iothub_host_fqdn`, authentication_create() shall fail and return NULL]
+                result = NULL;
+                LogError("authentication_create failed (config->iothub_host_fqdn could not be copied; STRING_construct failed)");
+            }
+            else
+            {
+                instance->state = AUTHENTICATION_STATE_STOPPED;
+
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_018: [authentication_create() shall save `config->on_state_changed_callback` and `config->on_state_changed_callback_context` into `instance->on_state_changed_callback` and `instance->on_state_changed_callback_context`.]
+                instance->on_state_changed_callback = config->on_state_changed_callback;
+                instance->on_state_changed_callback_context = config->on_state_changed_callback_context;
 
-				if (instance->device_sas_token != NULL)
-				{
-					instance->current_credential_in_use = USER_PROVIDED_SAS_TOKEN;
-				}
-				else
-				{
-					instance->current_credential_in_use = DEVICE_PRIMARY_KEY;
-				}
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_019: [authentication_create() shall save `config->on_error_callback` and `config->on_error_callback_context` into `instance->on_error_callback` and `instance->on_error_callback_context`.]
+                instance->on_error_callback = config->on_error_callback;
+                instance->on_error_callback_context = config->on_error_callback_context;
 
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_018: [authentication_create() shall save `config->on_state_changed_callback` and `config->on_state_changed_callback_context` into `instance->on_state_changed_callback` and `instance->on_state_changed_callback_context`.]
-				instance->on_state_changed_callback = config->on_state_changed_callback;
-				instance->on_state_changed_callback_context = config->on_state_changed_callback_context;
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_021: [authentication_create() shall set `instance->cbs_request_timeout_secs` with the default value of UINT32_MAX]
+                instance->cbs_request_timeout_secs = DEFAULT_CBS_REQUEST_TIMEOUT_SECS;
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_022: [authentication_create() shall set `instance->sas_token_lifetime_secs` with the default value of one hour]
+                instance->sas_token_lifetime_secs = DEFAULT_SAS_TOKEN_LIFETIME_SECS;
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_023: [authentication_create() shall set `instance->sas_token_refresh_time_secs` with the default value of 30 minutes]
+                instance->sas_token_refresh_time_secs = DEFAULT_SAS_TOKEN_REFRESH_TIME_SECS;
 
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_019: [authentication_create() shall save `config->on_error_callback` and `config->on_error_callback_context` into `instance->on_error_callback` and `instance->on_error_callback_context`.]
-				instance->on_error_callback = config->on_error_callback;
-				instance->on_error_callback_context = config->on_error_callback_context;
+                instance->authorization_module = config->authorization_module;
 
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_021: [authentication_create() shall set `instance->cbs_request_timeout_secs` with the default value of UINT32_MAX]
-				instance->cbs_request_timeout_secs = DEFAULT_CBS_REQUEST_TIMEOUT_SECS;
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_022: [authentication_create() shall set `instance->sas_token_lifetime_secs` with the default value of one hour]
-				instance->sas_token_lifetime_secs = DEFAULT_SAS_TOKEN_LIFETIME_SECS;
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_023: [authentication_create() shall set `instance->sas_token_refresh_time_secs` with the default value of 30 minutes]
-				instance->sas_token_refresh_time_secs = DEFAULT_SAS_TOKEN_REFRESH_TIME_SECS;
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_024: [If no failure occurs, authentication_create() shall return a reference to the AUTHENTICATION_INSTANCE handle]
+                result = (AUTHENTICATION_HANDLE)instance;
+            }
 
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_024: [If no failure occurs, authentication_create() shall return a reference to the AUTHENTICATION_INSTANCE handle]
-				result = (AUTHENTICATION_HANDLE)instance;
-			}
-
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_020: [If any failure occurs, authentication_create() shall free any memory it allocated previously]
-			if (result == NULL)
-			{
-				authentication_destroy((AUTHENTICATION_HANDLE)instance);
-			}
-		}
-	}
-	
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_020: [If any failure occurs, authentication_create() shall free any memory it allocated previously]
+            if (result == NULL)
+            {
+                authentication_destroy((AUTHENTICATION_HANDLE)instance);
+            }
+        }
+    }
+    
     return result;
 }
 
 void authentication_do_work(AUTHENTICATION_HANDLE authentication_handle)
 {
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_036: [If authentication_handle is NULL, authentication_do_work() shall fail and return]
-	if (authentication_handle == NULL)
-	{
-		LogError("authentication_do_work failed (authentication_handle is NULL)");
-	}
-	else
-	{
-		AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
-		
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_038: [If `instance->is_cbs_put_token_in_progress` is TRUE, authentication_do_work() shall only verify the authentication timeout]
-		if (instance->is_cbs_put_token_in_progress)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_084: [If no timeout has occurred, authentication_do_work() shall return]
-
-			bool is_timed_out;
-			if (verify_cbs_put_token_timeout(instance, &is_timed_out) == RESULT_OK && is_timed_out)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_085: [`instance->is_cbs_put_token_in_progress` shall be set to FALSE]
-				instance->is_cbs_put_token_in_progress = false;
-			
-				if (mark_current_device_key_as_invalid(instance))
-				{
-					// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_086: [`instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
-					update_state(instance, AUTHENTICATION_STATE_ERROR);
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_036: [If authentication_handle is NULL, authentication_do_work() shall fail and return]
+    if (authentication_handle == NULL)
+    {
+        LogError("authentication_do_work failed (authentication_handle is NULL)");
+    }
+    else
+    {
+        AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
+        
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_038: [If `instance->is_cbs_put_token_in_progress` is TRUE, authentication_do_work() shall only verify the authentication timeout]
+        if (instance->is_cbs_put_token_in_progress)
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_084: [If no timeout has occurred, authentication_do_work() shall return]
 
-					if (instance->is_sas_token_refresh_in_progress)
-					{
-						// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_087: [If `instance->is_sas_token_refresh_in_progress` is TRUE, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_SAS_REFRESH_TIMEOUT]
-						notify_error(instance, AUTHENTICATION_ERROR_SAS_REFRESH_TIMEOUT);
-					}
-					else
-					{
-						// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_088: [If `instance->is_sas_token_refresh_in_progress` is FALSE, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_AUTH_TIMEOUT]
-						notify_error(instance, AUTHENTICATION_ERROR_AUTH_TIMEOUT);
-					}
-				}
+            bool is_timed_out;
+            if (verify_cbs_put_token_timeout(instance, &is_timed_out) == RESULT_OK && is_timed_out)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_085: [`instance->is_cbs_put_token_in_progress` shall be set to FALSE]
+                instance->is_cbs_put_token_in_progress = false;
+            
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_086: [`instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
+                update_state(instance, AUTHENTICATION_STATE_ERROR);
 
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_089: [`instance->is_sas_token_refresh_in_progress` shall be set to FALSE]
-				instance->is_sas_token_refresh_in_progress = false;
-			}
-		}
-		else if (instance->state == AUTHENTICATION_STATE_STARTED)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_040: [If `instance->state` is AUTHENTICATION_STATE_STARTED and user-provided SAS token was used, authentication_do_work() shall return]
-			if (are_device_keys_used_for_authentication(instance))
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_039: [If `instance->state` is AUTHENTICATION_STATE_STARTED and device keys were used, authentication_do_work() shall only verify the SAS token refresh time]
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_065: [The SAS token shall be refreshed if the current time minus `instance->current_sas_token_put_time` equals or exceeds `instance->sas_token_refresh_time_secs`]
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_066: [If SAS token does not need to be refreshed, authentication_do_work() shall return]
-				bool is_timed_out;
-				if (verify_sas_token_refresh_timeout(instance, &is_timed_out) == RESULT_OK && is_timed_out)
-				{
-					STRING_HANDLE device_key;
-
-					// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_119: [authentication_do_work() shall set `instance->is_sas_token_refresh_in_progress` to TRUE]
-					instance->is_sas_token_refresh_in_progress = true;
+                if (instance->is_sas_token_refresh_in_progress)
+                {
+                    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_087: [If `instance->is_sas_token_refresh_in_progress` is TRUE, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_SAS_REFRESH_TIMEOUT]
+                    notify_error(instance, AUTHENTICATION_ERROR_SAS_REFRESH_TIMEOUT);
+                }
+                else
+                {
+                    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_088: [If `instance->is_sas_token_refresh_in_progress` is FALSE, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_AUTH_TIMEOUT]
+                    notify_error(instance, AUTHENTICATION_ERROR_AUTH_TIMEOUT);
+                }
 
-					// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_067: [authentication_do_work() shall create a SAS token using `instance->device_primary_key`, unless it has failed previously]
-					// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_069: [If using `instance->device_primary_key` has failed previously, a SAS token shall be created using `instance->device_secondary_key`]
-					// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_068: [If using `instance->device_primary_key` has failed previously and `instance->device_secondary_key` is not provided,  authentication_do_work() shall fail and return]
-					while ((device_key = get_current_valid_device_key(instance)) != NULL)
-					{
-						if (create_and_put_SAS_token_to_cbs(instance, device_key) == RESULT_OK)
-						{
-							break;
-						}
-						else
-						{
-							LogError("Failed refreshing SAS token (%d)", instance->current_credential_in_use);
-							(void)mark_current_device_key_as_invalid(instance);
-						}
-					}
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_089: [`instance->is_sas_token_refresh_in_progress` shall be set to FALSE]
+                instance->is_sas_token_refresh_in_progress = false;
+            }
+        }
+        else if (instance->state == AUTHENTICATION_STATE_STARTED)
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_040: [If `instance->state` is AUTHENTICATION_STATE_STARTED and user-provided SAS token was used, authentication_do_work() shall return]
+            if (IoTHubClient_Auth_Get_Credential_Type(instance->authorization_module) == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_039: [If `instance->state` is AUTHENTICATION_STATE_STARTED and device keys were used, authentication_do_work() shall only verify the SAS token refresh time]
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_065: [The SAS token shall be refreshed if the current time minus `instance->current_sas_token_put_time` equals or exceeds `instance->sas_token_refresh_time_secs`]
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_066: [If SAS token does not need to be refreshed, authentication_do_work() shall return]
+                bool is_timed_out;
+                if (verify_sas_token_refresh_timeout(instance, &is_timed_out) == RESULT_OK && is_timed_out)
+                {
+                    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_119: [authentication_do_work() shall set `instance->is_sas_token_refresh_in_progress` to TRUE]
+                    instance->is_sas_token_refresh_in_progress = true;
 
-					if (!instance->is_cbs_put_token_in_progress)
-					{
-						// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_120: [If cbs_put_token() fails, `instance->is_sas_token_refresh_in_progress` shall be set to FALSE]
-						instance->is_sas_token_refresh_in_progress = false;
+                    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_067: [authentication_do_work() shall create a SAS token using `instance->device_primary_key`, unless it has failed previously]
+                    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_069: [If using `instance->device_primary_key` has failed previously, a SAS token shall be created using `instance->device_secondary_key`]
+                    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_068: [If using `instance->device_primary_key` has failed previously and `instance->device_secondary_key` is not provided,  authentication_do_work() shall fail and return]
+                    if (create_and_put_SAS_token_to_cbs(instance) != RESULT_OK)
+                    {
+                        LogError("Failed refreshing SAS token '%'", instance->device_id);
+                    }
 
-						// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_079: [If cbs_put_token() fails, `instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
-						update_state(instance, AUTHENTICATION_STATE_ERROR);
+                    if (!instance->is_cbs_put_token_in_progress)
+                    {
+                        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_120: [If cbs_put_token() fails, `instance->is_sas_token_refresh_in_progress` shall be set to FALSE]
+                        instance->is_sas_token_refresh_in_progress = false;
 
-						// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_080: [If cbs_put_token() fails, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_SAS_REFRESH_FAILED]
-						notify_error(instance, AUTHENTICATION_ERROR_SAS_REFRESH_FAILED);
-					}
-				}
-			}
-		}
-		else if (instance->state == AUTHENTICATION_STATE_STARTING)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_041: [If `instance->device_sas_token` is provided, authentication_do_work() shall put it to CBS]
-			if (instance->device_sas_token != NULL)
-			{
-				STRING_HANDLE devices_path;
-				
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_044: [A STRING_HANDLE, referred to as `devices_path`, shall be created from the following parts: iothub_host_fqdn + "/devices/" + device_id]
-				if ((devices_path = create_devices_path(instance->iothub_host_fqdn, instance->device_id)) == NULL)
-				{
-					// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_045: [If `devices_path` failed to be created, authentication_do_work() shall set `instance->is_cbs_put_token_in_progress` to FALSE and return]
-					LogError("Failed authenticating using SAS token (create_devices_path() failed)");
-				}
-				else if (put_SAS_token_to_cbs(instance, devices_path, instance->device_sas_token) != RESULT_OK)
-				{
-					LogError("Failed authenticating using SAS token (put_SAS_token_to_cbs() failed)");
-				}
+                        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_079: [If cbs_put_token() fails, `instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
+                        update_state(instance, AUTHENTICATION_STATE_ERROR);
 
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_063: [authentication_do_work() shall free the memory it allocated for `devices_path`, `sasTokenKeyName` and SAS token]
-				STRING_delete(devices_path);
-			}
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_042: [Otherwise, authentication_do_work() shall use device keys for CBS authentication]
-			else
-			{
-				STRING_HANDLE device_key;
+                        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_080: [If cbs_put_token() fails, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_SAS_REFRESH_FAILED]
+                        notify_error(instance, AUTHENTICATION_ERROR_SAS_REFRESH_FAILED);
+                    }
+                }
+            }
+        }
+        else if (instance->state == AUTHENTICATION_STATE_STARTING)
+        {
+            if (create_and_put_SAS_token_to_cbs(instance) != RESULT_OK)
+            {
+                LogError("Failed authenticating device '%s' using device keys", instance->device_id);
+            }
 
-				while ((device_key = get_current_valid_device_key(instance)) != NULL)
-				{
-					if (create_and_put_SAS_token_to_cbs(instance, device_key) == RESULT_OK)
-					{
-						break;
-					}
-					else
-					{
-						LogError("Failed authenticating device '%s' using device keys (%d)", STRING_c_str(instance->device_id), instance->current_credential_in_use);
-						(void)mark_current_device_key_as_invalid(instance);
-					}
-				}
-			}
+            if (!instance->is_cbs_put_token_in_progress)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_061: [If cbs_put_token() fails, `instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_121: [If cbs_put_token() fails, `instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
+                update_state(instance, AUTHENTICATION_STATE_ERROR);
 
-			if (!instance->is_cbs_put_token_in_progress)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_061: [If cbs_put_token() fails, `instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_121: [If cbs_put_token() fails, `instance->state` shall be updated to AUTHENTICATION_STATE_ERROR and `instance->on_state_changed_callback` invoked]
-				update_state(instance, AUTHENTICATION_STATE_ERROR);
-
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_062: [If cbs_put_token() fails, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_AUTH_FAILED]
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_122: [If cbs_put_token() fails, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_AUTH_FAILED]
-				notify_error(instance, AUTHENTICATION_ERROR_AUTH_FAILED);
-			}
-		}
-		else
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_037: [If `instance->state` is not AUTHENTICATION_STATE_STARTING or AUTHENTICATION_STATE_STARTED, authentication_do_work() shall fail and return]
-			// Nothing to be done.
-		}
-	}
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_062: [If cbs_put_token() fails, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_AUTH_FAILED]
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_122: [If cbs_put_token() fails, `instance->on_error_callback` shall be invoked with AUTHENTICATION_ERROR_AUTH_FAILED]
+                notify_error(instance, AUTHENTICATION_ERROR_AUTH_FAILED);
+            }
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_037: [If `instance->state` is not AUTHENTICATION_STATE_STARTING or AUTHENTICATION_STATE_STARTED, authentication_do_work() shall fail and return]
+            // Nothing to be done.
+        }
+    }
 }
 
 int authentication_set_option(AUTHENTICATION_HANDLE authentication_handle, const char* name, void* value)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_097: [If `authentication_handle` or `name` or `value` is NULL, authentication_set_option shall fail and return a non-zero value]
-	if (authentication_handle == NULL || name == NULL || value == NULL)
-	{
-		LogError("authentication_set_option failed (one of the followin are NULL: authentication_handle=%p, name=%p, value=%p)", 
-			authentication_handle, name, value);
-		result = __FAILURE__;
-	}
-	else
-	{
-		AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_097: [If `authentication_handle` or `name` or `value` is NULL, authentication_set_option shall fail and return a non-zero value]
+    if (authentication_handle == NULL || name == NULL || value == NULL)
+    {
+        LogError("authentication_set_option failed (one of the followin are NULL: authentication_handle=%p, name=%p, value=%p)", 
+            authentication_handle, name, value);
+        result = __FAILURE__;
+    }
+    else
+    {
+        AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
 
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_098: [If name matches AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, `value` shall be saved on `instance->cbs_request_timeout_secs`]
-		if (strcmp(AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0)
-		{
-			instance->cbs_request_timeout_secs = *((size_t*)value);
-			result = RESULT_OK;
-		}
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_124: [If name matches AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, `value` shall be saved on `instance->sas_token_refresh_time_secs`]
-		else if (strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0)
-		{
-			instance->sas_token_refresh_time_secs = *((size_t*)value);
-			result = RESULT_OK;
-		}
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_125: [If name matches AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, `value` shall be saved on `instance->sas_token_lifetime_secs`]
-		else if (strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0)
-		{
-			instance->sas_token_lifetime_secs = *((size_t*)value);
-			result = RESULT_OK;
-		}
-		else if (strcmp(AUTHENTICATION_OPTION_SAVED_OPTIONS, name) == 0)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_098: [If name matches AUTHENTICATION_OPTION_SAVED_OPTIONS, `value` shall be applied using OptionHandler_FeedOptions]
-			if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, authentication_handle) != OPTIONHANDLER_OK)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_126: [If OptionHandler_FeedOptions fails, authentication_set_option shall fail and return a non-zero value]
-				LogError("authentication_set_option failed (OptionHandler_FeedOptions failed)");
-				result = __FAILURE__;
-			}
-			else
-			{
-				result = RESULT_OK;
-			}
-		}
-		else
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_128: [If name does not match any supported option, authentication_set_option shall fail and return a non-zero value]
-			LogError("authentication_set_option failed (option with name '%s' is not suppported)", name);
-			result = __FAILURE__;
-		}
-	}
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_098: [If name matches AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, `value` shall be saved on `instance->cbs_request_timeout_secs`]
+        if (strcmp(AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, name) == 0)
+        {
+            instance->cbs_request_timeout_secs = *((size_t*)value);
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_124: [If name matches AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, `value` shall be saved on `instance->sas_token_refresh_time_secs`]
+        else if (strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, name) == 0)
+        {
+            instance->sas_token_refresh_time_secs = *((size_t*)value);
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_125: [If name matches AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, `value` shall be saved on `instance->sas_token_lifetime_secs`]
+        else if (strcmp(AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, name) == 0)
+        {
+            instance->sas_token_lifetime_secs = *((size_t*)value);
+            result = RESULT_OK;
+        }
+        else if (strcmp(AUTHENTICATION_OPTION_SAVED_OPTIONS, name) == 0)
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_098: [If name matches AUTHENTICATION_OPTION_SAVED_OPTIONS, `value` shall be applied using OptionHandler_FeedOptions]
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, authentication_handle) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_126: [If OptionHandler_FeedOptions fails, authentication_set_option shall fail and return a non-zero value]
+                LogError("authentication_set_option failed (OptionHandler_FeedOptions failed)");
+                result = __FAILURE__;
+            }
+            else
+            {
+                result = RESULT_OK;
+            }
+        }
+        else
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_128: [If name does not match any supported option, authentication_set_option shall fail and return a non-zero value]
+            LogError("authentication_set_option failed (option with name '%s' is not suppported)", name);
+            result = __FAILURE__;
+        }
+    }
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_099: [If no errors occur, authentication_set_option shall return 0]
-	return result;
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_099: [If no errors occur, authentication_set_option shall return 0]
+    return result;
 }
 
 OPTIONHANDLER_HANDLE authentication_retrieve_options(AUTHENTICATION_HANDLE authentication_handle)
 {
-	OPTIONHANDLER_HANDLE result;
+    OPTIONHANDLER_HANDLE result;
 
-	// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_100: [If `authentication_handle` is NULL, authentication_retrieve_options shall fail and return NULL]
-	if (authentication_handle == NULL)
-	{
-		LogError("Failed to retrieve options from authentication instance (authentication_handle is NULL)");
-		result = NULL;
-	}
-	else
-	{
-		// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_101: [An OPTIONHANDLER_HANDLE instance shall be created using OptionHandler_Create]
-		OPTIONHANDLER_HANDLE options = OptionHandler_Create(authentication_clone_option, authentication_destroy_option, (pfSetOption)authentication_set_option);
+    // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_100: [If `authentication_handle` is NULL, authentication_retrieve_options shall fail and return NULL]
+    if (authentication_handle == NULL)
+    {
+        LogError("Failed to retrieve options from authentication instance (authentication_handle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_101: [An OPTIONHANDLER_HANDLE instance shall be created using OptionHandler_Create]
+        OPTIONHANDLER_HANDLE options = OptionHandler_Create(authentication_clone_option, authentication_destroy_option, (pfSetOption)authentication_set_option);
 
-		if (options == NULL)
-		{
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_102: [If an OPTIONHANDLER_HANDLE instance fails to be created, authentication_retrieve_options shall fail and return NULL]
-			LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed)");
-			result = NULL;
-		}
-		else
-		{
-			AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
+        if (options == NULL)
+        {
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_102: [If an OPTIONHANDLER_HANDLE instance fails to be created, authentication_retrieve_options shall fail and return NULL]
+            LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed)");
+            result = NULL;
+        }
+        else
+        {
+            AUTHENTICATION_INSTANCE* instance = (AUTHENTICATION_INSTANCE*)authentication_handle;
 
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_103: [Each option of `instance` shall be added to the OPTIONHANDLER_HANDLE instance using OptionHandler_AddOption]
-			// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_104: [If OptionHandler_AddOption fails, authentication_retrieve_options shall fail and return NULL]
-			if (OptionHandler_AddOption(options, AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, (void*)&instance->cbs_request_timeout_secs) != OPTIONHANDLER_OK)
-			{
-				LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed for option '%s')", AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS);
-				result = NULL;
-			}
-			else if (OptionHandler_AddOption(options, AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, (void*)&instance->sas_token_refresh_time_secs) != OPTIONHANDLER_OK)
-			{
-				LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed for option '%s')", AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS);
-				result = NULL;
-			}
-			else if (OptionHandler_AddOption(options, AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, (void*)&instance->sas_token_lifetime_secs) != OPTIONHANDLER_OK)
-			{
-				LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed for option '%s')", AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS);
-				result = NULL;
-			}
-			else
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_127: [If no failures occur, authentication_retrieve_options shall return the OPTIONHANDLER_HANDLE instance]
-				result = options;
-			}
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_103: [Each option of `instance` shall be added to the OPTIONHANDLER_HANDLE instance using OptionHandler_AddOption]
+            // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_104: [If OptionHandler_AddOption fails, authentication_retrieve_options shall fail and return NULL]
+            if (OptionHandler_AddOption(options, AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS, (void*)&instance->cbs_request_timeout_secs) != OPTIONHANDLER_OK)
+            {
+                LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed for option '%s')", AUTHENTICATION_OPTION_CBS_REQUEST_TIMEOUT_SECS);
+                result = NULL;
+            }
+            else if (OptionHandler_AddOption(options, AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS, (void*)&instance->sas_token_refresh_time_secs) != OPTIONHANDLER_OK)
+            {
+                LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed for option '%s')", AUTHENTICATION_OPTION_SAS_TOKEN_REFRESH_TIME_SECS);
+                result = NULL;
+            }
+            else if (OptionHandler_AddOption(options, AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS, (void*)&instance->sas_token_lifetime_secs) != OPTIONHANDLER_OK)
+            {
+                LogError("Failed to retrieve options from authentication instance (OptionHandler_Create failed for option '%s')", AUTHENTICATION_OPTION_SAS_TOKEN_LIFETIME_SECS);
+                result = NULL;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_127: [If no failures occur, authentication_retrieve_options shall return the OPTIONHANDLER_HANDLE instance]
+                result = options;
+            }
 
-			if (result == NULL)
-			{
-				// Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_105: [If authentication_retrieve_options fails, any allocated memory shall be freed]
-				OptionHandler_Destroy(options);
-			}
-		}
-	}
-
-	return result;
+            if (result == NULL)
+            {
+                // Codes_SRS_IOTHUBTRANSPORT_AMQP_AUTH_09_105: [If authentication_retrieve_options fails, any allocated memory shall be freed]
+                OptionHandler_Destroy(options);
+            }
+        }
+    }
+    return result;
 }