# Modules.Https

Prevents a man-in-the-middle attack when used with the Titanium.Network.HTTPClient class.

Availability
3.3.0
3.3.0

# Overview

Note: This feature requires a Pro or Enterprise subscription. More infos here!

Use the HTTPS module to create a Security Manager for Titanium.Network.HTTPClient that authenticates a set of HTTPS servers by pinning an HTTPS server's URL to its public key contained in the certificate.

The X.509 certificate files can have any name and extension you wish, but they must be in DER binary format.

The security manager will guarantee that all HTTPClient connections to this URL are to a server that holds the private key corresponding to the public key embedded in the certificate, therefore authenticating the server and preventing man-in-the-middle attacks.

# Concepts

Typically, HTTPS connections are authenticated using a chain of trust, where the identities of various intermediate certificate authorities (CA) are checked until a trusted root CA can be authenticated.

For example, an intermediate CA signs the HTTPS server's certificate used to check the identity of the HTTPS server you want to connect to. However, the intermediate CA cannot be trusted until its identity is verified. The certificate of the intermediate CA must be checked to see if the CA is trusted. This process repeats until a root CA can be checked. Once all identities have been validated, the application can establish a secure connection to the HTTPS server. This mechanism is known as a certificate chain.

This mechanism relies on trusting third parties to carefully check and validate other companies that sign certificates. If an untrustworthy CA issues a valid certificate to an attacker or an attacker gets a hold of a CA's private key, the attacker can insert themselves into the certificate chain, then intercept and send data to the client. This is known as a man-in-the-middle attack.

To prevent man-in-the-middle-attacks, the security manager, created by this module, ensures that the public key in the leaf certificate (or other certificate identified by the trustChainIndex property) of the chain is the same as the public key in the certificate configured with this URL. If the public keys match, the chain is passed onto the underlying OS to authenticate. If they do not match, the connection is terminated.

Since we pass the chain to the underlying OS to validate, self-signed certificates will be rejected. Note that the validatesSecureCertificate property of the HTTPClient is not honored for pinned URL's.

For the Security Manager to participate in the connection, the initial URL must be configured.

If a connection redirects to a different host, then public key validation on the redirected URL will only be performed if that URL is also configured in the Security Manager. If the redirected URL is not configured, then the default OS authentication is triggered.

# Getting Started

Once you have installed the module and added it as a depedency and use require() (ES5) or import (ES6+) to access it from JavaScript:

// ES5
var https = require('appcelerator.https');

// ES6+
import 'https' from 'appcelerator.https';

The https variable is a reference to the module object. Use this reference to call the createX509CertificatePinningSecurityManager() method to authenticate the specified HTTPS URLs. Pass in an array of dictionaries as the only required parameter to the method. Each dictionary in the array contains three keys (two of them required):

  • url: URL of the server to contact. Can be a fixed URL or wildcard URL (if supported by the certificate)
  • serverCertificate: X.509 certificate in DER format to verify the server's identity
  • trustChainIndex: (Optional) index of the trust-chain certificate to validate against (default: 0 - leaf certificate).

For example:

var securityManager = https.createX509CertificatePinningSecurityManager([
    {
        url: 'https://www.example.com',
        serverCertificate: 'exampleServerCertificate.der',
        trustChainIndex: 0
    }
]);

After the security manager is created, create an HTTPClient object and set the Titanium.Network.HTTPClient.securityManager property to the security manager object you just created. You must set this property when creating the HTTPClient instance.

var httpClient = Ti.Network.createHTTPClient({
    onload: function(e) {
        Ti.API.info('Received text: ' + httpClient.responseText);
    },
    onerror: function(e) {
        Ti.API.error(e.error);
    },
    timeout: 5000,
    // You can only set this property when creating the HTTPClient
    securityManager: securityManager
});

After the securityManager property is set, call the HTTPClient's open() and send() methods to initiate the HTTPS request.

httpClient.open('GET', 'https://example.com');
httpClient.send();

If the authentication fails, a security exception is thrown. The HTTP client's onerror callback will be passed an error object with the code key set to -1 and the message key set to the following message:

`Certificate could not be verified with provided public key`

To perform another HTTPS request, you need to create another HTTPClient object and follow the same procedure to initiate an HTTPS request. You can reuse the same security manager object.

# Examples

# Simple Example

This example pins two URLs.

The first URL, https://dashboard.appcelerator.com, is pinned to the public key in the X.509 certificate, named appcelerator.com.pem, located in the application's Resources directory (Classic) or app/assets/ directory (Alloy).

The second URL, https://www.wellsfargo.com, is pinned to the public key in the X.509 certificate, named wellsfargo.der, located the application's Resources directory (Classic) or app/assets/ directory (Alloy).

// Require in the module
var https = require('appcelerator.https'),
    securityManager,
    httpClient;

// Use the module to create a Security Manager that authenticates the specified URLs
securityManager = https.createX509CertificatePinningSecurityManager([
    {
        url: 'https://dashboard.appcelerator.com',
        serverCertificate: 'dashboard.appcelerator.com.der'
    },
    {
        url: 'https://www.wellsfargo.com',
        serverCertificate: 'wellsfargo.der'
    }
]);

// Create an HTTP client the same way you always have
// but pass in the optional Security Manager that was created previously.
httpClient = Ti.Network.createHTTPClient({
    onload: function(e) {
        Ti.API.info('Received text: ' + httpClient.responseText);
    },
    onerror: function(e) {
        Ti.API.error(e.error);
    },
    timeout: 5000,
    // Set this property before calling the `open` method. 
    securityManager: securityManager
});

// Prepare the HTTPS connection in the same way you always have
// and the Security Manager will authenticate all servers for
// which it was configured before any communication happens.
httpClient.open('GET', 'https://dashboard.appcelerator.com');

// Send the request in the same way you always have.
// Throws a Security Exception if authentication fails.
httpClient.send();

# Methods

# createX509CertificatePinningSecurityManager

Availability
3.3.0
3.3.0
createX509CertificatePinningSecurityManager(params) SecurityManagerProtocol

Creates a Security Manager object for the HTTPClient to authenticate a specified set of HTTPS URLs.

Set the object returned by this method to the securityManager property to authenticate the connection. Pass the object to the securityManager property when creating the HTTPClient instance.

Parameters

Name Type Description
params Array<Dictionary>

Server URLs with the corresponding certificate to authenticate, specified as an array of dictionaries that must contain the following keys:

  • url: HTTPS URL pinned to the public key in the server certificate
  • serverCertificate: X.509 certificate file in DER binary format

Optionally, use the following key for further configuration:

  • trustChainIndex: Index of the trust-chain certificate to validate against (default: 0 - leaf certificate).
  • clientCertificate: Client certificate for two-way authentication in PKCS12 format (*.p12)
  • clientPassword: Client certificate password.

Returns