Microsoft KB Archive/901183

From BetaArchive Wiki

Article ID: 901183

Article Last Modified on 12/13/2007



APPLIES TO

  • Microsoft .NET Framework 1.1, when used with:
    • Microsoft Internet Information Services 6.0
    • Microsoft Internet Information Services 5.0




SUMMARY

This article discusses how to pass a client certificate to a Web service for authentication from an ASP.NET Web application.

Note The steps in this article also apply to when you make a direct HTTP request by using the HttpWebRequest class if you do not invoke a Web service.


INTRODUCTION

Frequently, Web services must authenticate applications that call the Web services. The Web services must perform authentications of calling applications before the Web services can perform authorizations. One authentication technique is to require applications that call the Web service to present a client certificate.

When an ASP.NET Web application tries to call a Web service that uses certificate authentication, you may receive an "access denied" error message. When a console application or a Microsoft Windows Forms application calls the same Web service, you do not receive an error message.

This behavior occurs because the computer maintains two different certificate stores:

  • The local machine store: An ASP.NET Web application looks in this store to locate client certificates.
  • The local user store: An interactive user application looks in this store to locate client certificates.

Typically, when an interactive user application installs a client certificate, the client certificate is installed in the local user store. Therefore, the client certificate works for interactive user applications. However, the client certificate does not work for ASP.NET Web applications.

MORE INFORMATION

To enable an ASP.NET Web application to use a client certificate, you must install the client certificate in the local machine store. When you install a client certificate in the local machine store, the client certificate is only available for user accounts in the Administrators group and for the user who installed the client certificate. Therefore, you must grant access to the client certificate for the user account that is used to run the ASP.NET Web application.

Note You must have the Microsoft .NET Framework 1.1 Service Pack 1 (SP1) installed to use client certificates in the local machine store.

Additionally, when the ASP.NET Web application calls the Web service, the application must export the client certificate from the certificate store and then add the client certificate to the Web service call.

Install the client certificate and grant access for the user account

To install the client certificate, and to grant access to the client certificate for the user account that is used to run the ASP.NET Web application, follow these steps.

Step 1: Install the client certificate in the local machine store

If you have a client certificate in a PKCS#12 (.pfx) file, you can use the Microsoft Windows HTTP Services Certificate Configuration Tool (WinHttpCertCfg.exe) to install the client certificate and to grant access to the client certificate for additional user accounts such as the Network Service account. To do this, follow these steps:

  1. Download and then install the Microsoft Windows HTTP Services Certificate Configuration Tool. To obtain the tool, visit the following Microsoft Web site:
  2. Run the following command at a command prompt:

    winhttpcertcfg -i PFXFile -c LOCAL_MACHINE\My -a IWAM_TESTMACHINE -p PFXPassword

    Note PfxFile is the name of the .pfx file. Password is the password for the .pfx file. If the file does not require a password, omit the -p parameter.

    Typically, the WinHttpCertCfg.exe file is located in the following folder:

    C:\Program Files\Windows Resource Kits\Tools

If you do not have access to a .pfx file, and you have installed Microsoft Certificate Services on a computer that is running Microsoft Windows Server 2003 or Microsoft Windows 2000 Server, you can request and install the client certificate directly into the local machine store. To do this, follow these steps:

  1. Log on to the client computer by using a user account that has administrator credentials.
  2. In Microsoft Internet Explorer, visit the certification authority (CA) Web site. For example, if the CA server is named CAServer, visit the following Web site:
  3. Under Select a task, click Request a certificate, and then click advanced certificate request.
  4. Click Create and submit a request to this CA.
  5. In the Advanced Certificate Request form, enter a name and an e-mail address.
  6. In the Type of Certificate Needed section, click Client Authentication Certificate.
  7. In the Key Options section, click to select the Store certificate in the local computer certificate store check box, and then click Submit.

    Note the Request ID for the client certificate.
  8. In the Potential Scripting Violation dialog box, click Yes.
  9. After the CA has issued the client certificate, click Home, and then click View the status of a pending certificate request.
  10. Under Select the certificate request you want to view, click the certificate request that you submitted in step 7.
  11. Click Install this certificate, and then click Yes in the Potential Scripting Violation dialog box.

Step 2: Configure access to the client certificate

In this step, you must grant permission for the ASP.NET account to access the client certificate that is stored in the local machine store. The Network Service account is the default account for running Web applications on Windows Server 2003. Therefore, you must grant access to the certificate for the Network Service account. If you have configured a custom account to run ASP.NET, you must grant access for the custom account.

Note In Microsoft Internet Information Server (IIS) 5.0, ASP.NET runs under the ASPNET account and not under the Network Service account. Therefore, you must to grant permissions for the ASPNET account on a computer that is running IIS 5.0.

To grant access for a specific user account, run the following command at a command prompt:

WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "IssuedToName" -a "AccountName"


Note AccountName is the name of a local computer account or a domain account. IssuedToName is the name of the company or domain to which the client certificate was issued. This command contains a case-insensitive search string. The search string finds the first enumerated certificate that has a subject name that contains the string.

The following command-line command is an example of how to grant access to the client certificate for the Network Service account in Microsoft Internet Information Services (IIS) 6.0:

WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "IssuedToName" -a "NetworkService"


The following command-line command is an example on how to grant access to the client certificate for the ASPNET account in IIS 5.0:

WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "IssuedToName" -a "ASPNET"


Note When you use the Windows HTTP Services Certificate Configuration Tool, you can combine the process of importing the client certificate and the process of configuring access to the client certificate in one step. For example, the following command-line command performs both processes:

Winhttpcertcfg.exe -i PFXFile -c LOCAL_MACHINE\My -a “AccountName


Step 3: Copy the client certificate from the local user store to the local machine store

If an interactive application such as a Windows Forms application or a command-line application can access the client certificate, the client certificate is already stored in the local user store. However, if a service application such as an ASP.NET Web application cannot access the same client certificate, the client certificate may not be stored in the local machine store.

This step explains how to copy a client certificate in the local user store to the local machine store by using the Certificate Export Wizard.

Note If the client certificate is already in the local machine store, or if you can install the client certificate directly in the local machine store as in Step 1, go to Step 4. However, if you use Step 3, you must then return to Step 2 to grant access to the client certificate.

To copy the client certificate to the local machine store, follow these steps:

  1. Click Start, click Run, type mmc, and then click OK.
  2. On the File menu, click Add/Remove Snap-in, and then click Add.
  3. In the Add Standalone Snap-ins dialog box, click Certificates, click Add, click Computer account, click Next, and then click Finish.
  4. In the Add Standalone Snap-ins dialog box, click Certificates, click Add, click My user account, and then click Finish.
  5. Click Close, and then click OK.
  6. To export the client certificate from the local user store, follow these steps:
    1. Expand Certificates - Current User, expand Personal, and then click Certificates.
    2. Right-click the client certificate, click All Tasks, click Export, and then click Next.
    3. If the Yes, export the private key option is not available, the ASP.NET Web application cannot use the client certificate. You must obtain another client certificate. To do this, follow the instructions in Step 1 and Step 2. Otherwise, click Yes, export the private key, and then click Next two times.
    4. In the Password box and in the Confirm Password box, type a password, and then click Next.
    5. In the File name box, type a file name. Click Next, and then click Finish.
    6. In the Certificate Export Wizard dialog box, click OK.
  7. To import the client certificate to the local machine store, follow these steps:
    1. Expand Certificates (Local Computer), and then expand Personal.
    2. Right-click Certificates, click All Task, click Import, and then click Next.
    3. In the File name box, type the file name that you specified in step 6e, and then click Next.
    4. In the Password box, type the password that you specified in step 6d, and then click Next two times.
    5. Click Finish, and then click OK.

Step 4: Install the root certificate of the CA

If the client certificate is already signed by an external CA such as VeriSign, or if you have already installed the root certificate for the CA, you can omit Step 4.

By default, Windows has the root certificates of many external CAs already pre-installed in the Trusted Root Certificate Store.

Verify that the root certificate is installed

To verify that the root certificate for the CA is installed, follow these steps:

  1. Click Start, click Run, type mmc, and then click OK.
  2. On the File menu, click Add/Remove Snap-in, and then click Add.
  3. In the Add Standalone Snap-ins dialog box, click Certificates, click Add, click Computer account, click Next, and then click Finish.
  4. Click Close, and then click OK.
  5. Expand Certificates (Local Computer), expand Trusted Root Certification Authorities, and then click Certificates.
  6. In the right pane, confirm that the root certificate of the CA that you want to use is listed.
Install the root certificate

If the root certificate of the CA that you want to use is not listed, you must install the root certificate. If the root certificate of the CA that you want to use has been issued to you in a certificate file such as a .cer file, a .der file, or a .pfx file, follow these steps:

  1. Expand Certificates (Local Computer), right-click Trusted Root Certification Authorities, click All Tasks, and then click Import.
  2. In the Certificate Import Wizard dialog box, click Next, and then in the File name box, type the name of the certificate file, and then click Next two times.
  3. Click Finish, and then click OK.
Request the root certificate

If the CA that you want to use is included in the Microsoft Certificate Services installation database, you can request the root certificate. To do this, follow these steps:

  1. In Internet Explorer, visit the CA Web site. For example, if the CA server is named CAServer, visit the following Web site:
  2. Click Download a CA certificate, certificate chain, or CRL, and then click Download CA certificate.
  3. In the File Download dialog box, click Save.
  4. In the Save As dialog box, enter the location where you want to save the certificate file, and then click Save.
  5. After you have saved the root certificate file, use steps in the "Install the root certificate" section to install the certificate file in the Trusted Root Certification Authorities store.

Call the Web service

After you have installed the client certificate in either the local machine store or the local user store, you can access the client certificate from the ASP.NET Web application to call the Web service. The steps to access the client certificate are the same for a Windows Forms application or for an ASP.NET Web application.

If you are using the .NET Framework 1.1, you must first export the key to a DER-encoded file. You must export the key because the System.Security.Cryptography.X509Certificates.X509Certificate class does not contain methods to directly access the details of a certificate from a certificate store. Therefore, the application must read the details of a certificate from a DER-encoded file.

Note Web Services Enhancements 2.0 for Microsoft .NET (WSE) provides a way for an application to retrieve the details of a certificate directly from a certificate store.

The following C# example code shows how to call a Web service by passing a client certificate for authentication.

using System.Security.Cryptography.X509Certificates;
...

  public void CallWebService()
  {
    // TODO: Replace <C:\WSClientCert.cer> with the path of your certificate file.
    string certPath = @"<C:\WSClientCert.cer>";

    // Create an instance of the Web service proxy.
    WebSvc.math mathservice = new WebSvc.math();
    // TODO: Replace <https://wsserver/securemath/math.asmx> with a valid URL.
    mathservice.Url = @"<https://wsserver/securemath/math.asmx>";

    // Create an X509Certificate object from the information 
    // in the certificate export file, and then add the certificate to the 
    // ClientCertificates collection of the Web service proxy.
    mathservice.ClientCertificates.Add(
        X509Certificate.CreateFromCertFile(certPath));

    long lngResult = 0;
    try
    {
      lngResult = mathservice.Add(Int32.Parse(operand1.Text), 
          Int32.Parse(operand2.Text));
      string result = lngResult.ToString();
    }
    catch(Exception ex)
    {
      if(ex is WebException)
      {
        WebException we = ex as WebException;
        WebResponse webResponse = we.Response;
        throw new Exception("Exception calling method. " + ex.Message);
      }
    }
  }

Web Services Enhancements 2.0 for Microsoft .NET

Web Services Enhancements 2.0 for Microsoft .NET (WSE) is a Microsoft .NET class library for building Web services by using the latest Web services protocols. These protocols include the following:

  • WS-Security
  • WS-SecureConversation
  • WS-Trust
  • WS-Policy
  • WS-SecurityPolicy
  • WS-Addressing
  • WS-Attachments

Note WSE is not included as part of the .NET Framework. To obtain WSE, visit the following Microsoft Web site:

You do not have to use any one of these protocols to access a Web service that requires client certificate authentication. However, you may want to use the Microsoft.Web.Services2.Security.X509 class. The Microsoft.Web.Services2.Security.X509 class contains methods to directly access a client certificate in the certificate store. If you use these methods, you do not have to export the certificate to a file.

The following C# example code shows how to find the first certificate that is named SecureMathClient in the local machine store. Then, this example code uses the certificate to call the Add method of the math Web service. The math Web service requires client certificates.

...
  // TODO: Replace <SecureMathClient> with the name of the client certificate.
  string certName = "<SecureMathClient>";

  // WSE 2.0 method
  X509CertificateStore store =
    X509CertificateStore.LocalMachineStore(X509CertificateStore.MyStore);
  store.OpenRead();
  // Look for the first certificate that is named SecureMathClient.
  // Look in the local machine store.
  X509CertificateCollection col= 
    (X509CertificateCollection)store.FindCertificateBySubjectString(certName);
  X509Certificate cert =null;
  try
  { 

// This sample obtains the first matching certificate from the collection.
    cert = col[0];
  } 
  catch(Exception ex)
  {
    throw new Exception("Certificate not Found!");
  }

  // Create an instance of the Web service proxy.
  math mathservice = new math();
  // TODO: Replace <https://wsserver/securemath/math.asmx> with a valid URL.
  mathservice.Url = @"<https://wsserver/securemath/math.asmx>";
  mathservice.ClientCertificates.Add(cert);

  long lngResult = 0;
  try
  {
    lngResult = mathservice.Add(Int32.Parse(operand1.Text), 
        Int32.Parse(operand2.Text));
    result.Text = lngResult.ToString();
  }
  catch(Exception ex)
  {
    if(ex is WebException)
    {
      WebException we = ex as WebException;
      WebResponse webResponse = we.Response;
      throw new Exception("Exception calling method. " + ex.Message);
    }
  }

REFERENCES

For more information about the System.Security.Cryptography.X509Certificates.X509Certificate class, visit the following Microsoft Developer Network (MSDN) Web site:

For more information about how to call a security-enhanced Web site by using an ASP.NET Web application, click the following article number to view the article in the Microsoft Knowledge Base:

817854 FIX: ASP.NET Web application cannot deliver a client certificate to a security-enhanced Web site


Keywords: kbcode kbwebservices kbcertservices kbhowto kbinfo KB901183