Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Fixed links and formatting
Warning

Since Release 3.3.0 , the mechanisms described in this document to support SSL Certificate Stores for HTTP Clients are no longer supported. You should instead use use the HTTPClient's securityManager property to implement support for SSL Certificate Stores.

  • The Android-specific Titanium.Network.HTTPClient addKeyManager and addTrustManager methods are deprecated and removed in Release 3.4.0.
  • The iOS-specific Titanium.Network.HTTPClient clientCertificateIdentity and clientCertificates properties are no longer supported.

 

Table of Contents

Introduction

Starting with Release 3.1.0, the Android and iOS platforms have added functionality to support SSL Certificate Stores with the Titanium.Network.HTTPClient. This document provides information on the changes made to the platforms and the related functionality.

...

These are concrete C structures of the native iOS SDK and cannot be exposed on the JavaScript side. Modules must set these properties on the HTTPClient object in native code. These properties must be set before calling open on the HTTPClient. 

The clientCertificateIdentity property must be set for the clientCertificates to be honored. 

These two properties can be used to set client-side certificates for secure HTTP connections. These are useful for environments where the server requires the client to present valid certificates as part of the SSL handshake.

Validation of server certificates is controlled by the validatesSecureCertificate property of the HTTPClient and must be set to true validate the secure certificate.

...

The following example code shows how to load an external PKCS #12 file and use it with an HTTP client.  This This example contains two separate pieces: the Titanium application written in JavaScript and the iOS module written in Objective-C and using some of the native iOS SDK APIs.  The The Titanium application needs to use the iOS module to perform necessary functions as mentioned earlier.

...

  1. Require in the module.
  2. Create an HTTPClient with the the validatesSecureCertificate property set to true.
  3. Call the module method to parse the PKCS #12 file and set the the clientCertificateIdentity property.
  4. Call the open and send methods to initiate the HTTP request.
Code Block
// Require the module
var certificateStore = require('com.certtest');
var url = "https://some.url";
var httpClient = Ti.Network.createHTTPClient({
	onload: function(e) {
		Ti.API.info("Received text: " + this.responseText);
		alert('success');
	},
	onerror: function(e) {
		Ti.API.info("Error: " + e.error);
		alert('error');
	},
	timeout: 5000,
 
    // this property must be set to true
	validatesSecureCertificate: true
});

// References a file called server.p12 in the Resources directory
var cert = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, "server.p12");

// Call the module method and send the HTTPClient object
// to set the clientCertificateIdentity property
certificateStore.loadP12Cert(httpClient, cert, 'password');

httpClient.open("GET", url);
httpClient.send();

In an iOS module, the the loadP12Cert  method receives the HTTPClient object, the PKCS #12 file and the password to the file, then it:

  1. Loads the external PKCS #12 file.
  2. Parses it with the native native SecPKCS12Import method.
  3. Sets the the clientCertificateIdentity of the HTTPClient object.
Code Block
// Omitted boiler plate code created for a new module
// Note that this example does not perform type or error checking
-(id)loadP12Cert:(id)args
{
    // Parse the arguments
    NSArray* theArg = args;
    // Titanium.Network.HTTPClient object
    TiProxy* theClient = [theArg objectAtIndex:0];
    // Titanium.Filesystem.File object (p12 file)
    TiFile *theFile = [theArg objectAtIndex:1];
    // Password of the file
    NSString* thePassword = [theArg objectAtIndex:2];
    NSString* path = [theFile path];
 
    // Load the file data
    NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:path];
    CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;
    SecIdentityRef myIdentity;
    SecTrustRef myTrust;
    OSStatus securityError = noErr;
 
    // Parse the file data
    securityError = extractIdentityAndTrust(inPKCS12Data, &myIdentity, &myTrust, thePass);

    if (securityError == 0) {
        // Set the clientCertificateIdentity property 
        [theClient setValue:(id)myIdentity forUndefinedKey:@"clientCertificateIdentity"];
    }
    [PKCS12Data release];
    return securityError;
}
 
// Example code taken from the Mac Developer Guide: Certificate, Key, and Trust Services Tasks
OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data, SecIdentityRef *outIdentity, SecTrustRef *outTrust, NSString* thePass)
{
    OSStatus securityError = errSecSuccess;
    CFStringRef password = (CFStringRef)thePass;
    const void *keys[] =   { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);

    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);

    securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);

    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
        *outIdentity = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
        *outTrust = (SecTrustRef)tempTrust;
    }
    if (optionsDictionary)
        CFRelease(optionsDictionary);

    return securityError;
}

...

Users can add custom KeyManager and TrustManager implementations to use with the HTTPClient connection.  These  These methods must be called before calling before calling open on the HTTPClient.

You need to use an Android module to implement the X509KeyManager or X509TrustManager interface and return these objects to the Titanium application. The application uses the addKeyManager and addTrustManager methods to add support for these objects.

When either of these methods are used to initialize a custom SSLContext, the validatesSecureCertificate property of the HTTPClient is ignored.  For For more information about custom SSL, see Custom SSL for advanced JSSE developers.

Android Example

For an example of writing an Android module that implements and returns an X509TrustManager interface, see https://github.com/appcelerator-modules/ti.certificatestore.  This This module receives an external PKCS #12 file, parses it, then creates an X509TrustManager instance.

...