Automatically Creating Third-Party Client Applications
Introduction
CargoX Platform provides an /apps/ API endpoint to selected partners (referred to as Suppliers hereon) that have a need to create client applications for multiple integrations. An example would be an application which does not run in the cloud but needs to be installed on-premise. It makes sense for each such installation to have a separate client_id and client_secret. This endpoint is suitable for such specific cases.
Each supplier is issued an unique ID and a shared secret. The combination of both is used to request new OAuth credentials.
Please keep these credentials extremely safe. They should not be written down. Ideally, they should be baked into the application itself. If that's not possible and they need to be a part of configuration, make sure that the configuration is encrypted.
If these credentials are compromised an attacker may be able to gain access to all existing instances of your application. CargoX might not be able to detect or influence this.
If you need to become a software supplier, contact our support at [email protected].
Authorizing API requests: creating a hash
Each request to this API is authorized using your credentials. This is achieved by calculating a timestamped HMAC hash using your issued shared secret.
Message that uniquely defines a client application consists of three parts:
| Parameter key | Parameter name | Description |
|---|---|---|
app_id | Instance (Request) ID | The unique request ID. Every instance must use a different ID. |
supplier_id | Supplier ID | Your supplier identification code, provided by CargoX. |
timestamp | Unix timestamp | Current (Unix) time, truncated down to the last minute. |
app_id (Application ID) is the unique ID of your request. CargoX will match the app_id and supplier_id in its database and issue only one set of client credentials per combination. This enables you to call the endpoint multiple times (e.g. in case of network errors) and be certain you will always get the same result.
How you pick the app_id is up to you, just make sure they do not overlap. A good ID would be something that does not change -- e.g. you could either generate it on the first run and save it in the database, or use a combination of custom prefix and network card's MAC number.
The HMAC needs to be calculated using the following formula:
HMAC('{app_id}-{supplier_id}-{timestamp}', '{supplier_secret}')
Here are a couple of examples of how to calculate the hash.
- Python
- PHP
- JavaScript
import time
import hmac
import hashlib
APP_ID = get_application_id()
SUPPLIER_ID = 'e225d965-205d-4187-b9bd-103f1a54c4d1'
SECRET = '3c49474297c6338cce2788ec0ccee44fe38199bd74de3a03802404b2a7b62cfc'
timestamp = int(time.time() // 60 * 60)
message = '{app_id}-{supplier_id}-{timestamp}'.format(app_id=APP_ID,
supplier_id=SUPPLIER_ID,
timestamp=timestamp)
hash = hmac.new(bytes.fromhex(SECRET), msg=message.encode('utf-8'), digestmod=hashlib.sha256).hexdigest()
$APP_ID = get_application_id();
$SUPPLIER_ID = 'e225d965-205d-4187-b9bd-103f1a54c4d1';
$SECRET = '3c49474297c6338cce2788ec0ccee44fe38199bd74de3a03802404b2a7b62cfc';
$timestamp = intval(intdiv(time(), 60) * 60);
$message = sprintf('%s-%s-%d', $APP_ID, $SUPPLIER_ID, $timestamp);
$hash = hash_hmac('sha256', $message, hex2bin($SECRET));
// Define this somewhere within your app, as they do not change
const app_id = get_application_id();
const supplier_id = 'e225d965-205d-4187-b9bd-103f1a54c4d1';
const secret = '3c49474297c6338cce2788ec0ccee44fe38199bd74de3a03802404b2a7b62cfc';
let timestamp = Math.floor(Date.now() / 1000 / 60) * 60;
// The following code uses CryptoJS: https://cryptojs.gitbook.io/docs/
var hash = CryptoJS.HmacSHA256(`${app_id}-${supplier_id}-${timestamp}`, `${secret}`);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
To prevent replay attacks, the HMAC code includes the timestamp. This means that your request will not be valid indefinitely. More specifically, the server will accept only requests with a timestamp of current and previous minute (to prevent race conditions where the HMAC was generated just before the clock rolls around).
In general, this should be a safe margin. If you're running into issues where your hash code validation is failing, make sure you verify your clock is set up correctly first.
Create a client application
To create a new application, call the /apps endpoint with the following parameters:
| Parameter key | Parameter name | Description |
|---|---|---|
app_id | Instance (Request) ID | The unique request ID. Every instance must use a different ID. |
supplier_id | Supplier ID | Your supplier identification code, provided by CargoX. |
hash | HMAC-calculated hash | Unique hash calculated for this message. |
email | Supplier's email | Email connected with this account. Must be unique for each instance. |
Example: To create a new client application, send the following request:
curl --location --request POST 'https://cargox.digital/api/v3/apps/' \
--form 'app_id=supplier-D89FCA8719BDE9F18C' \
--form 'supplier_id=e225d965-205d-4187-b9bd-103f1a54c4d1' \
--form 'hash=4fef62145de199f3351f6f64f32234f6126d77d66f5614a9c5aa4cdf5f8dcdd9' \
--form '[email protected]'
The above request returns OAuth credentials and application status as a JSON response:
{
"client_id": "rP9wBF8zn8eipsDtYRM5JcnLOazTIl75JXswT20H",
"client_secret": "6819upD3VqLLjvQLVCfTTDKqn4iYBtKdggGZ8km7PYHIWAtpSL0aHuIze3yWOOMBr1AjAdMgvsdoNeA0zgSBLHU2pbKVFkoGidj2x93rsDCWr3nqlgBBTpCEbVaYPaM9",
"allowed_ip_ranges": "",
"status": "active"
}
As explained previously, subsequent requests with the same app_id and supplier_id will return existing credentials without creating a new application.
If your hash cannot be validated, you will get back a 403 FORBIDDEN error.
Depending on your agreement with CargoX, the credentials may be enabled automatically. If this is the case, status will display as "status": "active" and you can start using your newly assigned credentials straight away. If the credentials were issued but are not yet confirmed, the status will be shown as "status": "pending".
In case of pending credentials your application should regularly check in with CargoX (see the call below) and inquire about the status of credentials until they switch to active state.
Fetch application OAuth credentials status
To fetch existing client application OAuth credentials, make the following request:
curl --location --request GET 'https://cargox.digital/api/v3/apps/supplier-D89FCA8719BDE9F18C/?supplier_id=e225d965-205d-4187-b9bd-103f1a54c4d1&hash=411b0dbf528c65219b92c350db9411651d2e5578a0185fc326dd9a09ab7ae487'
The above request returns OAuth credentials and application status as a JSON response:
{
"client_id": "rP9wBF8zn8eipsDtYRM5JcnLOazTIl75JXswT20H",
"client_secret": "6819upD3VqLLjvQLVCfTTDKqn4iYBtKdggGZ8km7PYHIWAtpSL0aHuIze3yWOOMBr1AjAdMgvsdoNeA0zgSBLHU2pbKVFkoGidj2x93rsDCWr3nqlgBBTpCEbVaYPaM9",
"allowed_ip_ranges": "",
"status": "active"
}