Autoriser l'accès avec les politiques de TOSIAM
Sur cette page
Une API qui décide elle-même qui peut lire ou modifier ses données finit par disperser ses règles d’accès dans son code : chaque changement demande un développement et un déploiement. TOSIAM peut porter ces règles à sa place. L’API décrit ce que l’utilisateur veut faire (une action sur une ressource), TOSIAM répond par une décision calculée à partir de politiques, et l’API applique la décision. Les règles se changent dans la console, sans toucher à l’API.
Ce tutoriel construit une API de documents : les membres du groupe lecteurs lisent, ceux du groupe redacteurs lisent et modifient, personne ne supprime. Le code est dans le dépôt tosiam-samples, dossier tosiam-policies : l’API et une commande qui l’essaie, en Node.js sans dépendance.
-
Commande documents vers TOSIAM
Connexion de
dduck(REST) : jeton de session -
Commande documents vers API des documents
GET /documents/42, en-têteiPlanetDirectoryPro: la session dedduck -
API des documents vers TOSIAM
Évaluation : ressource
https://documents.example/documents/42, sujet : la session dedduck -
TOSIAM vers API des documents
actions: { lire: true }, attributmail -
API des documents vers Commande documents
200: le document -
Commande documents vers API des documents
DELETE /documents/42 - API des documents vers TOSIAM Évaluation
-
TOSIAM vers API des documents
actions: { lire: true }: pas desupprimer -
API des documents vers Commande documents
403 acces_refuse
Les notions (ensemble de stratégies, type de ressource, politique, sujets et conditions) sont présentées dans Autorisation. Ce tutoriel les met en œuvre de bout en bout.
Étape 1 : le type de ressource#
Un type de ressource décrit la forme des ressources protégées (des modèles d’URL) et les actions possibles. Dans Autorisation, onglet Types de ressource, créez le type documents avec le modèle https://documents.example/documents/* :
https://documents.example/documents/<id>.La ressource n’a pas besoin d’être une vraie adresse : c’est un nom, que l’API construit à partir de la requête. documents.example n’est jamais appelé.
Onglet Actions, ajoutez les trois actions de l’API :
lire (1), supprimer (2) et modifier (3).La valeur à côté de chaque action (« Autoriser ») est seulement celle que la console propose quand une politique ajoute l’action : un type de ressource n’accorde rien.
Étape 2 : l’ensemble de stratégies#
Un ensemble de stratégies regroupe des politiques et fixe les types de ressource qu’elles peuvent viser. L’API le nomme dans chaque demande d’évaluation. Dans Autorisation, Nouvel ensemble de stratégies : nom documents, type de ressource documents. Une fois les politiques de l’étape 3 créées, l’ensemble les liste :
lecture (1) et redaction (2).Quand plusieurs politiques visent la même ressource, un refus l’emporte sur une autorisation (combinateur DenyOverride).
Étape 3 : les politiques#
Deux politiques, créées par Nouvelle politique dans l’ensemble documents :
| Politique | Sujet | lire | modifier | supprimer | Attribut de réponse |
|---|---|---|---|---|---|
lecture | groupe lecteurs | autorisé | mail | ||
redaction | groupe redacteurs | autorisé | autorisé | refusé | mail |
Voici redaction, section par section. Ressources : le type documents et la ressource https://documents.example/documents/*, que TOSIAM enregistre avec le port (:443) :
Actions : lire et modifier autorisées, supprimer refusée :
lire (1) et modifier (3) autorisées, supprimer refusée (2).Une action absente d’une politique n’est ni autorisée ni refusée par elle ; une action qu’aucune politique n’autorise n’apparaît pas dans la décision. L’API traite les deux cas comme un refus.
Sujets : à qui la politique s’applique. Type Utilisateurs et groupes, groupe redacteurs :
redacteurs (2).Viser des groupes plutôt que des utilisateurs : donner ou retirer un droit revient à changer l’appartenance à un groupe, sans toucher aux politiques.
Attributs de réponse : les attributs de l’utilisateur renvoyés avec la décision. Cochez mail (le champ de recherche filtre la liste) :
mail (1), que l’API affiche comme demandeur.La politique lecture se construit de la même façon, avec le groupe lecteurs et la seule action lire.
Étape 4 : le compte de service et son privilège#
L’API demande les décisions avec sa propre session, celle d’un compte de service api-documents. TOSIAM n’accepte la demande que si ce compte a le privilège Entitlement Rest Access (« Appels REST d’évaluation de politique ») : sinon, il répond 403 The user has insufficient privileges. Le privilège se donne à un groupe. Dans Identités, créez l’utilisateur api-documents (mot de passe Api-Documents-2026, celui que l’API utilise par défaut, ou un autre passé dans API_DOCUMENTS_PASSWORD), puis le groupe evaluateurs avec api-documents pour membre, et activez le privilège dans l’onglet Privilèges du groupe :
En ligne de commande, c’est ce que fait le script de l’exemple :
ssoadm add-privileges --realm ref --idname evaluateurs --idtype Group --privileges EntitlementRestAccessLe compte de service ne reçoit aucun autre droit : il peut demander des décisions, pas modifier les politiques.
Étape 5 : demander une décision#
L’API reçoit la session de l’utilisateur dans l’en-tête iPlanetDirectoryPro. Elle transforme la requête en question pour TOSIAM : méthode HTTP → action (GET → lire, PUT → modifier, DELETE → supprimer), document → ressource.
POST /tosiam/json/ref/policies?_action=evaluate
X-Requested-With: XMLHttpRequest
Accept-API-Version: resource=2.1, protocol=1.0
Content-Type: application/json
iPlanetDirectoryPro: <session du compte de service>
{
"resources": ["https://documents.example/documents/42"],
"application": "documents",
"subject": { "ssoToken": "<session de l'utilisateur>" }
}X-Requested-With est obligatoire : sans lui, TOSIAM répond 403 sans corps. application est le nom de l’ensemble de stratégies. La réponse pour dduck (groupe lecteurs) :
[
{
"resource": "https://documents.example/documents/42",
"actions": { "lire": true },
"attributes": { "mail": ["donald_duck@tosiam.io"] },
"advices": {},
"ttl": 9223372036854775807
}
]Pour mmouse (groupe redacteurs) :
[
{
"resource": "https://documents.example/documents/42",
"actions": { "lire": true, "supprimer": false, "modifier": true },
"attributes": { "mail": ["mickey_mouse@tosiam.io"] },
"advices": {},
"ttl": 9223372036854775807
}
]Une ressource qu’aucune politique ne vise (https://autre.example/documents/42) reçoit "actions": {} : rien n’est accordé. Les erreurs de TOSIAM :
| Situation | Réponse |
|---|---|
| Session de l’utilisateur inconnue, expirée ou fermée | 400 « Invalid value subject » |
| Session de l’appelant expirée ou fermée | 401 « Access Denied » |
| Appelant sans le privilège Entitlement Rest Access | 403 « The user has insufficient privileges » |
Dans l’API, la session du compte de service est ouverte à la première requête, partagée par les suivantes, et renouvelée une fois si TOSIAM la refuse :
/** The decision of TOSIAM for the user's session on one resource; the caller session is renewed once. */
async function evaluate(subjectToken, resource) {
const current = callerSession();
const ask = async callerToken => tosiam.evaluate({ callerToken, subjectToken, resources: [resource], application: APPLICATION });
let decisions;
try {
decisions = await ask(await current);
} catch (e) {
if (!(e instanceof TosiamError) || e.kind !== 'caller') throw e;
// The caller session expired or was ended: a new one, and the question asked again
if (caller === current) caller = undefined;
decisions = await ask(await callerSession());
}
return decisions.find(d => d.resource === resource) ?? { actions: {}, attributes: {}, advices: {} };
}Étape 6 : appliquer la décision#
La règle de l’API tient en une ligne : refuser, sauf si TOSIAM répond true pour cette action. Une action à false, absente, une ressource sans décision, une erreur ou un TOSIAM injoignable donnent tous un refus, jamais une opération faite par défaut.
// Refused unless TOSIAM explicitly answers true for this action
const who = decision.attributes?.mail?.[0] ?? null;
if (decision.actions?.[action] !== true) {
log(`${req.method} /documents/${id} → 403, ${action} refusé${who ? ` à ${who}` : ''}`);
return send(res, 403, { error: 'acces_refuse', action, ressource: resource, advices: decision.advices ?? {} });
}| Cas | Réponse de l’API |
|---|---|
| Action accordée | 200 (ou 204 pour une suppression) |
| Action non accordée | 403 acces_refuse, avec l’action et les advices |
Sans session, ou session refusée par TOSIAM (400 Invalid value subject) | 401 |
| Compte de service refusé ou sans privilège | 500 : erreur de configuration, pas un refus de l’utilisateur |
| TOSIAM injoignable ou réponse inattendue | 503 |
Étape 7 : lancer et tester#
cd tosiam-policies
./up.sh
TOSIAM_USER=dduck TOSIAM_PASSWORD=Donald-Duck-2026 node documents/documents.jsDocument 42 de http://localhost:8087, en tant que dduck :
lire autorisé « Rapport annuel » (demandeur : donald_duck@tosiam.io)
modifier refusé
supprimer refusé
Session fermée.TOSIAM_USER=mmouse TOSIAM_PASSWORD=Mickey-Mouse-2026 node documents/documents.jsDocument 42 de http://localhost:8087, en tant que mmouse :
lire autorisé « Rapport annuel » (demandeur : mickey_mouse@tosiam.io)
modifier autorisé « Rapport annuel » (demandeur : mickey_mouse@tosiam.io)
supprimer refusé
Session fermée.La commande essaie vraiment les trois actions sur l’API : la modification de mmouse change le document. Sans les variables, elle demande l’identifiant et le mot de passe (masqué).
Pour voir une règle changer sans toucher à l’API : dans la console, retirez dduck du groupe lecteurs, puis relancez la commande : les trois actions sont refusées. Remettez-le dans le groupe ensuite.
Le journal de l’API (.tosiam/api-documents.log) nomme l’action, la décision et le mail de l’utilisateur, jamais une session :
2026-10-10T13:31:41.230Z GET /documents/42 → lire accordé à donald_duck@tosiam.io
2026-10-10T13:31:41.251Z PUT /documents/42 → 403, modifier refusé à donald_duck@tosiam.ioLes advices#
Une politique peut poser une condition d’environnement, par exemple un niveau d’authentification minimal (AuthLevel). Quand la session ne la remplit pas, TOSIAM ne refuse pas sèchement : il renvoie un advice, qui dit ce qui manque. Avec une troisième politique qui accorderait supprimer aux rédacteurs authentifiés au niveau 2, la réponse pour mmouse, connecté au niveau 0, devient :
[
{
"resource": "https://documents.example/documents/42",
"actions": {},
"attributes": { "mail": ["mickey_mouse@tosiam.io"] },
"advices": { "AuthLevelConditionAdvice": ["2"] },
"ttl": 9223372036854775807
}
]L’API renvoie les advices avec le 403, sans jamais les prendre pour un accord :
Document 42 de http://localhost:8087, en tant que mmouse :
lire refusé TOSIAM demande plus : AuthLevelConditionAdvice 2
modifier refusé TOSIAM demande plus : AuthLevelConditionAdvice 2
supprimer refusé TOSIAM demande plus : AuthLevelConditionAdvice 2
Session fermée.Une application peut alors relancer une authentification plus forte (voir StepUpAuthNode) et redemander la décision. Pour éviter de bloquer les autres actions, réservez les conditions à advice à des ressources distinctes (par exemple https://documents.example/suppression/*). L’exemple n’en utilise pas.
Exporter et importer les politiques#
Le modèle de l’exemple a été construit dans la console, puis exporté au format XACML :
ssoadm list-xacml --realm ref --outfile /tmp/documents-policies.xmlLe script up.sh l’importe avec ssoadm create-xacml --realm ref --xmlfile documents-policies.xml. L’import crée aussi l’ensemble de stratégies et un type de ressource, nommé documentsResourceType<nombre> (le format XACML ne transporte pas le type de ressource : TOSIAM le reconstruit à partir des actions des politiques). C’est pourquoi la politique redaction refuse supprimer explicitement : sans elle, aucune politique ne nommerait l’action, et le type importé ne l’aurait pas.
En cas de problème#
| Symptôme | Cause probable |
|---|---|
L’API répond 500, « Le compte de service n’a pas le privilège EntitlementRestAccess » | Le groupe du compte de service n’a pas le privilège : TOSIAM répond 403 The user has insufficient privileges |
L’API répond 500, « Le compte de service ne peut pas se connecter à TOSIAM » | Compte absent, ou mot de passe différent (API_DOCUMENTS_PASSWORD) |
| La commande s’arrête sur « –document : identifiant … attendu » | Identifiant hors de [A-Za-z0-9_-]{1,64} : l’API ne l’accepterait pas |
TOSIAM répond 403 sans corps à l’évaluation | En-tête X-Requested-With absent |
| Toutes les actions sont refusées pour tous | Politiques absentes ou désactivées, ou application qui ne nomme pas l’ensemble de stratégies |
| Toutes les actions sont refusées pour un utilisateur | Il n’est dans aucun groupe visé par les politiques : remettez-le dans son groupe (./up.sh ne vérifie pas les appartenances) |
| Toutes les actions sont refusées, avec des advices | Une condition d’environnement n’est pas remplie : voir Les advices |
actions: {} pour une ressource | Aucune politique ne vise cette ressource : comparez-la au modèle (TOSIAM ajoute :443 aux ressources https) |
create-xacml : « XML cannot be parsed » | Fichier exporté deux fois au même endroit : exportez dans un fichier neuf |
En production#
- Refus par défaut : n’exécutez une action que sur un
trueexplicite. Une erreur, un TOSIAM injoignable ou une réponse inattendue sont des refus. - Un compte de service dédié, avec le seul privilège Entitlement Rest Access, et son mot de passe dans le gestionnaire de secrets de la plateforme.
- Des groupes comme sujets, pas des utilisateurs : les droits suivent les mouvements de personnel sans toucher aux politiques.
- Des ressources nommées par l’API, stables et sans données de l’utilisateur ; vérifiez qu’un identifiant reçu ne peut pas sortir du modèle (
.., caractères spéciaux). - Les advices : relancez l’authentification demandée plutôt que de refuser sans explication, et ne mettez pas de condition à advice sur une ressource dont d’autres actions doivent rester accessibles.
- Aucune session dans les journaux : ni celle de l’utilisateur, ni celle du compte de service.
Pour aller plus loin#
- Autorisation : le modèle complet, les types de sujets et de conditions.
- S’authentifier par l’API REST : la connexion de la commande, sans navigateur.
- Délégation entre API avec le token exchange : quand une API appelle une autre API au nom de l’utilisateur.
Mis à jour le