Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

device client register method fails with CredentialError caused by UnauthorizedError when attempting to connect to a device on iot central using python sdk. #709

Closed
avwater opened this issue Nov 17, 2020 · 12 comments

Comments

@avwater
Copy link

avwater commented Nov 17, 2020

Context

  • OS and version used: Linux 4.19.0-xilinx-v2019.2 on PicoZed
  • Python version: Python 3.7.8
  • pip version: pip 19.2.3
  • list of installed packages: azure-iot-device 2.4.0
  • cloned repo: NA

Description of the issue

We are attempting to check if we can push telemetry data onto a device created in Azure IoT Central by following the tutorial:

https://docs.microsoft.com/en-us/azure/iot-central/core/tutorial-connect-device-python

On running the environmental_sensor.py that we created, we were hit with the following message:

# python3 env_sensor.py
 Device could not connect

We then modified the script to be a sync version of the same using:

https://github.com/Azure/azure-iot-sdk-python/blob/master/azure-iot-device/samples/sync-samples/provision_symmetric_key.py
as reference.

Upon running the environmental_sensor.py, we encountered the following error:

azure.iot.device.exceptions.CredentialError: CredentialError('Credentials invalid, could not connect') caused by UnauthorizedError('Connection Refused: not authorised.')

Code sample exhibiting the issue

Here's the modified script that we used. All it does is register, connect and attempt to send telemetry every 5s - synchronously.

sync_env_sensor.txt

Console log of the issue

~# python3 sync_env_sensor.py
 Traceback (most recent call last):
   File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 25, in handle_result
     return callback.wait_for_completion()
   File "/usr/lib/python3.7/site-packages/azure/iot/device/common/evented_callback.py", line 70, in wait_for_completion
     raise self.exception
 azure.iot.device.common.transport_exceptions.UnauthorizedError: UnauthorizedError('Connection Refused: not authorised.')
    
 The above exception was the direct cause of the following exception:
    
 Traceback (most recent call last):
   File "sync_env_sensor.py", line 25, in <module>
     registration_result = provisioning_device_client.register()
   File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 73, in register
     self._enable_responses()
   File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 96, in _enable_responses
     handle_result(subscription_complete)
   File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 35, in handle_result
     raise exceptions.CredentialError(message="Credentials invalid, could not connect", cause=e)
 azure.iot.device.exceptions.CredentialError: CredentialError('Credentials invalid, could not connect') caused by UnauthorizedError('Connection Refused: not authorised.')

This issue has also been raised @ https://docs.microsoft.com/en-us/answers/questions/154410/device-client-register-method-fails-with-credentia.html

Any help will be greatly appreciated.

AB#8828384

@avwater avwater added the bug label Nov 17, 2020
@olivakar
Copy link
Collaborator

olivakar commented Nov 17, 2020

The error message that you have received seems to be pointing to one of the 4 values to be wrong.

    provisioning_host = 'global.azure-devices-provisioning.net'
    id_scope = '{your Scope ID}'
    registration_id = '{your registration id}'
    symmetric_key = '{your Primary Key}'

if you are creating your own device enrollment on the portal (which you can to test it out to see if that works) please follow this
page

The registration id is by default is the device id unless you have chosen those 2 to be different. So please make sure that you are using the correct registration id.

And you can also increase your logging level to DEBUG if following the above page still does not work.

@avwater
Copy link
Author

avwater commented Nov 18, 2020

@olivakar, I have used the appropriate values for the registration and connection - with registration_id being the unique device ID as seen in the device connection screen below:

device_connection

I still am facing the same issue.

PS: How does one go about increasing the logging level to DEBUG?

@olivakar
Copy link
Collaborator

olivakar commented Nov 18, 2020

In your python code :-

logging.basicConfig(level=logging.DEBUG)

Additionally if you want to save to a file also add another kwarg filename="example.log"

Did you try creating a symmetric key individual enrollment record directly on the portal and then trying out the provisioning sample ? I just did with a new enrollment record and everything was fine.

If you are able to do that successfully using the same sync sample you should see your enrollment record updated with registration info like this.

registration success

@avwater
Copy link
Author

avwater commented Nov 18, 2020

Thanks @olivakar. As I mentioned earlier, we are creating/managing devices on Azure IoT Central. Refer:

https://docs.microsoft.com/en-us/azure/iot-central/core/tutorial-connect-device-python

We currently don't make use of the Azure IoT Hub service (directly, although I believe Azure IoT Central has it integrated).

Here's what we have done - created a device template and then a corresponding device. Applied the device connection information into our python script (provisioning_host, id_scope, registration_id, symmetric_key) and then run the script to be able to register with and connect to the device instance created to push telemetry data.

The only difference between the sample app in the reference and what we have used is that we have modified it to be synchronous using an example available in the azure-iot-sdk-python specifically this.

Here's the console log after logging level at DEBUG (based on the changes suggested by you to this effect):

# python3 sync_env_sensor.py
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Starting run_op in pipeline thread
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Creating pipeline executor
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:Scheduling SAS Token renewal for 3480 seconds in the future
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_mqtt:Gateway Hostname not present. Setting Hostname to: global.azure-devices-provisioning.net
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_mqtt:MQTTTransportStage(InitializePipelineOperation): got connection args
DEBUG:azure.iot.device.common.mqtt_transport:creating mqtt client
INFO:azure.iot.device.common.mqtt_transport:Creating client for connecting using MQTT over TCP
DEBUG:azure.iot.device.common.mqtt_transport:creating a SSL context
DEBUG:azure.iot.device.common.mqtt_transport:configuring SSL context with default certs
DEBUG:azure.iot.device.common.mqtt_transport:Created MQTT protocol client, assigned callbacks
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:InitializePipelineOperation: completing without error
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Starting <azure.iot.device.common.evented_callback.EventedCallback object at 0xb5f2c5f0> in callback thread
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Creating callback executor
DEBUG:azure.iot.device.common.evented_callback:Callback completed with result None
INFO:azure.iot.device.provisioning.provisioning_device_client:Registering with Provisioning Service...
INFO:azure.iot.device.provisioning.provisioning_device_client:Enabling reception of response from Device Provisioning Service...
DEBUG:azure.iot.device.provisioning.pipeline.mqtt_pipeline:enable_responses called
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Starting run_op in pipeline thread
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:EnableFeatureOperation: creating worker op of type MQTTSubscribeOperation
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:AutoConnectStage(MQTTSubscribeOperation): Op needs connection.  Queueing this op and starting a ConnectionOperation
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:AutoConnectStage(MQTTSubscribeOperation): calling down with Connect operation
INFO:azure.iot.device.common.pipeline.pipeline_stages_base:ReconnectStage(ConnectOperation): State changes LOGICALLY_DISCONNECTED->LOGICALLY_CONNECTED.  Adding to wait list and sending new connect op down
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ReconnectStage: sending new connect op down
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ConnectionLockStage(ConnectOperation): blocking
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_mqtt:MQTTTransportStage(ConnectOperation): connecting
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_mqtt:MQTTTransportStage(ConnectOperation): Starting watchdog
DEBUG:azure.iot.device.common.mqtt_transport:connecting to mqtt broker
INFO:azure.iot.device.common.mqtt_transport:Connect using port 8883 (TCP)
DEBUG:paho:Sending CONNECT (u1, p1, wr0, wq0, wf0, c0, k60) client_id=b'1uwj4ak5wit'
DEBUG:azure.iot.device.common.mqtt_transport:_mqtt_client.connect returned rc=0
DEBUG:paho:Received CONNACK (0, 5)
INFO:azure.iot.device.common.mqtt_transport:connected with result code: 5
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Starting _on_mqtt_connection_failure in pipeline thread
INFO:azure.iot.device.common.pipeline.pipeline_stages_mqtt:MQTTTransportStage: _on_mqtt_connection_failure called: UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_mqtt:MQTTTransportStage: failing connect op
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_mqtt:MQTTTransportStage(ConnectOperation): cancelling watchdog
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:ConnectOperation: completing with error UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ConnectionLockStage(ConnectOperation): op failed.  Unblocking queue with error: UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ConnectionLockStage(ConnectOperation): unblocking and releasing queued ops.
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ConnectionLockStage(ConnectOperation): processing 0 items in queue for error=UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ReconnectStage(ConnectOperation): on_connect_complete error=UnauthorizedError('Connection Refused: not authorised.') state=LOGICALLY_CONNECTED never_connected=True connected=False
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:ReconnectStage: completing waiting ops with error=UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:ConnectOperation: completing with error UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_stages_base:AutoConnectStage(MQTTSubscribeOperation): Connection failed.  Completing with failure because of connection failure: UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:MQTTSubscribeOperation: completing with error UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:EnableFeatureOperation: Worker op (MQTTSubscribeOperation) has been completed
DEBUG:azure.iot.device.common.pipeline.pipeline_ops_base:EnableFeatureOperation: completing with error UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Starting pipeline_callback in callback thread
INFO:azure.iot.device.common.mqtt_transport:disconnected with result code: 5
INFO:azure.iot.device.common.evented_callback:Callback completed with error UnauthorizedError('Connection Refused: not authorised.')
INFO:azure.iot.device.common.evented_callback:NoneType: None

Traceback (most recent call last):
  File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 25, in handle_result
    return callback.wait_for_completion()
  File "/usr/lib/python3.7/site-packages/azure/iot/device/common/evented_callback.py", line 70, in wait_for_completion
    raise self.exception
azure.iot.device.common.transport_exceptions.UnauthorizedError: UnauthorizedError('Connection Refused: not authorised.')

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "sync_env_sensor.py", line 29, in <module>
    registration_result = provisioning_device_client.register()
  File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 73, in register
    self._enable_responses()
  File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 96, in _enable_responses
    handle_result(subscription_complete)
  File "/usr/lib/python3.7/site-packages/azure/iot/device/provisioning/provisioning_device_client.py", line 35, in handle_result
    raise exceptions.CredentialError(message="Credentials invalid, could not connect", cause=e)
azure.iot.device.exceptions.CredentialError: CredentialError('Credentials invalid, could not connect') caused by UnauthorizedError('Connection Refused: not authorised.')
DEBUG:azure.iot.device.common.mqtt_transport:  File "/usr/lib/python3.7/threading.py", line 890, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib/python3.7/threading.py", line 926, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.7/site-packages/paho/mqtt/client.py", line 2913, in _thread_main
    self.loop_forever(retry_first_connection=True)
  File "/usr/lib/python3.7/site-packages/paho/mqtt/client.py", line 1578, in loop_forever
    rc = self.loop(timeout, max_packets)
  File "/usr/lib/python3.7/site-packages/paho/mqtt/client.py", line 1072, in loop
    rc = self.loop_read(max_packets)
  File "/usr/lib/python3.7/site-packages/paho/mqtt/client.py", line 1376, in loop_read
    return self._loop_rc_handle(rc)
  File "/usr/lib/python3.7/site-packages/paho/mqtt/client.py", line 1991, in _loop_rc_handle
    self.on_disconnect(self, self._userdata, rc)
  File "/usr/lib/python3.7/site-packages/azure/iot/device/common/mqtt_transport.py", line 210, in on_disconnect
    logger.debug("".join(traceback.format_stack()))

INFO:azure.iot.device.common.mqtt_transport:Forcing paho disconnect to prevent it from automatically reconnecting
DEBUG:azure.iot.device.common.mqtt_transport:in paho thread.  nulling _thread
DEBUG:azure.iot.device.common.mqtt_transport:Done forcing paho disconnect
DEBUG:azure.iot.device.common.pipeline.pipeline_thread:Starting _on_mqtt_disconnected in pipeline thread
ERROR:azure.iot.device.common.mqtt_transport:Unexpected error calling on_mqtt_disconnected_handler

@olivakar
Copy link
Collaborator

olivakar commented Nov 19, 2020

I was able to follow the steps in the tutorial and create device, provision device and also send telemetry.
What is the value of your provisioning_host ?

@avwater
Copy link
Author

avwater commented Nov 19, 2020

The provisioning host is set to 'global.azure-devices-provisioning.net' as suggested in the tutorial.
I have verified the 4 variables necessary for registration/connection - we are setting them to the values provided in the device connection screen (in Azure IoT Central).

@elhorton
Copy link
Contributor

Hi @avwater , unfortunately we are unable to repro this issue with the tutorial. We will work with Satish (from your Microsoft Q&A post) to communicate with you and find a root cause. For now, let's use that channel. We'll leave this open in the meantime and return to it when we have a solution.

@elhorton
Copy link
Contributor

Closing this issue as it was resolved on a separate thread. Please reopen if there are still issues, thank you!

@az-iot-builder-01
Copy link
Collaborator

@avwater, thank you for your contribution to our open-sourced project! Please help us improve by filling out this 2-minute customer satisfaction survey

@kodonnell
Copy link

Closing this issue as it was resolved on a separate thread. Please reopen if there are still issues, thank you!

Can you please post the resolution or a link to the thread? I've just followed the tutorial (running python3.7 in WSL) and am having the same issue.

@kodonnell
Copy link

running python3.7 in WSL

For anyone else - the exact same code (with hardcoded parameters) works in Windows command prompt, and not Ubuntu WSL. Should I file this as a bug or is it a know issue @olivakar ?

@elhorton
Copy link
Contributor

@kodonnell , thanks for following up on this! Could you please file the issue with WSL? that is not a known bug to my knowledge, and we will coordinate with the IoT Central team. The initial resolution was having the appropriate roles set (need to be an application Administrator), but it sounds like your issue may be different.

Here's a verbatim explanation for this issue:

_To access and use the Administration section, you must be in the Administrator role for an Azure IoT Central application. If you create an Azure IoT Central application, you're automatically added to the Administrator role for that application. For more information, see Manage users and roles in Azure IoT Central application.

You can either create your own IoT Central application for testing and to run the tutorial, in which case you'll be in Administrator role automatically. Or, you can ask someone who is in the Administrator role for your application to retrieve the group SAS key for you._

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants