Français
Sécurité
Autorisation
À l'exception de quelques fonctions qui ne nécessitent aucune autorisation, la plupart des fonctions requièrent une clé API envoyée dans les en-têtes de la requête. Le nom de l'en-tête utilisé est "Authorization".
Types de clés
Il existe 7 types de clés API pouvant être utilisés pour effectuer des requêtes vers l'API.
Clé de type API (API Type Key) : cette clé est statique et n'est pas liée à une session. Elle peut être générée à partir de la console d'administration. Il s'agit du type d'authentification le plus couramment utilisé pour les intégrations de type server-to-server.
N'utilisez jamais ce type de clé dans une application Web côté client, puisqu'elle pourrait être exposée.
Ce type de clé commence par la lettre A.
Chaque clé API peut être restreinte à une ou plusieurs adresses IP spécifiques. Cette fonctionnalité de sécurité est optionnelle, mais fortement recommandée si toutes vos requêtes proviennent d'une plage d'adresses connue. Vous pouvez configurer les plages d'adresses autorisées à partir de la console d'administration eZmax.
Chaque clé API peut également être configurée avec des permissions spécifiques. Nous recommandons fortement d'appliquer le principe du moindre privilège (Least Privilege Principle). Par exemple, plutôt que d'accorder toutes les permissions à une seule clé API, il est préférable de créer une clé API distincte pour chaque application, avec uniquement les permissions nécessaires à son fonctionnement.
Vous pouvez configurer les permissions associées aux clés API dans la console d'administration eZmax.
Clé de type délégué (Delegated Type Key) : cette clé possède une durée d'expiration. Elle est généralement utilisée dans les applications mobiles ou Web où il n'est pas possible d'utiliser une clé de type API, puisqu'elle pourrait être exposée.
L'application communique avec une partie serveur qui génère une clé de type délégué à l'aide d'une clé de type API. La clé de type délégué peut ensuite être utilisée par l'application mobile ou l'application Web sans exposer la clé de type API.
Ce type de clé commence par la lettre D.
Clé de type utilisateur (User Type Key) : cette clé est liée à une session et peut être récupérée après une authentification réussie.
Il s'agit du type de clé utilisé lorsque vous êtes connecté à nos applications Web. Ce type de clé n'est normalement pas utilisé directement lors du développement d'une intégration.
Ce type de clé commence par la lettre U.
Clé de type pré-signé (Presigned Type Key) : ces clés sont utilisées pour générer des URL pré-signées. Elles possèdent une date d'expiration configurée au moment de la signature.
Ce type de clé commence par la lettre P.
Clé de type spécial (Special Type Key) : ces clés sont réservées aux situations particulières où les autres types de clés ne peuvent pas être utilisés.
Ce type de clé commence par la lettre S.
Clé de type usurpation d'identité (Impersonation Type Key) : cette clé possède une durée d'expiration et est utilisée pour effectuer des requêtes dans le contexte d'un autre utilisateur. Ce type de clé permet de simuler l'identité d'un autre utilisateur lors de l'exécution des requêtes.
Ce type de clé commence par la lettre I.
Clé de type webhook (Webhook Type Key) : cette clé est utilisée lorsqu'un webhook est envoyé vers votre serveur et que la signature des requêtes (request signing) est activée.
Ce type de clé commence par la lettre W.
Signature des requêtes
La signature des requêtes est un processus permettant de signer une requête à l'aide d'un secret qui n'est jamais transmis sur le réseau.
Ce processus améliore la sécurité dans le cas où une clé API serait compromise ou lors d'une attaque de type MITM (Man-in-the-Middle). Il permet également d'empêcher la manipulation des requêtes ainsi que les attaques par rejeu.
Comme toutes les requêtes doivent utiliser HTTPS, ce type d'attaque est difficile à réaliser. Toutefois, certains clients peuvent ne pas être conscients que leur bibliothèque sous-jacente ne valide pas correctement les certificats SSL ou que leur application pourrait exposer leur clé API si celle-ci n'est pas correctement protégée.
Les exigences relatives à la signature des requêtes varient selon le type de clé utilisé.
Pour les clés de type API (le type le plus couramment utilisé) et les clé de type webhook, vous pouvez configurer si la signature des requêtes est obligatoire ou non à partir de la console d'administration eZmax. Pour tous les autres types de clés, les requêtes doivent obligatoirement être signées, sinon elles échoueront. Il est fortement recommandé de signer les requêtes afin d'améliorer la sécurité.
Si vous utilisez nos SDK, la plupart d'entre eux prennent automatiquement en charge la signature des requêtes, ce qui simplifie grandement son utilisation. Si cette fonctionnalité n'est pas disponible dans l'un de nos SDK ou si vous développez une intégration personnalisée, l'implémentation demande un peu plus de travail, mais elle demeure fortement recommandée.
La section suivante explique comment implémenter vous-même la signature des requêtes.
Implémentation personnalisée de la signature des requêtes
Pour appliquer une signature à votre requête, vous devrez ajouter 3 ou 4 en-têtes HTTP supplémentaires à la requête :
- Ezmax-Date
- Ezmax-Expiration (Optionnel)
- Ezmax-Fingerprint
- Ezmax-Signature
Ezmax-Date
Ezmax-Date correspond à la date et à l'heure auxquelles vous envoyez la requête. Cette valeur doit être au format ISO 8601, qui prend en charge les fuseaux horaires. Vous pouvez donc utiliser votre fuseau horaire local ou le temps universel coordonné (UTC). Veuillez noter que certaines implémentations ajoutent des millisecondes à la date formatée, ce qui n'est pas accepté par l'API (par exemple, la fonction toISOString() de JavaScript).
Une tolérance de ±5 minutes est autorisée entre la date et l'heure que vous indiquez et celles du serveur. Assurez-vous donc que votre horloge est correctement synchronisée. L'utilisation d'un serveur NTP est recommandée pour garantir une heure précise.
Calculez la date et l'heure le plus près possible du moment réel où la requête est envoyée. Par exemple, évitez de définir l'heure actuelle au début d'un script de longue durée qui envoie 50 requêtes au serveur avec la même date et la même heure, car vous pourriez recevoir des erreurs liées au décalage horaire.
Exemples :
- 2000-12-31T23:59:59Z
- 2000-12-31T23:59:59-05:00
Ezmax-Expiration
Ezmax-Expiration est optionnel. Il doit s'agir d'un entier positif représentant le nombre de minutes (à partir de Ezmax-Date) après lesquelles la requête signée sera considérée comme expirée.
Ezmax-Fingerprint
Ezmax-Fingerprint est une empreinte (fingerprint) représentant la requête que vous envoyez. Toute modification apportée à une partie quelconque de la requête produira une empreinte différente. Le hachage est calculé à l'aide de SHA256. La plupart des langages de programmation offrent une implémentation de SHA256. Pour vous assurer que votre implémentation produit les valeurs attendues, essayez de hacher la valeur "foo" ; elle devrait produire la valeur "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae".
Pour calculer l'empreinte, vous devez concaténer la méthode, l'URL, le corps, la clé API, la date et l'expiration (l'expiration doit être ajoutée uniquement si elle est définie). Toutes ces valeurs doivent être séparées par un caractère de saut de ligne (\n).
Assurez-vous que votre méthode est en majuscules (elle doit être "GET", et non "Get" ou "get"). Assurez-vous que le schéma et l'hôte de l'URL sont en minuscules (elle doit être "https://www.example.com", et non "HTTPS://WWW.EXAMPLE.COM"). Assurez-vous également que la partie URI de l'URL est correctement encodée selon le format URL (elle doit être "/Path%20with%20Spaces/?Key=Value%20with%20Spaces", et non "/Path with Spaces/?Key=Value with Spaces"). Si le corps est vide (par exemple, les requêtes GET n'ont pas de corps), utilisez une chaîne vide.
Une fois le hachage SHA256 calculé, ajoutez le préfixe "v1=", qui sert d'identifiant de version afin de permettre une évolution future.
Voici un exemple d'implémentation en 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
Voici deux exemples de ce à quoi peuvent ressembler les empreintes de requêtes GET et POST. Vous pouvez valider le fonctionnement de votre algorithme en utilisant ces valeurs d'exemple et en les comparant aux valeurs attendues. Dans l'exemple ci-dessous, le caractère littéral "\n" doit être remplacé par un caractère de saut de ligne.
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
Résultat attendu pour 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
Résultat attendu pour Ezmax-Fingerprint (POST) : v1=da829efd4c2a8722ce17d3cf977c4e86adf7d2dbaa47e1b2ee3b4ade6c9cb642
Ezmax-Signature
Ezmax-Signature est la signature réelle prouvant que la requête a été générée par le propriétaire de la clé à l'aide de son secret. La signature est calculée à l'aide de HMAC et de SHA256. Ne confondez pas SHA256 (aussi appelé SHA2-256) et SHA3-256 ; il s'agit de deux algorithmes distincts. La plupart des langages de programmation offrent une implémentation de HMAC avec SHA256. Pour vous assurer que votre implémentation produit les valeurs attendues, essayez de hacher la valeur "foo" avec la clé "bar" ; elle devrait produire la valeur suivante : "147933218aaabc0b8b10a2b3a5c34684c8d94341bcf10a4736dc7270f7741851".
Pour calculer la signature, vous devez concaténer le Ezmax-Fingerprint, la clé API et le Ezmax-Date. Les trois valeurs doivent être concaténées sans séparateur. Calculez ensuite le HMAC à l'aide de SHA256 en utilisant votre secret comme clé.
Une fois le hachage HMAC-SHA256 calculé, ajoutez le préfixe "v1=", qui sert d'identifiant de version afin de permettre une évolution future.
Voici un exemple d'implémentation en 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
Voici deux exemples de ce à quoi pourraient ressembler les signatures des requêtes GET et POST. Vous pouvez valider le fonctionnement de votre algorithme en utilisant ces valeurs d'exemple et en les comparant aux valeurs attendues. Dans les exemples ci-dessous, nous avons utilisé la même clé API, la même empreinte et la même date que dans la section sur les empreintes ci-dessus. La seule nouvelle variable est le secret, qui est "ThisIsTheSecretAssociatedToTheAuthorizationKey" dans cet exemple.
Exemple de calcul pour une requête (GET) :
text
v1=8f6f3ed75edb6e2cbe777b4fda5cab1a6adaebadc758780eb82c3d49934f354aThisIsMyAuthorizationKey2000-12-31T23:59:59Z1
Résultat attendu pour Ezmax-Signature (GET) :
text
v1=3a95fde64d27527745bcb0dd91be8caf7917c6778197e22d1d56c87245f979f51
Exemple de calcul pour une requête (POST) :
text
v1=da829efd4c2a8722ce17d3cf977c4e86adf7d2dbaa47e1b2ee3b4ade6c9cb642ThisIsMyAuthorizationKey2000-12-31T23:59:59Z1
Résultat attendu pour Ezmax-Signature (POST) :
text
v1=b924269145ff74f64985992325e82e79445bbe3aa994b90d2f24b3023b8d5f091
Conclusion des exemples
L'ensemble du processus a été détaillé ci-dessus, mais voici un résumé de ce à quoi vos en-têtes HTTP devraient ressembler pour signer ces exemples de requêtes, en considérant les variables communes suivantes :
| Variable | Valeur d'exemple |
|---|---|
| Date | 2000-12-31T23:59:59Z |
| Autorisation | ThisIsMyAuthorizationKey |
| Secret | ThisIsTheSecretAssociatedToTheAuthorizationKey |
Pour une requête GET vers 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
Pour une requête POST vers https://prod.api.global.ezmax.com/1/module/sspr/sendUsernames avec le corps suivant = '{"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