Blog Post

Azure PaaS Blog
3 MIN READ

API Management – Validate API requests through Client Certificate.

praskuma's avatar
praskuma
Icon for Microsoft rankMicrosoft
Jul 01, 2020

Azure APIM – Validate API requests through Client Certificate using Portal, C# code and Http Clients

 

Client certificates can be used to authenticate API requests made to APIs hosted using Azure APIM service. Detailed instructions for uploading client certificates to the portal can be found documented in the following article - https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-mutual-certificates-for-clients

 

Steps to authenticate the request –

 

  1. Via Azure portal

Once we have setup the certificate authentication using the above article, we can test an operation for a sample API (Echo API in this case). Here, we have chosen a GET operation and selected the “Bypass CORS proxy” option.

Once you click on the “Send” option, you would be asked to select the certificate that you would have already installed on your machine.

 

 

Note – This is the same certificate that you would have uploaded for your APIM service and added to the trusted list in the certificate store of your workstation.

 

 

After successful authentication and request processing, you would receive the 200 OK response code. Upon maneuvering to the trace logs, you can also see the certificate thumbprint that was passed for authentication.

 

 

 

The inbound policy definition used for this setup is as below:

(Kindly update the certificate thumbprint with your client certificate thumbprint)

 

 

 

 

<choose>
<when condition="@(context.Request.Certificate == null || context.Request.Certificate.Thumbprint != "BF3D644C46099A9D7C073EC002312878B8F9B847")">
<return-response>
<set-status code="403" reason="Invalid client certificate" />
</return-response>
</when>
</choose>

 

 

 

 

  1. Through C# or any other language that supports SDKs-

We can use the below sample C# code block to authenticate API calls and perform API operations.

Kindly update the below highlighted values with your custom values before executing the sample code attached below

 

Client certificate Thumbprint: BF3D644C46099A9D7C073EC002312878B8F9B847

Request URL: https://testapicert.azure-api.net/echo/resource?param1=sample

Ocp-Apim-Subscription-Key: 4916bbaf0ab943d9a61e0b6cc21364d2

Sample C# Code:

 

 

 

 

using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace CallRestAPIWithCert
{
    class Program
    {
        static void Main()
        {
            // EDIT THIS TO MATCH YOUR CLIENT CERTIFICATE: the subject key identifier in hexadecimal.
            string thumbprint = "BF3D644C46099A9D7C073EC002312878B8F9B847";
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
            X509Certificate2 certificate = certificates[0];
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://testapicert.azure-api.net/echo/resource?param1=sample");
            req.ClientCertificates.Add(certificate);
            req.Method = WebRequestMethods.Http.Get;
            req.Headers.Add("Ocp-Apim-Subscription-Key", "4916bbaf0ab943d9a61e0b6cc21364d2");
            req.Headers.Add("Ocp-Apim-Trace", "true");
            Console.WriteLine(Program.CallAPIEmployee(req).ToString());
            Console.WriteLine(certificates[0].ToString());

            Console.Read();

        }

        public static string CallAPIEmployee(HttpWebRequest req)
        {
            var httpResponse = (HttpWebResponse)req.GetResponse();
            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            {
                return streamReader.ReadToEnd();
            }
        }

        public static bool AcceptAllCertifications(object sender, X509Certificate certification, X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
    }
}

 

 

 

 

 

 

  1. Through Postman or any other Http Client

To use client certificate for authentication, the certificate has to be added under PostMan first.

Maneuver to Settings >> Certificates option on PostMan and configure the below values:

 

Host: testapicert.azure-api.net (## Host name of your Request API)

PFX file: C:\Users\praskuma\Downloads\abc.pfx (## Upload the same client certificate that was uploaded to APIM instance)

Passphrase: (## Password of the client certificate)

 

 

Once the certificate is uploaded on PostMan, you can go ahead and invoke the API operation.

 

You need to add the Request URL in the address bar and also add the below 2 mandatory headers:

Ocp-Apim-Subscription-Key : 4916bbaf0a43d9a61e0bsssccc21364d2 (##Add your subscription key)

Ocp-Apim-Trace : true

 

Once updated, you can send the API request and receive a 200 OK response upon successful authentication and request processing.

 

 

 

For detailed trace logs, you can check the value for the output header - Ocp-Apim-Trace-Location and retrieve the trace logs from the generated URL.

 

 

Updated Jul 03, 2020
Version 4.0
  • peterSchults's avatar
    peterSchults
    Copper Contributor

    After some further investigation i figured out how to get some extra logging setting the HEADER in postman: Ocp-Apim-Trace "true" to get Ocp-Apim-Trace-Location providing the required details.  

     

    Questions remaining are:

    When receiving API request with a client certificate what is required in APIM and policies to get it working?

     

    !context.Request.Certificate.Verify() ---- what does this setting require on APIM?

    - do we need to install the client certificate in APIM certificates? i have tested this and this was not working

    - do I need to install the certificate under trusted root? 

    <when condition="@(context.Request.Certificate == null || !context.Request.Certificate.Verify() || context.Request.Certificate.Thumbprint != "ZZZZZZZZZZ27")">
      <return-response>
          <set-status code="403" reason="Invalid client certificate" />
      </return-response>
    </when>

     

  • peterSchults's avatar
    peterSchults
    Copper Contributor

    Hi, I have an issue with a similar scenario.

    I have enabled an API and did the configurations as described.

     

    - Gateway settings done to negotiate client certificate

    - added self-signed client certificate to API Certificate as root

     

     

     

    - added policy to API to validate thumbprint

     

     

            <choose>
                <when condition="@(context.Request.Certificate == null || !context.Request.Certificate.Verify() || context.Request.Certificate.Thumbprint != "B6D3BE73E79586474DCC1221A77937686E60979C")">
                    <return-response>
                        <set-status code="403" reason="Invalid client certificate" />
                    </return-response>
                </when>
            </choose>

     

     

     

    If first tested it with a self-signed certificate generated on Azure and it worked.

    Now setting up the scenario with an external partner and his self-signed certificate it fails....

     

     

    Questions:

    Is there a way to figure out what thumbprint i am receiving. It's not shown in the insight logs.

    Or other suggestions to validate the incoming API call?