Search code examples
web-serviceswcfwsdlx509x509certificate2

How can I connect with Apple's GSX NewGeneration webservices with WCF?


Starting August 15 2015, the GSX webservices from Apple will be upgraded to a more secure version, requiring a clientside SSL certificate for each request. What steps do I need to take to connect to this New Generation webservice using the WCF framework with C#.NET?

The documentation from Apple states the first step is to generate a CSR (Certificate Signing Request), send this to Apple and they will return a certificate to secure the future connections with.

How can I generate this CSR? What steps do I need to take next to successfully connect and get a valid response?

The above and the previous Find My iPhone webservice implementation caused me a relative great deal of trouble, I hope this helps other users out.

(N.B. I'd like to add the apple-gsx tag, but I don't have the required reputation)


Solution

  • In order to call the webservice succesfully the following steps need to have taken place:

    1. Make sure you have OpenSSL installed and working
    2. Generate a key pair:
      openssl genrsa -aes256 -out [NameOfPrivateKey].pem 2048
      Keep this private key PRIVATE, don't share this with anyone!
    3. When prompted, select a secure password and keep it safe.
    4. Generate a certificate signing request (CSR):
      openssl req -new -sha256 -key [NameOfPrivateKeyFromStep2].pem -out [NameOfTheSigningRequest].csr
      When the above command fails with 'WARNING: can't open config file: /usr/local/ssl/openssl.cnf' run the command set OPENSSL_CONF=c:\[PATH TO YOUR OPENSSL DIRECTORY]\bin\openssl.cfg under an Admin command prompt)
    5. Send the .csr (Certificate Signing Request) to Apple, keep the .key private. Apple returns a .pem certificate file
    6. Make sure the MD5 of .pem and .key match. The output of the following commands should be identical:

      openssl x509 -noout -modulus -in [CertificateReceivedFromApple].pem | openssl md5

      openssl rsa -noout -modulus -in [NameOfPrivateKeyFromStep2].pem | openssl md5

    7. Combine the certificate and key into a single .p12 container (More info here)

      openssl pkcs12 -export -in [CertificateReceivedFromApple].pem -inkey [NameOfPrivateKeyFromStep2].pem -out [FilenameOfNewKeyContainer].p12

    8. When prompted, select a secure password and keep it safe.

    9. Let VisualStudio generate a proxy class, based on the WSDL file you can download from Apple, for example call it GsxWSEmeaAspService

    10. Using the code below, authenticate yourself. The userSessionId is needed for further calls to actually send or receive data.

      public void Authenticate() {
          using (GsxWSEmeaAspService client = new GsxWSEmeaAspService()) {
              X509Certificate2 cert = new X509Certificate2(
                  [PathToContainerFromStep7].p12"),
                  [YourPasswordFromStep8],
                  X509KeyStorageFlags.MachineKeySet);
              client.ClientCertificates.Add(cert);
      
              GsxWSEmeaAspService.authenticateRequestType req = new GsxWSEmeaAspService.authenticateRequestType();
              req.languageCode = "EN";
              req.serviceAccountNo = [YourAppleServiceAccountNumber];
              req.userId = [YourUserID];
              req.userTimeZone = "CEST";
      
              client.Proxy = null;
      
              GsxWSEmeaAspService.authenticateResponseType res = client.Authenticate(req);
              userSessionId = res.userSessionId;
          }
      }
      
    11. Make sure you're not running any http proxies such as Fiddler, because the request will fail when one is active. This is also true for running the requests in SoapUI: the proxy setting needs to be off.

    12. Feel free to comment questions, I'll improve the answer if they add valuable information.

    (N.B. Sorry, unable to convince the parser to format this properly, any help is welcome..)