What is App proxy ?

App Proxy in SHOPLINE is a feature that act as intermediates, take requests from SHOPLINE links (configured subpath & child pages), and redirect them to external links (Proxy URL)

Possible usecases for ref.

  • Allow developers to integrate their web applications with SHOPLINE storefronts. It works by redirecting certain requests from the SHOPLINE store's URL to an external server
  • Initiate API calls from SHOPLINE storefront via App proxy

Setting up App proxy in Dev Center

a. Navigate to App > Advanced Settings > App proxy section in your SHOPLINE account

b. Configure App Proxy Settings

To configure the App Proxy settings for your app in SHOPLINE:

  1. Enable App Proxy: Toggle on the App Proxy feature in your app's settings
  2. Set up the required values in App Proxy settings, below list out are the details of each settings value for your persual.
SettingsDescriptionRemark
App Proxy SecretA unique, system-generated secret key used for signature verificationSecurity Note: This key must remain confidential. If you suspect it has been compromised, use the revoke button to generate a new secret for replacement.
Subpath PrefixSelect a subpath prefix that forms part of the proxy URL-
SubpathSubpath forms the full shop proxy URL. Subpath have 2 variants: Release version & development versionRelease Version: Utilizes the SEO slug value or, if unavailable, the app ID. Changes to the SEO slug value take effect only after the release version is approved.

Development Version: Formatted as {app_id}_TEST.
Proxy URLThe destination URL where the requests should be proxiedExample: If configured as https://proxy-url.demo, requests will be redirected to this link
  1. Submit for Approval: Once you've configured the settings, submit them for approval.

Illustration on how request to your shop's URL are routed to the proxy URL

Data added to proxy request

The system automatically insert the following query strings to the proxy request:

  1. merchant_id: The merchant ID
  2. customer_id: The customer ID if the custom has logged in. If not, it will be an empty string.
  3. path_prefix: /{sub_path_prefix}/{sub_path}
  4. timestamp: Unix timestamp of the request
  5. signature: The signature used for verification

Allowed Content Types & disallowed headers

Currently, only the following Content-Types are allowed:

  • text/html
  • application/json

Due to security concerns, the following headers are stripped from app proxy responses:

  • origin
  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers

Signature verification

Purpose of the Signature

The signature acts as a cryptographic proof that the request has been sent by SHOPLINE, which is generated by combining app proxy secret (a secret key known only to your system) with the query strings of the request

Generation Process

Step 1: Obtain and store the App Proxy Secret

  • Retrieve your App Proxy Secret, which should be securely stored and accessible in your environment
  • This is a unique key can be found in SHOPLINE app proxy set up section

Step 2: Parse and Sort the Query Strings

  • Extract the query string parameters from the incoming request
  • Sort these parameters alphabetically by key. This step is crucial to ensure consistency in signature generation, as the order of parameters in a query string can vary
# Original json
{
  "b": 1,
  "c": { c: 1, b: 2, a: 3},
  "a": 3
}
# Sorted json
{
  "a": 3
  "b": 1
  "c": {
      a: 3
      b: 2
      c: 1
  }
}

Step 3: Generate the Signature

Use the HMAC-SHA256 algorithm to generate the signature with app proxy secret & the sorted query strings (example will be provided)

Remark: The process is deterministic, meaning the same input (secret key and sorted query strings) will always produce the same output (signature)

The following pseudo-code illustrate the process of the generation

# step 1 - get all the messages
const appProxySecret = {your_app_proxy_secret}
const payload = req.query // obtain it from request query strings

# step 2 - serialization
const sortedPayload = sortByKeys(payload) // sort the payload, see below section for sorting the payload
const message = JSON.stringify(sortedPayload); // stringify it

# step 3 - generate signature
const hash = crypto
  .createHmac('sha256', appProxySecret) // use app secret as key to create hmac
  .update(message) // add the message
  .digest('hex'); // generate disgest