I currently have the below policy which validates the certificate thumbprint against "any" certificate uploaded to API Management:
<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>
</choose>
But I want to validate a thumbprint against a "specific" certificate uploaded to API Management, not "any".
I have tried the below policy:
<choose>
<when condition="@(context.Request.Certificate == null || context.Deployment.Certificates["MyCert"].Thumbprint == context.Request.Certificate.Thumbprint)">
<return-response>
<set-status code="403" reason="Invalid client certificate"/>
</return-response>
</when>
</choose>
"MyCert" is the "Id" of the "Client Certificate" in API which refers to the certificate uploaded in Key Vault.
But when I call the API, it throws this error: Expression evaluation failed. The given key 'MyCert' was not present in the dictionary. at System.Collections.Immutable.ImmutableDictionary`2.get_Item(TKey key)
Can someone please help me with this issue?
context.Deployment.Certificates.Values
doesn't contain Certificate Id parameter to filter. You can validate it by using <set-variable name="Values" value="@((string)string.Join(", ", context.Deployment.Certificates.Values))" />
expression.
You can use the below given policy to pass the Thumbprint of a specific certificate uploaded in APIM to verify against the incoming certificate.
<policies>
<inbound>
<base />
<choose>
<when condition="@(context.Request.Certificate != null || (string)context.Deployment.Certificates.Values.FirstOrDefault(cert => cert.Thumbprint == "<APIMCertThumbprint>")?.Thumbprint == context.Request.Certificate.Thumbprint)">
<return-response>
<set-status code="200" reason="OK" />
<set-body>Valid certificate</set-body>
</return-response>
</when>
<otherwise>
<return-response>
<set-status code="403" reason="Invalid client certificate" />
<set-body>Invalid or missing client certificate</set-body>
</return-response>
</otherwise>
</choose>
</inbound>
</policies>
Due to some limitations I can't pass the certificate information in request body, so I am testing by storing the value of thumbprint in set-variable against the uploaded certificate in APIM.