Authentification
Toutes les API IDCloud (contrats Web & SDK et API) utilisent OAuth2 avec le type d'octroi JWT Bearer (RFC 7523). Vous générez une assertion JWT de courte durée sur votre back-end, l'échangez contre un jeton Bearer, et utilisez ce jeton dans chaque appel ultérieur.
L'assertion JWT doit être générée uniquement sur votre back-end. N'exposez jamais votre clé privée dans du code front-end, des applications mobiles, des dépôts ou des journaux.
Obtention des identifiants
Avant de pouvoir générer des jetons, vous avez besoin d'un compte de service provisionné par Unico. Contactez le support Unico en fournissant :
- Nom du compte de service (max 12 caractères)
- Nom, e-mail et téléphone du responsable (numéros du Brésil, des États-Unis ou du Mexique uniquement)
Vous recevrez :
- Nom unique du compte
- ID du tenant
- Payload JWT de base
- Fichier de clé privée (format
.pem)
Gardez des comptes de service distincts pour UAT et Production.
Construction de l'assertion JWT
L'assertion est un JWT au format JWS compact : {Base64url(Header)}.{Base64url(Payload)}.{Base64url(Signature)}.
{
"alg": "RS256",
"typ": "JWT"
}
| Claim | Valeur | Notes |
|---|---|---|
iss | <account_name>@<tenant_id>.iam.acesso.io | Fourni avec vos identifiants |
aud | https://identityhomolog.acesso.io (UAT) ou https://identity.acesso.io (Production) | Doit correspondre à l'hôte du point de terminaison du jeton |
scope | * | Accorde toutes les permissions |
iat | Horodatage Unix (secondes) | Heure d'émission du JWT |
exp | iat + max 3600 | Ne peut pas dépasser 1 heure à partir de iat |
{
"aud": "https://identity.acesso.io",
"scope": "*",
"iat": 1738086000,
"exp": 1738089600
}
Signez l'en-tête + le payload en utilisant RS256 (RSA + SHA-256) avec la clé privée .pem fournie par Unico.
Tout champ non listé ci-dessus (ex. sub, jti, nbf) provoquera une erreur 1.2.22. Utilisez uniquement les claims indiqués.
Demande du jeton
Le point de terminaison du jeton est identique pour les deux contrats :
| Environnement | Point de terminaison |
|---|---|
| Production | POST https://identity.acesso.io/oauth2/token |
| UAT | POST https://identityhomolog.acesso.io/oauth2/token |
| Paramètre | Valeur |
|---|---|
Content-Type | application/x-www-form-urlencoded |
grant_type | urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion | Votre JWT signé |
- cURL
- Node.js
- Python
curl -X POST https://identity.acesso.io/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
-d "assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
import jwt from 'jsonwebtoken';
import fs from 'fs';
import qs from 'querystring';
const privateKey = fs.readFileSync('./private-key.pem');
const now = Math.floor(Date.now() / 1000);
const assertion = jwt.sign(
{
aud: 'https://identity.acesso.io',
scope: '*',
iat: now,
exp: now + 3600,
},
privateKey,
{ algorithm: 'RS256' }
);
const res = await fetch('https://identity.acesso.io/oauth2/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: qs.stringify({
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion,
}),
});
const { access_token, expires_in } = await res.json();
import time
import jwt # PyJWT
import requests
with open("private-key.pem", "rb") as f:
private_key = f.read()
now = int(time.time())
assertion = jwt.encode(
{
"aud": "https://identity.acesso.io",
"scope": "*",
"iat": now,
"exp": now + 3600,
},
private_key,
algorithm="RS256",
)
response = requests.post(
"https://identity.acesso.io/oauth2/token",
data={
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion,
},
)
token_data = response.json()
access_token = token_data["access_token"]
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}
| Champ | Type | Description |
|---|---|---|
access_token | string | Jeton d'accès JWT. À utiliser dans Authorization: Bearer <token> sur tous les appels API. |
expires_in | integer | Durée d'expiration en secondes. Exemple : 3600. |
token_type | string | Toujours Bearer. |
Utilisation du jeton
Ajoutez le jeton à l'en-tête Authorization de chaque requête API. L'en-tête est identique pour les deux contrats — ce qui diffère, c'est l'hôte et le chemin de l'API que vous appelez :
| Contrat | Hôte de production | Hôte UAT |
|---|---|---|
| Web & SDK | https://api.idcloud.unico.app | https://api.idcloud.uat.unico.app |
| API | https://api.id.unico.app | https://api.id.uat.unico.app |
Web & SDK — Authorization est le seul en-tête d'authentification requis :
curl -X POST https://api.idcloud.unico.app/client/v1/process \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'
API — Authorization est utilisé conjointement avec l'en-tête APIKEY :
curl -X POST https://api.id.unico.app/processes/v1 \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "APIKEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{ ... }'
Renouvellement du jeton
Les jetons expirent après 3600 secondes. Implémentez un renouvellement proactif dans votre back-end :
- Suivez
expires_inde la réponse du jeton et stockez l'horodatage d'expiration. - Demandez un nouveau jeton lorsqu'il reste 10 minutes ou moins avant l'expiration.
- N'attendez jamais un
401en production pour déclencher un renouvellement.
Référence API
La spécification OpenAPI complète pour le point de terminaison du jeton est disponible dans authentication.yaml.
| Méthode | Chemin | Description |
|---|---|---|
POST | /oauth2/token | Échangez une assertion JWT signée contre un jeton d'accès Bearer |
Codes d'erreur
| Code | Description | Action |
|---|---|---|
1.0.1 | L'ID fourni dans la construction de iss est incorrect | Vérifiez que le champ iss correspond à l'ID du tenant fourni lors de la génération de la clé privée |
1.0.14 | L'application n'est pas active | Vérifiez auprès du chef de projet si l'application utilisée est active |
1.1.1 | Le paramètre scope n'a pas été fourni | Ajoutez "scope": "*" à votre payload JWT |
1.2.4 | Assertion JWT invalide | L'assertion JWT n'est plus valide. Deux causes : (a) l'heure actuelle est postérieure à exp (JWT véritablement expiré — générez une nouvelle assertion pour chaque demande de jeton) ; ou (b) exp dépasse iat + 3600 (durée de vie trop longue — limitez exp à iat + 3600). |
1.2.5 | La validation du JWT a échoué | Le JWT ne peut pas être validé. Vérifiez les paramètres et assurez-vous qu'il a été signé avec RS256 et la bonne clé privée |
1.2.6 | La clé privée n'est plus valide | La clé privée utilisée pour signer le JWT n'est plus acceptable. Demandez de nouveaux identifiants pour le compte |
1.2.7 | JWT déjà utilisé | Le JWT n'est plus acceptable car il a déjà été utilisé. Générez une nouvelle assertion pour chaque demande de jeton |
1.2.11 | Le compte n'est pas actif | Le compte utilisé n'est pas actif |
1.2.14 | Le compte manque des permissions nécessaires | Le compte utilisé ne dispose pas des permissions nécessaires |
1.2.18 | Compte temporairement verrouillé | Le compte a été temporairement verrouillé en raison du dépassement du nombre de tentatives d'authentification invalides |
1.2.19 | Usurpation d'identité non autorisée | Le JWT contient un claim sub pointant vers un compte non autorisé pour l'usurpation d'identité. Supprimez le claim sub du payload. |
1.2.20 | Échec du décodage du JWT | Impossible de décoder le JWT. Vérifiez le format du jeton et qu'il a été signé avec RS256. |
1.2.21 | Mauvaise clé privée / Authentification échouée | La signature du JWT n'a pas pu être vérifiée avec aucune clé connue pour ce compte. Vérifiez que vous utilisez le bon fichier .pem de clé privée pour ce compte de service et cet environnement. |
1.2.22 | Champs non autorisés dans le payload | Le JWT contient des champs de payload supplémentaires non autorisés. Supprimez tout claim non listé dans ce guide (ex. sub, jti, nbf). Remarque : si vous avez inclus un claim sub et reçu l'erreur 1.2.19, cette erreur a la priorité. |
1.3.1 | Restriction d'accès par IP | Votre IP ne figure pas dans la liste d'autorisation de ce compte |
1.3.2 | Restriction d'accès basée sur le temps | La requête se situe en dehors de la fenêtre temporelle autorisée pour ce compte |
Étapes suivantes
- Environnements — hôtes sandbox vs production
- Web & SDK — Créer un processus — premier appel après l'authentification
- API — Créer un processus — premier appel après l'authentification