<img src="abc.png" />
    
call to replace anchor tags contains '/admin' in href

Multipass

Let's say you are the owner of a successful website forum. All of your users must log in to the forum to contribute. Members of your forum can then purchase a forum t-shirt through your StoreHippo store. Unfortunately, your users have to log in to the forum first and then log in to yourStoreHippo store before they can purchase a t-shirt.

Multipass login is for store owners who have a separate website and aStoreHippo store. It redirects users from the website to theStoreHippo store and seamlessly logs them in with the same email address they used to sign up for the original website.

Implementation

1. Enable Multipass login through your store admin

Log in to your store admin and go to the Settings > MISC page.
Select Multipass. Once enabled, a secret will be visible underneath. You will need the secret in order to generate tokens to log your customers into your Shopify store. Make sure you keep your secret private.

2. Encode your customer information using JSON

The customer information is represented as a hash which must contain at least the email address of the customer. You can also include the customer's first name, last name.
A minimal example, containing all required fields, might look like this:

{
  email: "xyz@abc.com",
  first_name: "Xyz",
}


3. Encrypt the JSON data using AES

To generate a valid multipass login token, you need the secret given to you in your StoreHippo admin. The secret is used to derive two cryptographic keys — one for encryption and one for signing. This key derivation is done through the use of the SHA-256 hash function (the first 128 bit are used as encryption key and the last 128 bit are used as signature key).

The encryption provides confidentiality. It makes sure that no one can read the customer data. As encryption cipher, we use the AES algorithm (128 bit key length, CBC mode of operation, random initialization vector).


4. Sign the encrypted data using HMAC

The signature (also called message authentication code) provides authenticity. It makes sure that the multipass token is authentic and hasn't been tampered with. We use the HMAC algorithm with a SHA-256 hash function and we sign the encrypted JSON data from step 2 (not the plaintext JSON data from step 1).

5. Base64 encode the binary data

The multipass login token now consists of the 128 bit initialization vector, a variable length ciphertext, and a 256 bit signature (in this order). This data is encoded using base64 (URL-safe variant, RFC 4648).

6. Redirect your customer to your StoreHippo store

Once you have the token, you should trigger a HTTP GET request to your StoreHippo store.

GET /ms/login/multipass/insert_token_here

When the request is successful (e.g. the token is valid and not expired), the customer will be logged in to yourStoreHippo store.



Example implementation

The following shows a basic example implementation of the token generation in PHP.

<?php
date_default_timezone_set("UTC");

class StoreHippoMultipass {
    private $encryption_key;
    private $signature_key;

    public function __construct($multipass_secret) {
        // Use the Multipass secret to derive two cryptographic keys,
        // one for encryption, one for signing
        $key_material = md5($multipass_secret);
        $this->encryption_key = substr($key_material, 0, 16);
        $this->signature_key = substr($key_material, 16, 16);
    }

    public function generate_token($customer_data_hash) {
        // Store the current time in ISO8601 format.
        // The token will only be valid for a small timeframe around this timestamp.
        $customer_data_hash["created_on"] = date("c");

        // Serialize the customer data to JSON and encrypt it
        $ciphertext = $this->encrypt(json_encode($customer_data_hash));

        // Create a signature (message authentication code) of the ciphertext
        // and encode everything using URL-safe Base64 (RFC 4648)
        return strtr(base64_encode($ciphertext . $this->sign($ciphertext)), '+/', '-_');
    }

    private function encrypt($plaintext) {
        // Use a random IV
        $iv = openssl_random_pseudo_bytes(16);

        // Use IV as first block of ciphertext
        return $iv . openssl_encrypt($plaintext, "AES-128-CBC", $this->encryption_key, OPENSSL_RAW_DATA, $iv);
    }

    private function sign($data) {
        return hash_hmac("sha256", $data, $this->signature_key, true);
    }
}

$customer_data = array(
    "email" => "xyz@abc.com"
);

$multipass = new StoreHippoMultipass("multipass secret from shop admin");
$token = $multipass->generate_token($customer_data);
?>


The following shows a basic example implementation of the token generation in NodeJS.

const crypto = require('crypto');
const KEY = "multipass secret from admin";
let hash = crypto.createHash("md5").update(KEY).digest('hex');
let _encryptionKey = hash.slice(0, 16);
let _signingKey = hash.slice(16, 32);
let calculateHmac = function (data, key) {
    return crypto.createHmac('SHA256', key).update(data).digest();
};
let encryptToken = function (key, data, iv) {
    let cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
    return Buffer.concat([iv, cipher.update(data, 'utf8'), cipher.final()]);
};

let user = {email: "test.user@store.com", created_on: "2013-04-11T15:16:23-04:89"};
let iv = crypto.randomBytes(16);
let verUser = encryptToken(_encryptionKey, JSON.stringify(user), iv);
let verHmac = calculateHmac(_signingKey, verUser);

let token = Buffer.concat([verUser, verHmac]).toString('base64');
token = token.replace(/\+/g, '-') // Replace + with -
    .replace(/\//g, '_'); // Replace / with _
console.log(token);