English
Security
Authorization
With the exception of a few functions that do not require authorization, most functions require an API key to be sent in the request headers. The name of the header used is Authorization.
Key Types
There are 7 types of API keys that can be used to make requests to the API.
API Type Key: this key is static and is not tied to a session. It can be generated from the administration console. This is the most commonly used authentication method for server-to-server integrations.
Never use this type of key in a client-side web application, as it could be exposed.
This type of key starts with the letter A.
Each API key can be restricted to one or more specific IP addresses. This security feature is optional, but highly recommended if all your requests originate from a known range of addresses. You can configure the allowed address ranges from the eZmax administration console.
Each API key can also be configured with specific permissions. We strongly recommend following the Principle of Least Privilege. For example, rather than granting all permissions to a single API key, it is preferable to create a separate API key for each application, with only the permissions required for its operation.
You can configure the permissions associated with API keys in the eZmax administration console.
Delegated Type Key: this key has an expiration period. It is generally used in mobile or web applications where it is not possible to use an API Type Key, as it could be exposed.
The application communicates with a server-side component that generates a Delegated Type Key using an API Type Key. The Delegated Type Key can then be used by the mobile or web application without exposing the API Type Key.
This type of key starts with the letter D.
User Type Key: this key is tied to a session and can be retrieved after successful authentication.
This is the type of key used when you are logged in to our web applications. This type of key is not normally used directly when developing an integration.
This type of key starts with the letter U.
Presigned Type Key: these keys are used to generate presigned URLs. They have an expiration date configured at the time of signing.
This type of key starts with the letter P.
Special Type Key: these keys are reserved for specific situations where the other types of keys cannot be used.
This type of key starts with the letter S.
Impersonation Type Key: this key has an expiration period and is used to make requests in the context of another user. This type of key allows you to impersonate another user's identity when executing requests.
This type of key starts with the letter I.
Webhook Type Key: this key is used when a webhook is sent to your server and request signing is enabled.
This type of key starts with the letter W.
Request signing
Request signing is a process used to sign a request using a secret that is never transmitted over the network.
This process enhances security in the event that an API key is compromised or during a MITM (Man-in-the-Middle) attack. It also helps prevent request tampering and replay attacks.
Since all requests must use HTTPS, this type of attack is difficult to carry out. However, some clients may not be aware that their underlying library does not properly validate SSL certificates or that their application could expose their API key if it is not properly protected.
The requirements for request signing vary depending on the type of key being used.
For API Type Keys (the most commonly used type) and Webhook Type Keys, you can configure whether request signing is required from the eZmax Administration Console. For all other key types, requests must be signed; otherwise, they will fail. Request signing is strongly recommended to enhance security.
If you use our SDKs, most of them automatically support request signing, which greatly simplifies its use. If this feature is not available in one of our SDKs or if you are developing a custom integration, implementation requires a little more work, but it is still strongly recommended.
The following section explains how to implement request signing yourself.
Custom Request Signing Implementation
To apply a signature to your request, you will need to add 3 or 4 additional HTTP headers to the request:
- Ezmax-Date
- Ezmax-Expiration (Optional)
- Ezmax-Fingerprint
- Ezmax-Signature
Ezmax-Date
Ezmax-Date corresponds to the date and time at which you send the request. This value must be in ISO 8601 format, which supports time zones. You can therefore use your local time zone or Coordinated Universal Time (UTC). Please note that some implementations add milliseconds to the formatted date, which is not accepted by the API (for example, the toISOString() function in JavaScript).
A tolerance of ±5 minutes is allowed between the date and time you provide and those of the server. Therefore, make sure that your clock is properly synchronized. Using an NTP server is recommended to ensure accurate time.
Calculate the date and time as close as possible to the actual time the request is sent. For example, avoid setting the current time at the beginning of a long-running script that sends 50 requests to the server with the same date and time, as this could result in errors related to the time difference.
Examples:
- 2000-12-31T23:59:59Z
- 2000-12-31T23:59:59-05:00
Ezmax-Expiration
Ezmax-Expiration is optional. It must be a positive integer representing the number of minutes (starting from Ezmax-Date) after which the signed request will be considered expired.
Ezmax-Fingerprint
Ezmax-Fingerprint is a fingerprint representing the request you are sending. Any modification made to any part of the request will produce a different fingerprint. The hash is calculated using SHA256. Most programming languages provide an implementation of SHA256. To ensure that your implementation produces the expected values, try hashing the value "foo"; it should produce the value "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae".
To calculate the fingerprint, you must concatenate the method, URL, body, API key, date, and expiration (expiration should only be included if it is defined). All of these values must be separated by a newline character (\n).
Make sure that your method is in uppercase (it must be "GET", not "Get" or "get"). Make sure that the scheme and host of the URL are in lowercase (it must be "https://www.example.com", not "HTTPS://WWW.EXAMPLE.COM"). Also, make sure that the URI portion of the URL is properly encoded according to the URL format (it must be "/Path%20with%20Spaces/?Key=Value%20with%20Spaces", not "/Path with Spaces/?Key=Value with Spaces"). If the body is empty (for example, GET requests do not have a body), use an empty string.
Once the SHA256 hash has been calculated, add the prefix "v1=", which serves as a version identifier to allow for future evolution.
Here is an example implementation in PHP:
php
public static function getFingerprintV1(string $sAuthorization, string $dtDate, string $sMethod, string $sURL, string $sBody = '', ?int $iExpiration = null): string {
$sContentToHash = "$sMethod\n$sURL\n$sBody\n$sAuthorization\n$dtDate" . (is_null($iExpiration) ? '' : "\n$iExpiration");
return 'v1=' . hash('sha256', $sContentToHash);
}1
2
3
4
2
3
4
Here are two examples of what GET and POST request fingerprints may look like. You can validate that your algorithm is working correctly by using these sample values and comparing them with the expected values. In the example below, the literal "\n" character must be replaced with a newline character.
text
GET\n
https://prod.api.appcluster01.ca-central-1.ezmax.com/rest/1/object/activesession/getCurrent\n
\n
ThisIsMyAuthorizationKey\n
2000-12-31T23:59:59Z1
2
3
4
5
2
3
4
5
Expected result for Ezmax-Fingerprint (GET): v1=8f6f3ed75edb6e2cbe777b4fda5cab1a6adaebadc758780eb82c3d49934f354a
text
POST\n
https://prod.api.global.ezmax.com/1/module/sspr/sendUsernames\n
{"pksCustomerCode": "demo","fkiLanguageID": "2","eUserTypeSSPR": "Native","sEmailAddress": "email@example.com"}\n
ThisIsMyAuthorizationKey\n
2000-12-31T23:59:59Z1
2
3
4
5
2
3
4
5
Expected result for Ezmax-Fingerprint (POST): v1=da829efd4c2a8722ce17d3cf977c4e86adf7d2dbaa47e1b2ee3b4ade6c9cb642
Ezmax-Signature
Ezmax-Signature is the actual signature proving that the request was generated by the key owner using their secret. The signature is calculated using HMAC and SHA256. Do not confuse SHA256 (also known as SHA2-256) with SHA3-256; they are two distinct algorithms. Most programming languages provide an implementation of HMAC with SHA256. To ensure that your implementation produces the expected values, try hashing the value "foo" with the key "bar"; it should produce the following value: "147933218aaabc0b8b10a2b3a5c34684c8d94341bcf10a4736dc7270f7741851".
To calculate the signature, you must concatenate Ezmax-Fingerprint, the API key, and Ezmax-Date. The three values must be concatenated without a separator. Then, calculate the HMAC using SHA256 with your secret as the key.
Once the HMAC-SHA256 hash has been calculated, add the prefix "v1=", which serves as a version identifier to allow for future evolution.
Here is an example implementation in PHP:
php
public static function getSignatureV1(string $sAuthorization, string $dtDate, string $sFingerprint, string $sSecret): string {
$sContentToSign = "$sFingerprint$sAuthorization$dtDate";
return 'v1=' . hash_hmac('sha256', $sContentToSign, $sSecret);
}1
2
3
4
2
3
4
Here are two examples of what GET and POST request signatures may look like. You can validate that your algorithm is working correctly by using these sample values and comparing them with the expected values. In the examples below, we used the same API key, fingerprint, and date as in the fingerprint section above. The only new variable is the secret, which is "ThisIsTheSecretAssociatedToTheAuthorizationKey" in this example.
Example of a calculation for a request (GET):
text
v1=8f6f3ed75edb6e2cbe777b4fda5cab1a6adaebadc758780eb82c3d49934f354aThisIsMyAuthorizationKey2000-12-31T23:59:59Z1
Expected result for Ezmax-Signature (GET):
text
v1=3a95fde64d27527745bcb0dd91be8caf7917c6778197e22d1d56c87245f979f51
Example of a calculation for a request (POST):
text
v1=da829efd4c2a8722ce17d3cf977c4e86adf7d2dbaa47e1b2ee3b4ade6c9cb642ThisIsMyAuthorizationKey2000-12-31T23:59:59Z1
Expected result for Ezmax-Signature (POST):
text
v1=b924269145ff74f64985992325e82e79445bbe3aa994b90d2f24b3023b8d5f091
Example Summary
The entire process has been detailed above, but here is a summary of what your HTTP headers should look like to sign these example requests, using the following common variables:
| Variable | Example Value |
|---|---|
| Date | 2000-12-31T23:59:59Z |
| Authorization | ThisIsMyAuthorizationKey |
| Secret | ThisIsTheSecretAssociatedToTheAuthorizationKey |
For a GET request to https://prod.api.appcluster01.ca-central-1.ezmax.com/rest/1/object/activesession/getCurrent:
http
Authorization: ThisIsMyAuthorizationKey
Ezmax-Date: 2000-12-31T23:59:59Z
Ezmax-Fingerprint: v1=8f6f3ed75edb6e2cbe777b4fda5cab1a6adaebadc758780eb82c3d49934f354a
Ezmax-Signature: v1=3a95fde64d27527745bcb0dd91be8caf7917c6778197e22d1d56c87245f979f51
2
3
4
2
3
4
For a POST request to https://prod.api.global.ezmax.com/1/module/sspr/sendUsernames with the following body: '{"pksCustomerCode": "demo","fkiLanguageID": "2","eUserTypeSSPR": "Native","sEmailAddress": "email@example.com"}':
http
Authorization: ThisIsMyAuthorizationKey
Ezmax-Date: 2000-12-31T23:59:59Z
Ezmax-Fingerprint: v1=da829efd4c2a8722ce17d3cf977c4e86adf7d2dbaa47e1b2ee3b4ade6c9cb642
Ezmax-Signature: v1=b924269145ff74f64985992325e82e79445bbe3aa994b90d2f24b3023b8d5f091
2
3
4
2
3
4