PepperHQ Developer

The PepperHQ Developer Hub

Hand crafted, customised and bespoke mobile experiences to suit your brand and needs.

Guides

Service Facade

Exposing a 3rd party service to the PepperHQ Platform

This document describes the characteristics of a 'Pepper Connected Service' (Service) that are common, regardless of the role that they occupy.

Please note that a Service Facade conforming to this specification is only required if the service being integrated with is external. Integration with internal services can be more tightly coupled, for example via a Node.js module.

Service Interface

A Service exposes itself to clients as a collection of JSON-RPC 2.0 methods over HTTP.

The path to the Service functions is /api.

The JSON schema to which all requests to Services adhere is:

	{
    	"$schema": "http://json-schema.org/draft-04/schema#",
	    "description": "A JSON RPC 2.0 request",
    	"oneOf": [
        	{
            	"description": "An individual request",
	            "$ref": "#/definitions/request"
    	    },
        	{
            	"description": "An array of requests",
	            "type": "array",
    	        "items": { "$ref": "#/definitions/request" }
        	}
	    ],
    	"definitions": {
        	"request": {
            	"type": "object",
	            "required": [ "jsonrpc", "method" ],
    	        "properties": {
        	        "jsonrpc": { "enum": [ "2.0" ] },
            	    "method": {
                	    "type": "string"
	                },
    	            "id": {
        	            "type": [ "string", "number", "null" ],
            	        "note": [
                	        "While allowed, null should be avoided: http://www.jsonrpc.org/specification#id1",
	                        "While allowed, a number with a fractional part should be avoided: http://www.jsonrpc.org/specification#id2"
    	                ]
        	        },
            	    "params": {
                	    "type": [ "array", "object" ]
	                }
    	        }
        	}
	    }
	}

Multi-Tenancy

Pepper is a multi-tenanted service, meaning that many Tenants are co-located on the same infrastructure and within the same overall data domain.

To ensure that data integrity is maintained and Merchant data does not leak, every request to a Service must be scoped by an X-TENANT-ID http header.

X-TENANT-ID: 1234567890

The Service uses this information to scope settings.

Non-Functional Paths

In addition to the primary Service interface, Services include the following additional Interfaces:

  • / - does not require authentication and returns information about the service expressed as JSON
  • /docs - documentation for interacting with the Service.
  • /admin - web user interface for administering the service (if necessary).
  • /health - does not require authentcation and returns information about the service and services on which it depends as JSON. The health of a Service or a dependancy is one of the following values - OK, DEGRADED, SEVERE, CRITICAL.

Example of a / response:

{
  "name": "Pepper API",
  "environment": "production",
  "version": "1.0.1507291445",
  "date": "2015-08-28T10:45:24.453Z",
  "documentation": "/docs"
}

Example of a /health response:

{
  "status": "OK",
  "dependancies": {
    "someThirdPartyAPI": "OK"
  }
}

Authorization

Endpoints of services that provide access to private data (or otherwise should be protected) are protected with the hmac-http-authentication module. This is currently a private module.

The pattern for authentication enabled by this module is similar to that employed by the Amazon Web Services APIs.

The Authorization header should be structured as follows:

Authorization: HMAC-SHA256, SignedHeaders=<header 1>;<header 2>, Signature=<signature>

This header contains the following information:

  • Scheme - Encryption method (currently only HMAC-SHA256).
  • SignedHeaders - Semi-colon separated concatenation of the HTTP request headers that have been encrypted.
  • Signature - Encrypted semi-colon separated concatenation of the values specified in the SignedHeaders. A pre-shared key is used as the secret.

For example, the following HTTP header:

GET /resource/1234567890
Date: Tue, 15 Nov 1994 08:12:31 GMT
If-None-Match: 737060cd8c284d8af7ad3082f209582d

Would result in an Authorization header of:

Authorization: HMAC-SHA256 SignedHeaders=verb;path;Date;If-None-Match, Signature=ced6826de92d2bdeed8f846f0b

To authenticate the request:

/* Get the pre-shared key for the service */
var API_KEY = process.env.API_KEY;

/* Authorize the request */
var auth = require('@pepperhq/hmac-http-authentication');
var authenticated = auth.authorizeHeaders(req.headers, API_KEY);

If Services are not hosted and operated by Pepper, then this module need not be used if an identical Authentication pattern can be achieved by other means.

Service Internals

If Pepper connected services are hosted and operated by Pepper, they have a common platform 'pattern' as described in this section of the document.

  • Services are developed using the NodeJS runtime.
  • Services use Express as their underlying web application framework.
  • Services are portable, so that they can reliably be deployed into development, test and production environments. To achieve this, they are available as Docker containers.
  • Services are deployed into an Amazon EC2 Container Service environment in production.
  • Where appropriate, Amazon Lambda may be used to host Services for which demand is sporadic and may peak at relatively high concurrences.
  • Where Services require access to Amazon Web Services resources (e.g. DynamoDB), the Amazon credentials that are used must only have rights that are appropriate to the needs of the Service and are exposed to the application via environment variables as described in the AWS Documentation.
  • Services submit log events to the 'Central Log' service via the Amazon SNS topic (ARN is arn:aws:sns:eu-west-1:445362371491:CentralLog).
  • Services include a complete set of Mocha tests that employ the Unexpected assertion toolkit.
  • Services are developed in accordance with Felix Geisendorfer's Node.js Style Guide.
  • A Service is contained in a single GitHub repository. The repository should be titled according to the following pattern: service-type-instance (e.g. service-pos-revel).
  • Services include a clear description of its purpose as well as clear instructions for spinning up a development instance of the service in the README. The README need not contain detailed information about how to consume the service itself as this is already provided at /docs.
  • Service versions are exposed via the root path and are in line with the Semantic Versioning 2.0.0. The 'patch' value should be the time of the commit of the source in YYMMDDHHmm format. e.g. 1.0.1511121042.
  • The params property of all requests are validated using JSON Schema.