Vous voulez exposer une API REST sécurisée (SSO/OAuth 2.0) dans Copilot Studio et la rendre disponible dans Teams, mais l’authentification, la visibilité des flows et la publication bloquent ? Voici un guide exhaustif, concret et opérationnel pour réussir de bout en bout.
Créer un plug‑in personnalisé Copilot Studio à partir d’une API externe
Vue d’ensemble de la question
L’objectif est de connecter une API REST protégée par SSO/OAuth 2.0 (avec consentement administrateur) à Copilot Studio. Trois approches ont été testées :
- Mettre à jour ou obtenir des réponses à partir de données externes : ouverture de Power Automate pour créer un connecteur personnalisé → blocage à l’étape OAuth.
- Flux personnalisé : création d’un cloud flow contenant une action HTTP → même blocage OAuth.
- Plug‑in Copilot basé sur un flow → le flow n’apparaît pas dans Copilot et l’option Ajouter une API pour un connecteur personnalisé est grisée.
Les besoins sont clairs : (1) configurer correctement OAuth 2.0 ; (2) faire reconnaître le connecteur/le flow dans Copilot Studio puis dans Copilot for Teams ; (3) exposer le plug‑in à tous les utilisateurs du tenant.
Architecture cible (vue rapide)
[Utilisateur Teams/Copilot] ──► [Copilot Studio Plug‑in] │ ├─ (A) Appel direct via Connecteur personnalisé (OAuth 2.0) │ └─ (B) Appel via Power Automate Flow (owner’s connection, logique multi‑étapes)
Pré‑requis administratifs
Avant toute configuration, alignez‑vous avec l’administrateur Entra ID (ex‑Azure AD) et, côté API, avec l’éditeur du service.
- Enregistrement d’application (si non fourni par l’éditeur API) dans Entra ID : obtenez Client ID, créez un Client secret si nécessaire, notez le Tenant ID.
- Consentement administrateur (Grant admin consent) sur les scopes/permissions requis par l’API (utilisateur délégué ou application).
- URI de redirection à ajouter côté app : par défaut, pour les connecteurs personnalisés Power Platform, utilisez :
https://global.consent.azure-apim.net/redirect
(ou l’URL de redirection spécifique à votre cloud/région). - Endpoints OAuth de l’API : URL d’autorisation, URL de jeton, éventuellement URL de revocation et valeur audience/resource si l’API l’exige.
Cartographie des paramètres OAuth 2.0
Ce que demande l’API | Où le renseigner dans le connecteur personnalisé | Remarques clés |
---|---|---|
Authorization URL | Onglet Sécurité → URL d’autorisation | Doit correspondre à l’environnement de l’API (prod/sandbox). |
Token URL | Onglet Sécurité → URL de jeton | Supporte authorization_code et/ou client_credentials selon le cas d’usage. |
Client ID / Secret | Onglet Sécurité → ID client / Secret client | Stockez le secret côté admin, pas dans un document partagé. |
Scopes | Onglet Sécurité → Scopes | Chaîne séparée par des espaces. Ajoutez offline_access si un refresh token est requis. |
Audience / Resource | Onglet Sécurité → Paramètre ressource (si présent) | Utilisé par certaines API qui exigent resource=... ou aud=... . |
Redirect URI | Entra ID → Redirect URIs de l’app | Incluez https://global.consent.azure-apim.net/redirect . |
PKCE requis | Selon capacités du connecteur | Si l’API impose PKCE et que l’UI du connecteur ne le gère pas, utilisez l’option Flow (B) ou un proxy. |
Créer le connecteur personnalisé (Power Automate → Données → Connecteurs)
- Onglet Sécurité
- Type d’authentification : OAuth 2.0.
- ID client / Secret client / URL d’autorisation / URL de jeton.
- Scopes : listez‑les séparés par des espaces. Ajoutez
offline_access
si un token d’actualisation est nécessaire. - Si l’API requiert un ID Token (OIDC) pour du profilage : cochez « Utiliser ID token si disponible ».
- Si l’API exige audience ou resource : renseignez le champ dédié ou ajoutez un paramètre de requête personnalisé si l’UI le permet.
- Onglet Définition
- Importez un document OpenAPI (YAML/JSON) ou définissez les actions manuellement (verbes, chemins, schémas, auth). Assurez‑vous de renseigner les policies de transformation (headers, auth).
- Préférez des operationId explicites (ex.
getCustomerById
,postInvoice
).
- Onglet Test
- Cliquez Nouvelle connexion : la fenêtre OAuth s’ouvre, vous authentifie, puis renvoie à la redirection APIM. Vérifiez que la connexion s’affiche avec un statut Connecté.
- Testez une action (GET/POST) avec des paramètres concrets. Contrôlez le code HTTP, les en‑têtes (
Authorization: Bearer …
) et la charge utile.
- Enregistrer, publier et partager
- Enregistrez puis Publiez le connecteur dans l’environnement cible (Dev/Sandbox, puis Prod).
- Dans Paramètres → Partager, partagez avec : vous‑même (si créé par un admin), votre équipe, et/ou des groupes de sécurité.
Pourquoi l’option “Ajouter une API pour un connecteur personnalisé” est‑elle grisée ?
Elle s’active uniquement lorsqu’au moins un connecteur publié et accessible existe dans le même environnement que votre Copilot. Vérifiez également que vous avez bien partagé le connecteur avec le compte qui crée le plug‑in.
Paramètres avancés & bonnes pratiques OAuth
- User‑delegated (Authorization Code) : chaque utilisateur crée sa connexion et agit en son nom. Requiert un admin consent global pour éviter des demandes individuelles.
- Application (Client Credentials) : le connecteur agit « au nom de l’application ». À privilégier pour des lectures techniques ou des tâches de service. Attention au périmètre d’accès.
- Refresh tokens : assurez‑vous que l’API émet des refresh tokens (scope
offline_access
) si la session doit survivre au‑delà de l’expiration du token d’accès. - Audience/Resource : si l’API est multi‑ressource, validez la valeur exacte attendue côté aud/resource.
- PKCE : si obligatoire côté fournisseur et non pris en charge par l’UI du connecteur, recourez au pattern Flow (voir plus bas) ou à un proxy (APIM/Azure Function) pour effectuer l’échange de code.
- Scopes minimaux : appliquez le principe du moindre privilège. Documentez précisément chaque scope.
Construire le plug‑in dans Copilot Studio
- Ouvrez Copilot Studio dans le même environnement que votre connecteur.
- Créez/ouvrez votre copilote → Plug‑ins ou Actions → Données externes → sélectionnez le connecteur personnalisé publié.
- Ajoutez les actions pertinentes (GET/POST/DELETE) à la compétence de votre copilote et décrivez l’intention « quand utiliser cette action » via le descripteur.
- Dans l’aire de test, validez que :
- Le câblage paramètres → inputs fonctionne (id, filtres, body JSON).
- Le rendement (latence) est correct ; sinon, simplifiez la réponse ou limitez le payload côté API.
- La connexion vous est bien proposée puis créée au premier appel, si vous êtes en user‑delegated.
Rédiger de bonnes invites (prompts) d’action
Associez des exemples clairs au plug‑in, afin d’aider l’orchestrateur à choisir l’action.
Exemples (à consigner dans la description de l’action)
- "Quand l’utilisateur demande 'liste mes commandes du mois', appeler GET /orders?from=&to="
- "Quand l’utilisateur dit 'crée une facture pour le client X', appeler POST /invoices avec le body suivant…"
Alternative : utiliser un flow Power Automate comme plug‑in
Si l’API requiert plusieurs étapes non prises en charge par le connecteur (signature, rafraîchissement manuel, transformation complexe), encapsulez la logique dans un cloud flow :
- Créez une Solution (nécessaire pour la visibilité dans Copilot) dans l’environnement voulu.
- Ajoutez un Cloud flow Automatisé avec le déclencheur Copilot (v2) (ou le déclencheur Copilot disponible dans votre environnement).
- Étapes du flow :
- Initialize variable (paramètres d’entrée du Copilot).
- HTTP vers l’API (avec votre connection reference vers le connecteur personnalisé, ou HTTP direct si nécessaire).
- Condition : si
401/403
→ rafraîchir le token (si pattern manuel) → relancer l’appel. - Parse JSON → façonnez une sortie structurée (objets, tableaux) pour Copilot.
- Sorties : définissez des outputs clairs (par exemple
status
,message
,data[]
). - Run‑only users & connexions : dans les paramètres du flow, définissez que les run‑only users utilisent la connexion du propriétaire. Ainsi, les utilisateurs finaux n’ont pas à créer leur connexion OAuth.
Mon flow n’apparaît pas dans Copilot Studio ?
Assurez‑vous qu’il est solution‑aware, qu’il utilise un déclencheur Copilot (v2), qu’il est propriétaire par vous (ou par un compte de service) dans le même environnement, et qu’il a été publié/activé. Partagez le flow avec le créateur du Copilot si besoin.
Publication et déploiement dans Microsoft Teams
- Publier le Copilot depuis Copilot Studio (environnement Prod ou pré‑prod).
- Dans le Centre d’administration Teams :
- Gérer les applications → Mettre en lumière (Pin) pour le promouvoir.
- Créez ou mettez à jour une Stratégie d’installation d’app pour l’installer automatiquement aux utilisateurs/groupes ciblés.
- Tester depuis le client Teams (bureau et web). Validez le SSO/connexion : en mode user‑delegated, chaque utilisateur verra un consent screen la première fois (sauf si l’admin a pré‑consenti).
Deux modèles d’accès : lequel choisir ?
Modèle | Description | Avantages | Points d’attention | Scénarios typiques |
---|---|---|---|---|
A. Connecteur direct (User‑delegated) | Le plug‑in appelle le connecteur ; chaque utilisateur crée sa connexion. | Traçabilité par utilisateur, respect du least privilege, compatibilité SSO. | Nécessite un admin consent global ; expérience de première connexion à piloter. | Lecture/écriture au nom de l’utilisateur (CRM, tickets, documents). |
B. Flow avec connexion du propriétaire | Le plug‑in déclenche un flow ; le flow utilise la connexion du propriétaire. | Pas de pop‑up OAuth pour l’utilisateur, logique multi‑étapes centralisée. | Risque d’impersonation si l’API n’isole pas les droits ; audits à configurer. | Intégrations techniques, jobs de service, appels nécessitant un compte applicatif. |
Sécurité, secrets, conformité
- Environnements : séparez Dev/Sandbox et Prod. Restreignez qui peut exporter/importer des Solutions.
- Gestion des secrets : stockez les secrets dans un Key Vault ou des paramètres d’environnement protégés. Évitez de saisir des secrets en clair dans un connecteur partagé.
- Rotation : planifiez la rotation des secrets et le renouvellement des certificats (app registrations).
- Scopes minimaux : validez régulièrement la liste. Documentez les justifications.
- Journalisation : activez les logs d’exécution du connecteur ; corrélez avec les journaux de l’API pour diagnostiquer les expirations de token et les anomalies.
Dépannage (troubleshooting)
Symptôme / Message | Cause probable | Correction immédiate |
---|---|---|
redirect_uri_mismatch | L’URI de redirection du connecteur ne correspond pas à celle déclarée dans l’app. | Ajoutez https://global.consent.azure-apim.net/redirect dans les Redirect URIs de l’app et republiez le connecteur. |
Pop‑up OAuth en boucle | Cookies/SSO bloqués ou prompt=consent imposé par l’API. | Vérifiez la stratégie navigateur/tenant ; assurez le admin consent préalable. |
invalid_scope ou AADSTS70011 | Scope mal orthographié ou séparateur incorrect. | Utilisez des espaces (scope1 scope2 ) et validez l’existence des scopes côté app/API. |
invalid_client / unauthorized_client | Client secret invalide, app non autorisée pour le flux choisi. | Régénérez le secret ; activez le type d’octroi (authorization_code / client_credentials) dans l’API. |
401 Unauthorized sur l’API | Audience/ressource incorrecte ou token expiré sans refresh. | Renseignez audience/resource attendu ; activez offline_access et le rafraîchissement. |
« Ajouter une API pour un connecteur personnalisé » grisé | Aucun connecteur publié (ou pas dans le même environnement) ; droits manquants. | Publiez et partagez le connecteur dans l’environnement du Copilot. |
Le flow n’apparaît pas dans Copilot | Flow non hébergé dans une Solution ; mauvais déclencheur ; propriétaire différent. | Déplacez le flow dans une Solution, utilisez Copilot (v2), alignez propriétaire/environnement, activez et partagez. |
Exemples concrets
Exemple d’OpenAPI minimal pour le connecteur
{
"openapi": "3.0.1",
"info": { "title": "Orders API", "version": "1.0.0" },
"servers": [{ "url": "https://api.example.com" }],
"paths": {
"/orders": {
"get": {
"operationId": "getOrders",
"parameters": [
{ "name": "from", "in": "query", "schema": { "type": "string", "format": "date" } },
{ "name": "to", "in": "query", "schema": { "type": "string", "format": "date" } }
],
"responses": {
"200": {
"description": "List of orders",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"customer": { "type": "string" },
"total": { "type": "number" }
},
"required": ["id","customer","total"]
}
}
}
}
}
}
}
}
},
"components": { "securitySchemes": { "oauth2": { "type": "oauth2" } } },
"security": [{ "oauth2": [] }]
}
Exemple de flow Power Automate (pseudo)
Déclencheur : Copilot (v2)
Étapes :
1) Initialize variable (from, to)
2) Action "Custom Connector" -> getOrders
3) Condition (si statusCode != 200) -> gérer les erreurs
4) Compose (façonner la réponse)
Sorties :
- data: body de getOrders
- count: length(data)
- status: "ok"
Exemple d’invite pour Copilot
Quand l’utilisateur écrit "liste mes commandes entre <date1> et <date2>",
- Valide <date1> et <date2> (format ISO).
- Appelle l’action getOrders avec les deux paramètres.
- Résume les résultats (client, total) et propose d’exporter au format CSV si > 20 lignes.
Stratégie d’environnements & déploiement
Environnement | Usage | Objets | Rôles | Passerelle vers Prod |
---|---|---|---|---|
Dev | Itérations rapides | Connecteur (brouillon), Flow (draft), Copilot (test) | Makers | Export de Solution (managed) |
Test/Pré‑prod | Validation fonctionnelle & sécu | Connecteur (publié), Flow (activé), Copilot (pré‑prod) | Makers + Sécu | Export/Import de Solution (managed) |
Prod | Service aux utilisateurs | Connecteur (publié), Flow (stable), Copilot (publié) | Ops + Admin | Change control / CAB |
Checklist express (de 0 à « dispo dans Teams »)
- Entra ID : App enregistrée, Redirect URI ajoutée, scopes créés, admin consent accordé.
- Connecteur personnalisé : Sécurité OAuth 2.0 renseignée, Définition importée, Test passé, Connecteur publié et partagé.
- Copilot Studio : Plug‑in créé, actions mappées, prompts ajoutés, tests OK.
- Option Flow (si nécessaire) : Solution, déclencheur Copilot (v2), run‑only users avec connexion du propriétaire.
- Publication Copilot : environnement Prod, version figée.
- Teams Admin Center : stratégie d’installation, mise en lumière, test utilisateur.
FAQ rapide
Faut‑il un consentement à chaque utilisateur ?
Non si l’administrateur a accordé le consentement administrateur aux scopes. Les utilisateurs créeront leur connexion sans demander un nouvel accord global.
Peut‑on éviter que chaque utilisateur crée sa connexion ?
Oui via le modèle Flow : le flow s’exécute avec la connexion du propriétaire (compte de service), et les run‑only users n’ont pas à s’authentifier sur l’API.
Comment tracer « qui a fait quoi » ?
Avec le modèle direct (user‑delegated), les journaux de l’API corrèlent le sub/upn. Avec le modèle Flow, journalisez l’identité appelante dans l’entrée du flow et ajoutez des audit logs côté API.
L’API impose PKCE, le connecteur échoue
Mettez en place un proxy (APIM/Function) qui gère l’échange PKCE, ou encapsulez l’échange dans un flow. Optionnellement, discutez avec l’éditeur pour autoriser le flux standard authorization_code sans PKCE.
Conclusion
En respectant l’enchaînement : Entra ID (app & consent) → Connecteur personnalisé validé → Plug‑in Copilot (ou Flow en alternative) → Publication Teams, vous obtenez un branchement propre d’une API REST sécurisée dans Copilot Studio. Ce guide détaille les paramètres OAuth 2.0, les options de visibilité et les stratégies de déploiement tenant‑wide pour que vos utilisateurs profitent du plug‑in sans friction, tout en respectant la sécurité et la gouvernance Microsoft 365.
Annexe A — Modèle de politique d’accès (exemple)
// Pseudo‑politique à documenter pour l'audit
Ressource : https://api.example.com
Scopes requis : orders.read orders.write offline_access
Modèle : A (user‑delegated)
Consentement : Admin (global)
Rétention logs API : 90 jours
Rafraîchissement token : auto (via connecteur)
Rotation secrets app : 180 jours
Annexe B — Modèle de réponse d’action (pour un affichage optimal)
{
"status": "ok",
"count": 2,
"data": [
{ "id": "ORD-1001", "customer": "ACME", "total": 1234.56, "currency": "EUR" },
{ "id": "ORD-1002", "customer": "Globex", "total": 987.65, "currency": "EUR" }
],
"nextLink": null
}
Annexe C — Gabarit d’OpenAPI avec schémas
openapi: 3.0.1
info:
title: Orders API
version: 1.0.0
servers:
- url: https://api.example.com
paths:
/orders:
get:
operationId: getOrders
parameters:
- in: query
name: from
schema: { type: string, format: date }
- in: query
name: to
schema: { type: string, format: date }
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/OrderList'
components:
schemas:
Order:
type: object
properties:
id: { type: string }
customer: { type: string }
total: { type: number, format: double }
currency: { type: string }
required: [id, customer, total]
OrderList:
type: array
items: { $ref: '#/components/schemas/Order' }
Annexe D — Matrice rôles et responsabilités
Tâche | Rôle principal | Validation | Livrable |
---|---|---|---|
App Entra ID + Consent | Admin Entra ID | Sécurité | Client ID/Secret, Redirect URI, Scopes |
Connecteur personnalisé | Maker Power Platform | Lead Tech | Connecteur publié + guide d’usage |
Flow (option B) | Maker Power Automate | Lead Tech | Flow dans Solution + run‑only |
Plug‑in Copilot | Bot Builder | PO Métier | Actions mappées + prompts |
Déploiement Teams | Admin Teams | Change Advisory | Stratégie d’installation appliquée |
Annexe E — Modèle de « run‑only users » (flows)
Flow → Details → Run‑only users
- Ajouter le(s) groupe(s) cible(s)
- Pour chaque connexion utilisée :
- Sélectionner "Use this connection" (connexion du propriétaire)
- Sauvegarder
En suivant ce parcours — enregistrement Entra ID, connecteur personnalisé éprouvé, création du plug‑in puis déploiement via Teams — vous exposez votre API protégée par OAuth à Copilot Studio et la rendez disponible aux utilisateurs du tenant de façon fiable et gouvernée.