Server side integration

Server side integration allows you to communicate with ZealiD backend to be able to upload, sign and retrieve documents or data.

First steps

There are few things before you get started...

πŸ“˜

Prerequisites for integrating ZealiD:

  • Have ZealiD app
    • Receive your client_id and client_secret
    • use HMAC_STRING generator to be able to generate hmac_string for Authentication header in your requests
    • use HMAC_REQUEST to generate and send an authenticated request

Below you can find a couple of different scripts for generating hmac_string or for sending hmac requests

#!/bin/bash
if [ $# -eq 5 ]
then
    export LC_ALL=C.UTF-8
    clientid=$1
    clientsecret=$2
    uripart=$3
    method=$4
    payload=$5
    timestamp=$(date +%s)
    nonce=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 60)
    base="https://core-hermes.zealid.com"
    fulluri="$base$uripart"
    reqstr="$method $uripart"
    auth_string="$clientid$nonce$timestamp$reqstr$payload"
    hmacsig=$(echo -n $auth_string | openssl dgst -binary -sha512 -hmac "$clientsecret" | base64)
    hmac="client_id=\"$clientid\",ts=\"$timestamp\",nonce=\"$nonce\",signature=\"$hmacsig\""
    echo "HMAC_STRING $hmac "
else
    echo "Five input params required:"
    echo "1 - client_id"
    echo "2 - client_secret"
    echo "3 - request_url - everything after https://hermes-dev.zealid.com"
    echo "4 - request_method"
    echo "5 - request_payload"
fi
import sys
import secrets
import time
import base64
import hmac
import json

def hmac_string(method, url, client, payload=None):
    request_method = method
    full_path = '/' + '/'.join(url.split('/')[3:])
    client_id = client['id']
    secret = client['secret']
    nonce = secrets.token_urlsafe(32)
    ts = int(time.time())
    request_string = f"{request_method} {full_path}"
    auth_string = f"{client_id}{nonce}{ts}{request_string}{payload if payload else ''}"
    signature = base64.b64encode(
      hmac.new(
        secret.encode("utf-8"),
        auth_string.encode("utf-8"),
        "sha512"
      ).digest()
    ).decode("utf-8")
    hmac_string = f'client_id="{client_id}",ts="{ts}",nonce="{nonce}",signature="{signature}"'
    return hmac_string


if len(sys.argv) != 6:
    print("Five input params required:")
    print("1 - client_id")
    print("2 - client_secret")
    print("3 - request_url - everything after https://hermes-dev.zealid.com")
    print("4 - request_method")
    print("5 - request_payload")
else:
    clientid = sys.argv[1]
    clientsecret = sys.argv[2]
    uripart = sys.argv[3]
    method = sys.argv[4]
    payload = sys.argv[5]
    base_url = "https://core-hermes.zealid.com"
    hmac_string = hmac_string(method,
                              f"{base_url}{uripart}",
                              {"id": clientid, "secret": clientsecret},
                              payload
                             )
    print(f"HMAC_STRING: {hmac_string}")
#!/bin/bash
if [ $# -eq 5 ]
then
    export LC_ALL=C.UTF-8
    clientid=$1
    clientsecret=$2
    uripart=$3
    method=$4
    payload=$5
    timestamp=$(date +%s)
    nonce=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 60)
    base="https://core-hermes.zealid.com"
    fulluri="$base$uripart"
    reqstr="$method $uripart"
    auth_string="$clientid$nonce$timestamp$reqstr$payload"
    hmacsig=$(echo -n $auth_string | openssl dgst -binary -sha512 -hmac "$clientsecret" | base64)
    hmac="client_id=\"$clientid\",ts=\"$timestamp\",nonce=\"$nonce\",signature=\"$hmacsig\""
    curl $fulluri\
         -X $method\
         -H "Authorization: HMAC $hmac"\
         -H "Content-Type: application/json"\
         -d "$payload"
else
    echo "Five input params required:"
    echo "1 - client_id"
    echo "2 - client_secret"
    echo "3 - request_url - everything after https://hermes-dev.zealid.com"
    echo "4 - request_method"
    echo "5 - request_payload"
fi
import sys
import secrets
import time
import base64
import hmac
import json
import requests

def hmac_request(method, url, client, headers={}, payload=None):
    request_method = method
    full_path = '/' + '/'.join(url.split('/')[3:])
    client_id = client['id']
    secret = client['secret']
    nonce = secrets.token_urlsafe(32)
    ts = int(time.time())
    request_string = f"{request_method} {full_path}"

    session = requests.session()
    request = requests.Request(method,
                               url,
                               headers=headers,
                               data=payload)

    prepped = request.prepare()
    payload = prepped.body

    auth_string = f"{client_id}{nonce}{ts}{request_string}{payload if payload else ''}"
    signature = base64.b64encode(
      hmac.new(
        secret.encode("utf-8"), auth_string.encode("utf-8"), "sha512"
      ).digest()
    ).decode("utf-8")
    hmac_string = f'client_id="{client_id}",ts="{ts}",nonce="{nonce}",signature="{signature}"'
    print(f"auth_string: {auth_string}")
    print(f"hmac_string: {hmac_string}")
    headers.update({"Authorization": f"HMAC {hmac_string}"})
    prepped.headers.update(headers)  # this is OK
    response = session.send(prepped)
    try:
        result = response.json()
    expect:
        result = response.content
    return  result


if len(sys.argv) != 6:
    print("Five input params required:")
    print("1 - client_id")
    print("2 - client_secret")
    print("3 - request_url - everything after https://hermes-dev.zealid.com")
    print("4 - request_method")
    print("5 - request_payload")
else:
    clientid = sys.argv[1]
    clientsecret = sys.argv[2]
    uripart = sys.argv[3]
    method = sys.argv[4]
    payload = sys.argv[5]
    base_url = "https://core-hermes.zealid.com"
    response = hmac_request(method,
                            f"{base_url}{uripart}",
                            {"id": clientid, "secret": clientsecret},
                            headers={"Content-type": "application/json"},
                            payload=payload
                           )
    print(f"{response}")

How to use hmac_string generation script

πŸ“˜

How to:

  • hmac_string generation script returns to you an hmac string that you need to include in the request Authentication header
  • hmac_string generation requires the whole request information
  • For more information about hmac and it's usage please refer to hmac guide

🚧

Be aware!

  • For all examples we expect you to pass payload as JSON!
    • Your request is expected to have Content-Type: application/json in headers!
    • HMAC_STRING value can be different depending if json is sorted or not
    • We recommend using hmac_string generators to generate hmac_string for API Reference tests
#For [get_token]
./hmac_string.sh "your_client_id" "your_client_secret" "/mediator/api/get_token" "POST" "{\"grant_type\":\"authorization_code\",\"code\":\"HERMES_CODE\",\"redirect_uri\":\"https://example.com\"}"

#For [get_data]
./hmac_string.sh "your_client_id" "your_client_secret" "/mediator/api/get_data" "POST" "{\"token\":\"HERMES_TOKEN\"}"

#For [get_documents]
./hmac_string.sh "your_client_id" "your_client_secret" "/mediator/api/user/CUSTOMER_ID/documents" "GET" ""

#For [upload]
./hmac_string.sh "your_client_id" "your_client_secret" "/mediator/api/upload/CUSTOMER_ID" "POST" "{\"content\":\"base64filecontent==\",\"digest\":\"sha1offile\",\"filename\":\"your_file_name.pdf\"}"

#For [upload_hash]
./hmac_string.sh "your_client_id" "your_client_secret" "/mediator/api/upload/hash/CUSTOMER_ID" "POST" "{\"content\":\"hashstring\",\"hashname\":\"your_hash_name\"}"

#for [sign QRcode]
./hmac_string.sh "your_client_id" "your_client_secret" "/mediator/api/sign" "POST" "{\"document_id\":\"DOCUMENT_ID\",\"title\":\"my_file.pdf\",\"redirect_url\":\"https://example.com\", \"customer_id\": \"CUSTOMER_ID\"}"
#For [get_token]
python3 hmac_string.py "your_client_id" "your_client_secret" "/mediator/api/get_token" "POST" "{\"grant_type\":\"authorization_code\",\"code\":\"YOUR_HERMES_CODE\",\"redirect_uri\":\"https://example.com\"}"

#For [get_data]
python3 hmac_string.py "your_client_id" "your_client_secret" "/mediator/api/get_data" "POST" "{\"token\":\"YOUR_HERMES_TOKEN\"}"

#For [get_documents]
python3 hmac_string.py "your_client_id" "your_client_secret" "/mediator/api/user/YOUR_CUSTOMER_ID/documents" "GET" ""

#For [upload]
python3 hmac_string.py "your_client_id" "your_client_secret" "/mediator/api/upload/YOUR_CUSTOMER_ID" "POST" "{\"content\":\"base64filecontent==\",\"digest\":\"sha1offile\",\"filename\":\"your_file_name.pdf\"}"

#For [upload_hash]
python3 hmac_string.py "your_client_id" "your_client_secret" "/mediator/api/upload/hash/CUSTOMER_ID" "POST" "{\"content\":\"hashstring\",\"hashname\":\"your_hash_name\"}"

#for [sign QRcode]
python3 hmac_string.py "your_client_id" "your_client_secret" "/mediator/api/sign" "POST" "{\"document_id\":\"YOUR_DOCUMENT_ID\",\"title\":\"my_file.pdf\",\"redirect_url\":\"https://example.com\", \"customer_id\": \"YOUR_CUSTOMER_ID\"}"

How to use HMAC request generation script

πŸ“˜

How to:

  • HMAC request generation scripts accept input in the same format as hmac_string generators
  • HMAC request generators actually executes HTTP(S) request with HMAC authentication

🚧

Be ware!

  • For all examples we expect you to pass payload as JSON!
  • HMAC_STRING value can be different depending if json is sorted or not
#for [get_token]
./hmac_curl.sh "your_client_id" "your_client_secret" "/mediator/api/get_token" "POST" "{\"grant_type\":\"authorization_code\",\"code\":\"HERMES_CODE\",\"redirect_uri\":\"https://example.com\"}"

#for [get_data]
./hmac_curl.sh "your_client_id" "your_client_secret" "/mediator/api/get_data" "POST" "{\"token\":\"HERMES_TOKEN\"}"

#for [get_documents]
./hmac_curl.sh "your_client_id" "your_client_secret" "/mediator/api/user/CUSTOMER_ID/documents" "GET" ""

#for [upload]
./hmac_curl.sh "your_client_id" "your_client_secret" "/mediator/api/upload/CUSTOMER_ID" "POST" "{\"content\":\"base64...\",\"digest\":\"sha1...\",\"filename\":\"your_file_name.pdf\"}"

#For [upload_hash]
./hmac_curl.sh "your_client_id" "your_client_secret" "/mediator/api/upload/hash/CUSTOMER_ID" "POST" "{\"content\":\"hashstring\",\"hashname\":\"your_hash_name\"}"

#for [sign QRcode]
./hmac_curl.sh "your_client_id" "your_client_secret" "/mediator/api/sign" "POST" "{\"document_id\":\"DOCUMENT_ID\",\"title\":\"my_file.pdf\",\"redirect_url\":\"https://example.com\", \"customer_id\": \"CUSTOMER_ID\"}"
#For [get_token]
python3 hmac_request.py "your_client_id" "your_client_secret" "/mediator/api/get_token" "POST" "{\"grant_type\":\"authorization_code\",\"code\":\"YOUR_HERMES_CODE\",\"redirect_uri\":\"https://example.com\"}"

#for [get_data]
python3 hmac_request.py "your_client_id" "your_client_secret" "/mediator/api/get_data" "POST" "{\"token\":\"YOUR_HERMES_TOKEN\"}"

#for [get_documents]
python3 hmac_request.py "your_client_id" "your_client_secret" "/mediator/api/user/YOUR_CUSTOMER_ID/documents" "GET" ""

#for [upload]
python3 hmac_request.py "your_client_id" "your_client_secret" "/mediator/api/upload/YOUR_CUSTOMER_ID" "POST" "{\"content\":\"base64...\",\"digest\":\"sha1...\",\"filename\":\"your_file_name.pdf\"}"

#For [upload_hash]
python3 hmac_request.py "your_client_id" "your_client_secret" "/mediator/api/upload/hash/CUSTOMER_ID" "POST" "{\"content\":\"hashstring\",\"hashname\":\"your_hash_name\"}"

#for [sign QRcode]
python3 hmac_request.py "your_client_id" "your_client_secret" "/mediator/api/sign" "POST" "{\"document_id\":\"YOUR_DOCUMENT_ID\",\"title\":\"my_file.pdf\",\"redirect_url\":\"https://example.com\", \"customer_id\": \"YOUR_CUSTOMER_ID\"}"

Retrieve your customer data and get ready for signing

To be able to upload, sign or retrieve documents or data, first of all, you need to authenticate yourself as a user

πŸ“˜

Prerequisites for actions with documents:

Generating authentication QR code

πŸ“˜

How to:

  • QR code scanning is initial step of your authentication which helps to map your identity with the help of your device
  • To be able to scan QR code you need the ZealiD app and successfully pass onboarding steps

🚧

Be aware!

  • your_client_id - The same client_id as you provide for HMAC authentication
  • After scanning qrcode and successfully confirming your authentication request you will be redirected and you will receive HERMES_CODE as url parameter
  • *Make sure you are targeting correct environment!
# NOTE: production environment

# Open in your browser:
curl https://core-hermes.zealid.com/mediator/web_embed/auth_link/start/hermes_orpheus_dev/hermes_orpheus_dev_provider/{your_client_id}



# NOTE: testing environment

# Open in your browser:
curl https://hermes-dev.zealid.com/mediator/web_embed/auth_link/start/hermes_orpheus_dev/hermes_orpheus_dev_provider/{your_client_id}
665

Steps:
1 - 2. Use the url provided above to GET a template with QR code
3 - 4. While QR code is on your screen - JS in browser is checking request status in server
5 - 7. Scan QR code with Your ZealiD App and confirm request with TouchiD or FaceiD
8. After successful confirmation you will be redirected and in new url you can find code=HERMES_CODE -> This is the HERMES_CODE that you will have to provide in get_token request

Expected response:
https://core-hermes.zealid.com/mediator/web_embed/auth_link/success/OKQQJZuQQWsh-DclxhwZDdo_DCd7LOSaqinIIjA35Ms?code=hermes_code_xHVSIv-A...

You are ready!

πŸ“˜

Congratulations!

  • You now have HERMES_CODE which you can use to finish your authentication process and start working with your documents
  • For further actions please refer to any of these documentations: