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)
In order to call the webservice succesfully the following steps need to have taken place:
openssl genrsa -aes256 -out [NameOfPrivateKey].pem 2048
openssl req -new -sha256 -key [NameOfPrivateKeyFromStep2].pem -out [NameOfTheSigningRequest].csr
set OPENSSL_CONF=c:\[PATH TO YOUR OPENSSL DIRECTORY]\bin\openssl.cfg
under an Admin command prompt)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
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
When prompted, select a secure password and keep it safe.
Let VisualStudio generate a proxy class, based on the WSDL file you can download from Apple, for example call it GsxWSEmeaAspService
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;
}
}
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.
(N.B. Sorry, unable to convince the parser to format this properly, any help is welcome..)