I'm trying to verify Client Certificates in Azure API Management. I created a new instance and I'm using the default Echo API. I followed this documentation https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-mutual-certificates-for-clients and this one for testing with Postman https://medium.com/@jkewley/testing-client-certificate-authentication-to-azure-api-management-with-postman-e1cfae52fc35
I'm using the following Policy in the Echo API All operations Inbound just checking if any certificate is present:
<policies>
<inbound>
<choose>
<when condition="@(context.Request.Certificate == null)">
<return-response>
<set-status code="403" reason="Missing client certificate" />
</return-response>
</when>
</choose>
<base />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
In the Custom Domains tab, I have my Endpoint Gateway with Negotiate client certificate and Default SSL binding enabled.
When testing without the policy it works fine. With the policy, I get "403 - Missing client certificate".
My PostMan logs show my local pfx file being sent. I have used that same CA certificate successfully with an Apigee setup that I'm trying to replicate.
The APIM Trace shows no sign of that certificate
{
"traceId": "1e2950a4-7ae9-4489-9175-dd6b7a8e6872",
"traceEntries": {
"inbound": [
{
"source": "api-inspector",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0002376",
"data": {
"request": {
"method": "POST",
"url": "https://xxxxxx-poc-apim.azure-api.net/echo/resource",
"headers": [
{
"name": "Ocp-Apim-Subscription-Key",
"value": "20c7x7x22xa5xdxc8a1x857bb651000a"
},
{
"name": "X-Forwarded-For",
"value": "76.98.XX.XXX"
},
{
"name": "Connection",
"value": "keep-alive"
},
{
"name": "Content-Length",
"value": "102"
},
{
"name": "Content-Type",
"value": "text/plain"
},
{
"name": "Accept",
"value": "*/*"
},
{
"name": "Accept-Encoding",
"value": "gzip,deflate,br"
},
{
"name": "Host",
"value": "xxxxxxx-poc-apim.azure-api.net"
},
{
"name": "User-Agent",
"value": "PostmanRuntime/7.26.10"
}
]
}
}
},
{
"source": "api-inspector",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0002401",
"data": {
"configuration": {
"api": {
"from": "/echo",
"to": {
"scheme": "http",
"host": "echoapi.cloudapp.net",
"port": 80,
"path": "/api",
"queryString": "",
"query": {
},
"isDefaultPort": true
},
"version": null,
"revision": "1"
},
"operation": {
"method": "POST",
"uriTemplate": "/resource"
},
"user": "-",
"product": "-"
}
}
},
{
"source": "cors",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0002602",
"data": "Origin header was missing or empty and the request was classified as not cross-domain. CORS policy was not applied."
},
{
"source": "choose",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0002753",
"data": {
"message": "Expression was successfully evaluated.",
"expression": "context.Request.Certificate == null",
"value": true
}
},
{
"source": "set-status",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0002817",
"data": {
"message": [
"Response status code was set to 403",
"Response status reason was set to 'Missing client certificate'"
]
}
},
{
"source": "return-response",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0002863",
"data": {
"message": "Return response was applied",
"response": {
"status": {
"code": "Forbidden",
"reason": "Missing client certificate"
},
"headers": [
]
}
}
}
],
"outbound": [
{
"source": "transfer-response",
"timestamp": "2021-03-08T16:45:36.1300291Z",
"elapsed": "00:00:00.0003120",
"data": {
"message": "Response headers have been sent to the caller."
}
}
]
}
}
I have tried a lot of things. I tried using SoapUI instead of Postman I try with another CA certificate. I tried on another APIM that has a CA certificate but is behind an App Gateway. Always the same result. I'm out of ideas.