Zephr User Guide

Login Extension

39 views 0

The Zephr login extension plugin allows Zephr customers to import their users with legacy password details but still have their users log in as standard Zephr users. This is achieved by processing the legacy password details as a user logs in, converting them to Zephr’s standard bcrypt format.


  • Enables login for users who have been imported to Zephr with password details in the following formats:
    • MD5
    • bcrypt
    • SHA-256
    • SHA-512
    • Drupal Hash
    • PBKDF2
    • PWDTK (an alternative implementation of PBKDF2)
  • As users login, their credentials are converted to Zephr’s highly secure bcrypt format; after a user has logged in once, their future logins are handled by Zephr’s core user authentication mechanism.
  • All legacy logins are entirely transparent to end users: there is no difference in user experience for a user who has been imported to Zephr with legacy credentials compared to a user who is created directly in Zephr.

Configuring the HubSpot Extension

To enable the Login Extension within Zephr, navigate to Settings > Extensions > Login Extension. If you cannot see the HubSpot option in your list of Extensions, email support@zephr.com.

To active the Login Extension, simply confirm which of your Sites the extension should be active on. To do this, use the toggles for each site under the Activate Plugin section, or choose Select All Sites.

Mailchimp - Plugin Activation

Once completed, click Save.


The plugin is active in the background and will orchestrate login for any users that are imported with legacy credentials.

To import a legacy user, you will need to make POSTs to /v3/users as detailed in the Zephr Admin API documentation. However in the validators section, you will need to include a legacy_password field, the value of which will be a stringified JSON object including fields relating to the user’s credentials (these vary by algorithm: please check below for details).

Here is an example, providing some md5 legacy password details:

    "identifiers": {
        "email_address": "bob.smith@company.com"
    "validators": {
        "legacy_password": "{\"algorithm\": \"md5\",\"hash\": \"cc58db7c46ddbee969c257af0c505498\", \"salt\": \"mySuperSecureHash\"}"
    "attributes": {
        "first-name": "Bob",
        "last-name": "Smith"

Each of the supported legacy password algorithms may require different fields in the legacy_password object.

For ease of reading, the JSON objects below are presented as plain JSON. They must be stringified before being used to create users with legacy password credentials.


    "algorithm": "md5",
    "salt": "<salt>", // string
    "hash": "<hash>" // string


    "algorithm": "bcrypt",
    "hash": "<hash>", // string
    "salt": "<salt>", // string
    "rounds": <rounds> // number (int)

Note: bcrypt hashes must be split into their constituent parts before submission as per the example here.

For a hash of $2a$12$5gL.SoMV.kKijer1iArWWeH7DJFqBL1NvBRoW2cGC4xHZquPleauO

  • The red section is the bcrypt version (not needed).
  • The blue section is the cost factor. The cost factor is the base-2 exponent which gives the number of rounds of hashing to which the string has been subjected. To calculate the number of rounds from the cost factor calculate the output of 2<cost_factor>. For example: a cost factor of 12 would result in a number of rounds of 4096 (212 = 4096). Once you know the number of rounds for your hashes, please provide this as an integer in the rounds field.
  • The section in green is the salt. Add this as a string to the salt field (there will be a dollar sign – $ – separating the rounds from the salt: do not include this).
  • The section in pink is the hash. Add this as a string to the hash field.

A full JSON payload to create a user with a legacy hash as above would look like:

    "identifiers": {
        "email_address": "alice.smith@company.com"
    "validators": {
        "legacy_password": "{\"algorithm\": \"bcrypt\",\"hash\": \"H7DJFqBL1NvBRoW2cGC4xHZquPleauO\", \"salt\": \"5gL.SoMV.kKijer1iArWWe\", \"rounds\": 4096}"
    "attributes": {
        "first-name": "Alice",
        "last-name": "Smith"


    "algorithm": "SHA-256",
    "salt": "<salt>",        // string
    "hash": "<hash>"         // string


    "algorithm": "sha512",
    "salt": "<salt>",        // string
    "hash": "<hash>",        // string
    "rounds": <rounds>       // number (int)

Please note that the algorithm should be provided as sha512.

Drupal Hash

    "algorithm": "DRUPAL-HASH",
    "hash": "<hash>"            // string


    "algorithm": "pbkdf2",                      // REQUIRED: string (must be "pbkdf2")
    "hash": "<hash>",                           // REQUIRED: string
    "salt": "<salt>",                           // REQUIRED: string
    "rounds": <rounds>,                         // REQUIRED: number (int)
    "keyLength": <keyLength>,                   // OPTIONAL: number (int); default: 128
    "cipher": "<cipher>",                       // OPTIONAL: string (one of: "sha-1", "sha-256"); default: "sha-1"
    "saltBase64EncodedPostHashing": <boolean>   // OPTIONAL: boolean; default: true

Zephr’s handling for PBKDF2 legacy password hashes currently supports SHA-1 and SHA-256 ciphers.

Depending on the system from which you are exporting the hashes, you may need to split up the data into its constituent parts before users are imported to Zephr. Portable hashes of this usually have segments of data delimited by a $ character. Example hash:


  • Algorithm
  • Rounds
  • Salt
  • Hash

Note: the hash above is purely to demonstrate delimiting: characters do not represent a valid hash.

By default, only 4 of the fields above are required in the legacy password object:

  • algorithm (must be pbkdf2)
  • hash (must be base64 encoded)
  • salt
  • rounds

There are also some optional fields that can be used to declare the settings that were used to originally hash the passwords in the system from which you are exporting:

  • keyLength: the number of bits for the key. Defaults to 128, but can be set to a value such as 256 or 512 etc.
  • cipher: the cipher used in the algorithm. Defaults to sha-1. If declared, the value of this field must be one of sha-1 or sha-256.
  • saltBase64EncodedPostHashing: declares whether the salt value provided has been base 64 encoded since it was used to create the hash. Defaults to true. If the salts you have provided are the exact strings that were used to originally salt the hashes (i.e. they have not since been base 64 encoded), please set this field to false.


Zephr provider support for hashes generated by the alternative PWDTK implementation of PBKDF2.

    "algorithm": "pbkdf2-pwdtk",
    "hash": "<hash>", // string (hex)
    "saltLength": <saltLength>, // number (int)
    "iterations": <iterations> // number (int)