Proxy is not respected
I followed the steps here and its not using the proxy at all. My requests just time out: https://learn.microsoft.com/en-us/graph/sdks/customize-client?tabs=python#configuring-the-http-proxy-for-the-client
While normal requests using httx work, the requests to Azure do not. I'm guessing that this new client is not accepted somewhere down the chain
import asyncio
from azure.identity.aio import ClientSecretCredential
from django.conf import settings
from httpx import AsyncClient
from kiota_authentication_azure.azure_identity_authentication_provider import (
AzureIdentityAuthenticationProvider,
)
from msgraph import GraphRequestAdapter, GraphServiceClient
from msgraph.generated.users.users_request_builder import UsersRequestBuilder
from msgraph_core import GraphClientFactory
def get_azure_client() -> tuple[GraphServiceClient, AsyncClient]:
credential = ClientSecretCredential(
settings.AZURE_TENANT_ID, settings.AZURE_CLIENT_ID, settings.AZURE_CLIENT_SECRET # type: ignore
)
auth_provider = AzureIdentityAuthenticationProvider(
credential, scopes=["https://graph.microsoft.com/.default"]
)
# see: https://learn.microsoft.com/en-us/graph/sdks/customize-client?tabs=python#configuring-the-http-proxy-for-the-client
httpx_proxies = {
"http://": settings.INTERNET_PROXY,
"https://": settings.INTERNET_PROXY,
}
http_client = AsyncClient(proxies=httpx_proxies) # type: ignore
http_client = GraphClientFactory.create_with_default_middleware(client=http_client)
adapter = GraphRequestAdapter(auth_provider, http_client)
return GraphServiceClient(request_adapter=adapter), http_client
async def amain() -> None:
client, http_client = get_azure_client()
await http_client.get("https://microsoft.com") # this works
await client.groups.by_group_id( # this times out
settings.AZURE_GROUP_ID
).transitive_members.get()
if __name__ == "__main__":
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(amain())
except KeyboardInterrupt:
pass
/cc @nejch
Can you confirm if attempting to disable ssl verification via this approach is also a symptom of this problem?
from msgraph import GraphRequestAdapter
from msgraph_core import GraphClientFactory
http_client = GraphClientFactory.create_with_default_middleware(client=httpx.AsyncClient(verify=False))
request_adapter = GraphRequestAdapter(auth_provider, http_client)
client = GraphServiceClient(request_adapter=request_adapter)
gives error of:
ClientSecretCredential.get_token failed: Cannot connect to host login.microsoftonline.com:443 ssl:True [SSLCertVerificationError: (5, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1006)')]
---------------------------------------------------------------------------
SSLCertVerificationError Traceback (most recent call last)
File /opt/conda/lib/python3.11/site-packages/aiohttp/connector.py:992, in TCPConnector._wrap_create_connection(self, req, timeout, client_error, *args, **kwargs)
989 async with ceil_timeout(
990 timeout.sock_connect, ceil_threshold=timeout.ceil_threshold
991 ):
--> 992 return await self._loop.create_connection(*args, **kwargs)
993 except cert_errors as exc:
Update: A total hack to get around it, for those who can do this - find the aiohttp python module connector.py, and find where the default value for verify_ssl is set to True, and simply set it to false. Works for me, as I have nothing else doing aio.
Hey there; ran into the same issue these past few days.
What solved it for us was specifying proxies=proxies in the Credential class, as per the tutorial:
# Proxy URLs
proxies = {
'http': 'http://proxy-url',
'https': 'http://proxy-url',
}
# Create a token credential with the proxies. It can be any
# of the credential classes from azure.identity
credential = DeviceCodeCredential(
"client_id", tenant_id = "tenant_id", proxies = proxies)
FYI, in our case we are using CertificateCredential class, but it shouldn't change much.
It seems that this proxies parameter is passed through **kwargs in the Credential parent class, MsalCredential from azure.identity. The furthest I got is here, where a proxies keyword argument can be accepted.
Both proxies parameters are needed. Using only the proxies=proxies argument (without building httpx_proxies in a specific request adapter) does not work. Not specifying proxies=proxies in the Credential class arguments does not work for me either (as shown in your case).
Since proxies & httpx_proxies are different objects, it seems HTTPX is used in the msgraph library (which needs httpx_proxies), and another adapter is used in azure.identity (which need the proxies parameter).
Thanks a lot for sharing @nitneuqr, we just tested your solution and it also works for us. 🙏🏻
Our currently-working solution (a bit anonymized) with ClientSecretCredential is the following:
proxies = {
"http": "http://proxy-url",
"https": "http://proxy-url",
"no_proxy": "no-proxy.com",
}
credential = ClientSecretCredential("tenant_id", "client_id", "client_secret", proxies=proxies )
auth_provider = AzureIdentityAuthenticationProvider(credential, scopes=["https://graph.microsoft.com/.default"])
httpx_proxies = {
"http://": "http://proxy-url",
"https://": "http://proxy-url",
}
http_client = AsyncClient(proxies=httpx_proxies, timeout=300)
/cc @max-wittig