I have created some Azure function apps and imported them to APIM, where they work fine. But I have a problem with some APIs that use certificate authentication. When I access the APIM Developer Portal for the first time and try to test an API that does not need a certificate, the browser still asks me to select a certificate.
is this is expected scenario?
Inbound policy of API that have certificate authentication:
<inbound>
<base />
<choose>
<when condition="@(context.Request.Certificate == null || !context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint))">
<return-response>
<set-status code="403" reason="Invalid client certificate" />
</return-response>
</when>
<otherwise />
</choose>
<authentication-certificate certificate-id="DevCert" />
<set-backend-service id="apim-generated-policy" backend-id="sample-func" />
</inbound>
Inbound policy of API that DOES NOT HAVE certificate authentication:
<inbound>
<base />
<set-backend-service id="apim-generated-policy" backend-id="sample-func" />
</inbound>
2
Answers
No, this is not the expected case. You shouldn’t get the option to select the certificate for the API which is not having
authentication-certificate
policy in it unless you have added the policy in global level or in product level and have attached that product to the API.I have imported an Azure function to the APIM instance and it is having two operations(GET, POST) in it.
Policy of GET operation looks like below-
Policy of POST operation looks like below-
Then I published the developer portal and trying to access these operations.
GET Operation–
POST Operation–
Not being asked to select the certificate even if I am trying to access the Post operation prior.
Verify your policies and publish the developer portal after making the changes.
This is normal browser behavior when mutual authentication is involved, and is not APIM specific. Client certificate can either be provided at the time connection is created or later during re-negotiation process when server requests one. But in both cases it is common browser behavior to prompt user for a certificate while still allowing to press Cancel and provide none.
There are two places in APIM where you can control this behavior, first is in custom hostname properties where you can check "Negotiate client certificate" option. If checked it will prompt client for certificate whenever new connection is being established to make a request. Probably not what you want.
Second option is to read
context.Request.Certificate
. If referenced in policy expressions this triggers re-negotiation process and will request certificate from client, which browsers would treat by showing corresponding UI. Unfortunately there is nothing in protocol that would indicate upfront that client does not have a certificate and would prevent browser from showing selection UX.In both cases this happens only once per connection as browsers generally maintain connections to websites to future requests and also remember your certificate choise for the duration of client session.
The only way to avoid it would be to make sure that "Negotiate client certificate" option is disabled on your hostname (including default one), and to make sure you only read
context.Request.Certificate
only when necessary. One way to do this is to wrap yourchoose
policy with another one to make sure thatcontext.Request.Certificate
is referenced only when necessary, i.e. if call is made to specific API, or over specific domain, or not made from Developer portal. For the latter you can do something like below: