Azure / Azure/azure-sdk-for-python
[Bug]: `ServiceRequestError` due to `SSLCertVerificationError` when using `azure-communication-chat` (async)
- Dominant language
- Python
- Stars
- 5.6k
- Forks
- 3.4k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 193
Description
### Description
I am encountering a `ServiceRequestError` when attempting to make any asynchronous API call (specifically `create_chat_thread`) using the `azure-communication-chat` SDK. The underlying error is an `SSLCertVerificationError` which indicates an issue with SSL certificate chain verification, specifically citing a **"self-signed certificate in certificate chain"**.
This suggests that the environment where the code is running (potentially an enterprise network or machine with security tools) is injecting an intermediate self-signed certificate into the SSL handshake, and the Python environment's SSL library is failing to validate it against the trusted root CAs.
The error chain leads to:
`aiohttp.client_exceptions.ClientConnectorCertificateError` $\rightarrow$ `ssl.SSLCertVerificationError` $\rightarrow$ `azure.core.exceptions.ServiceRequestError`.
It appears that the **Azure Core aiohttp transport** does not currently provide a clear or convenient way to pass custom **SSL context arguments** (like a custom CA bundle or disabling verification) to the underlying `aiohttp.ClientSession` or the `aiohttp.connector`, which is necessary to resolve this common corporate network issue.
### Reproduction Steps
1. Set up a Python environment with **Python 3.13** (based on the traceback) and the required Azure Communication Services and Core libraries (`azure-communication-chat`, `azure-core`).
2. Run an asynchronous Python script that attempts to instantiate the `ChatClient` and make an API call (e.g., `await chat_client.create_chat_thread(...)`).
3. Ensure the execution environment is behind a network proxy or security tool that implements **SSL Inspection/Man-in-the-Middle** by injecting a self-signed certificate into the SSL chain.
4. Observe the application fail with the traceback below.
### Expected Behavior
The `ChatClient` or the underlying `azure-core` pipeline should allow the user to provide an optional parameter (e.g., `verify=False` or `ssl_context=...`) in the client constructor to manage SSL verification, especially for aiohttp. This is a common requirement for enterprise environments.
### Actual Behavior
The operation fails with an `azure.core.exceptions.ServiceRequestError` due to `SSLCertVerificationError`.
### Traceback
```
Traceback (most recent call last):
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/connector.py", line 1283, in _wrap_create_connection
return await self._loop.create_connection(*args, **kwargs, sock=sock)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 1193, in create_connection
transport, protocol = await self._create_connection_transport(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<2 lines>...
ssl_shutdown_timeout=ssl_shutdown_timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 1226, in _create_connection_transport
await waiter
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/sslproto.py", line 581, in _on_handshake_complete
raise handshake_exc
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/sslproto.py", line 563, in _do_handshake
self._sslobj.do_handshake()
~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/ssl.py", line 951, in do_handshake
self._sslobj.do_handshake()
~~~~~~~~~~~~~~~~~~~~~~~~~^^
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1028)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/transport/_aiohttp.py", line 346, in send
result = await self.session.request( # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<8 lines>...
)
^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/client.py", line 779, in _request
resp = await handler(req)
^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/client.py", line 734, in _connect_and_send_request
conn = await self._connector.connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
req, traces=traces, timeout=real_timeout
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/connector.py", line 642, in connect
proto = await self._create_connection(req, traces, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/connector.py", line 1209, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/connector.py", line 1581, in _create_direct_connection
raise last_exc
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/connector.py", line 1550, in _create_direct_connection
transp, proto = await self._wrap_create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<7 lines>...
)
^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/aiohttp/connector.py", line 1285, in _wrap_create_connection
raise ClientConnectorCertificateError(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host rohicommunicationservice.africa.communication.azure.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1028)')]
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/chat_client_sample_async.py", line 159, in
asyncio.run(main())
~~~~~~~~~~~^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 195, in run
return runner.run(main)
~~~~~~~~~~^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/chat_client_sample_async.py", line 152, in main
await sample.create_thread_async()
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/chat_client_sample_async.py", line 76, in create_thread_async
create_chat_thread_result = await chat_client.create_chat_thread(topic, thread_participants=participants)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/tracing/decorator_async.py", line 119, in wrapper_use_tracer
return await func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/communication/chat/aio/_chat_client_async.py", line 166, in create_chat_thread
create_chat_thread_result = await self._client.chat.create_chat_thread(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<2 lines>...
**kwargs)
^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/tracing/decorator_async.py", line 119, in wrapper_use_tracer
return await func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/communication/chat/_generated/aio/operations/_chat_operations.py", line 197, in create_chat_thread
pipeline_response: PipelineResponse = await self._client._pipeline.run( # pylint: disable=protected-access
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_request, stream=_stream, **kwargs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 229, in run
return await first_node.send(pipeline_request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Previous line repeated 2 more times]
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/policies/_redirect_async.py", line 76, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/policies/_retry_async.py", line 204, in send
raise err
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/policies/_retry_async.py", line 178, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/policies/_authentication_async.py", line 105, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 77, in send
response = await self.next.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Previous line repeated 2 more times]
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/_base_async.py", line 111, in send
await self._sender.send(request.http_request, **request.context.options),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rohiogula/DDI/acs/access-tokens-quickstart/.venv/lib/python3.13/site-packages/azure/core/pipeline/transport/_aiohttp.py", line 393, in send
raise ServiceRequestError(err, error=err) from err
azure.core.exceptions.ServiceRequestError: Cannot connect to host rohicommunicationservice.africa.communication.azure.com:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1028)')]
```
### Environment
* **SDK Package Name:** `azure-communication-chat`
* **SDK Package Version:** `1.3.0`
* **Python Version:** 3.13.0
* **Operating System:** macOS
* **AIOHTTP Version:** `3.13.2`
Contributor guide
Assessment
This issue has not been assessed yet.