# 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

You can download the module at appcelerator.https (opens new window)

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();

# Properties

# apiName READONLY

Availability
3.3.0
3.3.0
apiName :String

The name of the API that this proxy corresponds to.

The value of this property is the fully qualified name of the API. For example, Titanium.UI.Button returns Ti.UI.Button.


# bubbleParent

Availability
3.3.0
3.3.0
bubbleParent :Boolean

Indicates if the proxy will bubble an event to its parent.

Some proxies (most commonly views) have a relationship to other proxies, often established by the add() method. For example, for a button added to a window, a click event on the button would bubble up to the window. Other common parents are table sections to their rows, table views to their sections, and scrollable views to their views. Set this property to false to disable the bubbling to the proxy's parent.

Default: true


# lifecycleContainer

Availability
3.6.0

The Window or TabGroup whose Activity lifecycle should be triggered on the proxy.

If this property is set to a Window or TabGroup, then the corresponding Activity lifecycle event callbacks will also be called on the proxy. Proxies that require the activity lifecycle will need this property set to the appropriate containing Window or TabGroup.

# Methods

# addEventListener

Availability
3.3.0
3.3.0
addEventListener(name, callback) void

Adds the specified callback as an event listener for the named event.

Parameters

Name Type Description
name String

Name of the event.

callback Callback<Titanium.Event>

Callback function to invoke when the event is fired.

Returns

Type
void

# applyProperties

Availability
3.3.0
3.3.0
applyProperties(props) void

Applies the properties to the proxy.

Properties are supplied as a dictionary. Each key-value pair in the object is applied to the proxy such that myproxy[key] = value.

Parameters

Name Type Description
props Dictionary

A dictionary of properties to apply.

Returns

Type
void

# 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


# fireEvent

Availability
3.3.0
3.3.0
fireEvent(name[, event]) void

Fires a synthesized event to any registered listeners.

Parameters

Name Type Description
name String

Name of the event.

event Dictionary

A dictionary of keys and values to add to the Titanium.Event object sent to the listeners.

Returns

Type
void

# removeEventListener

Availability
3.3.0
3.3.0
removeEventListener(name, callback) void

Removes the specified callback as an event listener for the named event.

Multiple listeners can be registered for the same event, so the callback parameter is used to determine which listener to remove.

When adding a listener, you must save a reference to the callback function in order to remove the listener later:

var listener = function() { Ti.API.info("Event listener called."); }
window.addEventListener('click', listener);

To remove the listener, pass in a reference to the callback function:

window.removeEventListener('click', listener);

Parameters

Name Type Description
name String

Name of the event.

callback Callback<Titanium.Event>

Callback function to remove. Must be the same function passed to addEventListener.

Returns

Type
void