MCP sicuro in Copilot Studio: quale identità sta davvero eseguendo le azioni?

Gli agenti di intelligenza artificiale hanno smesso di limitarsi a rispondere alle domande. Possono interrogare un database, leggere documenti, aprire ticket, modificare record, eseguire chiamate API e avviare processi aziendali. Con l’introduzione del Model Context Protocol in Copilot Studio, collegare queste capacità a un agente è diventato molto più semplice: un server MCP può pubblicare strumenti e risorse che vengono rilevati dalla piattaforma e resi disponibili all’orchestratore.

La facilità dell’integrazione, però, nasconde una domanda che dovrebbe precedere qualsiasi configurazione: Quale identità vede realmente la risorsa quando l’agente esegue un’azione? Non è una distinzione accademica.

Un agente che legge una pratica con i privilegi dell’utente che ha formulato la richiesta ha un determinato perimetro. Lo stesso agente, se utilizza un’identità applicativa con accesso a tutte le pratiche dell’organizzazione, ne ha uno completamente diverso.

In entrambi i casi, dalla chat potrebbe apparire la stessa risposta. La differenza emerge soltanto osservando i token, i claim, i log di Microsoft Entra e i controlli applicati dal resource server.

Microsoft Copilot Studio consente di collegare un server MCP attraverso il proprio wizard oppure mediante un custom connector. Attualmente supporta il trasporto Streamable HTTP; il precedente trasporto SSE non è più supportato da Copilot Studio dall’agosto 2025. Una volta collegato il server, strumenti e risorse pubblicati vengono rilevati dinamicamente e possono essere resi disponibili all’agente.

La semplificazione è notevole. La sicurezza, invece, rimane una nostra responsabilità.

Che cosa fa realmente MCP

Il Model Context Protocol definisce un modello standardizzato attraverso il quale un’applicazione basata su intelligenza artificiale può scoprire e utilizzare capacità esterne.

Un server MCP può pubblicare:

  • tools, cioè funzioni che l’agente può invocare;
  • resources, cioè dati utilizzabili come contesto;
  • prompts, cioè modelli di prompt predefiniti.

Copilot Studio supporta attualmente tool e resource MCP. Quando il server aggiunge, modifica o rimuove una capacità, Copilot Studio riflette dinamicamente la nuova configurazione. Il server fornisce il nome dello strumento, la descrizione, gli input e gli output; l’orchestratore utilizza queste informazioni per decidere se e quando invocarlo.

Supponiamo che un server MCP esponga questi strumenti:

get_my_orders

get_order

cancel_order

approve_order

Dal punto di vista dell’agente sono quattro funzioni disponibili. Dal punto di vista della sicurezza sono quattro operazioni su un sistema aziendale. La descrizione dello strumento può aiutare il modello a scegliere correttamente, ma non rappresenta una policy di autorizzazione. Un prompt del tipo: “Non mostrare ordini appartenenti ad altri utenti. Non annullare un ordine senza autorizzazione.” può orientare il comportamento dell’agente, ma non deve essere considerato un controllo di sicurezza.

L’autorizzazione deve essere applicata dal server MCP, dall’API downstream o da un servizio di policy attendibile. Il modello può decidere quale strumento proporre o invocare; non deve decidere da solo se l’utente sia autorizzato a utilizzarlo.

Il primo equivoco: la connessione di Copilot Studio non racconta tutta la storia

Quando si aggiunge un server MCP attraverso il wizard di Copilot Studio, è possibile selezionare tre tipi di autenticazione:

  • nessuna autenticazione;
  • API key;
  • OAuth 2.0.

Per OAuth 2.0 sono disponibili configurazioni con dynamic discovery, dynamic client registration o configurazione manuale. Nel caso manuale vengono richiesti client ID, client secret, authorization URL, token URL, refresh URL ed eventuali scope. Il flusso descritto da Microsoft prevede che l’utente venga indirizzato al provider di identità, conceda il consenso e permetta all’agente di ottenere un access token e, quando previsto, un refresh token per il server MCP.

Questo ci dice quale identità viene utilizzata nel primo tratto:

Copilot Studio → server MCP

Non ci dice automaticamente quale identità il server MCP utilizzerà nel tratto successivo:

server MCP → API aziendale

Il server può infatti:

  1. ottenere un nuovo token downstream mantenendo il contesto dell’utente;
  2. ottenere un token applicativo usando una propria workload identity;
  3. usare una credenziale tecnica verso un sistema legacy;
  4. applicare l’autorizzazione localmente e poi invocare un backend con un’identità di servizio.

È quindi necessario separare chiaramente i confini di autenticazione.

Due confini, due token

L’architettura corretta non dovrebbe essere pensata come un’unica catena nella quale lo stesso token viene passato da un componente al successivo.

Esistono almeno due risorse protette:

  • il server MCP;
  • l’API downstream.

Ciascuna dovrebbe ricevere un token emesso espressamente per sé.

Figura 1 – Flusso token

Nel primo hop, Copilot Studio chiama il server MCP con un token destinato al server MCP.

Se il server deve chiamare una seconda API mantenendo l’identità dell’utente, può utilizzare l’On-Behalf-Of flow. In questo modello il token A ha come audience l’API intermedia, mentre l’API intermedia chiede a Microsoft Entra un token B destinato alla risorsa downstream. Microsoft specifica che OBO utilizza esclusivamente delegated scope e che non deve essere usato per scambiare token app-only.

Se invece il server MCP deve eseguire un’operazione come applicazione, può ottenere un token attraverso il client credentials flow, una managed identity o una federated workload identity.

Il punto essenziale è che il token A non deve essere inoltrato direttamente all’API downstream.

La specifica MCP richiede che il parametro OAuth resource identifichi il server MCP destinatario e che il server verifichi che il token sia stato emesso specificamente per lui. Il token passthrough è espressamente vietato perché rompe la separazione delle audience, indebolisce i controlli e rende più ambiguo l’audit trail.

Token A

aud = api://contoso-mcp-orders

Token B

aud = api://contoso-orders-api

Stesso utente, eventualmente. Token differenti. Risorse differenti. Decisioni autorizzative differenti.

Delegated flow: l’agente opera nel contesto dell’utente

Nel modello delegato, l’applicazione agisce per conto di un utente autenticato.

Il resource server riceve un token che contiene gli scope concessi e un contesto riferibile all’utente. L’API può quindi applicare controlli basati sull’identità della persona, sui gruppi, sui ruoli applicativi assegnati e sulla proprietà dell’oggetto richiesto.

Il claim scp contiene gli scope delegati concessi ed è incluso nei token utente. L’API deve verificare che lo scope ricevuto corrisponda a uno degli scope esposti e accettati.

Un flusso end-to-end può apparire così:

Figura 2 – Token End-To-End

Se Domenico è autorizzato a leggere soltanto i propri ordini, il server o l’API possono applicare una regola come:

order.ownerObjectId == token.oid

Se il record appartiene a un altro utente, la risposta dovrà essere:

HTTP/1.1 403 Forbidden

Il vantaggio del modello delegato è che l’identità umana rimane presente lungo la catena.

Questo facilita:

  • l’applicazione delle autorizzazioni individuali;
  • l’attribuzione delle operazioni;
  • la revoca dell’accesso;
  • l’applicazione delle policy di Conditional Access;
  • l’eventuale richiesta di autenticazione step-up;
  • il rispetto delle ACL già esistenti sulla risorsa.

Il limite emerge quando il processo deve essere eseguito senza una sessione utente: job schedulati, elaborazioni batch, sincronizzazioni, attività notturne o operazioni guidate da eventi. In quei casi è normalmente necessaria un’identità applicativa.

Application identity: l’agente non sta più agendo come l’utente

Il client credentials flow permette a un servizio di autenticarsi con le proprie credenziali e chiamare una risorsa senza impersonare un utente. I permessi vengono concessi direttamente all’applicazione, generalmente attraverso application permissions o app role approvati da un amministratore. Microsoft lo indica come il modello tipico per daemon, servizi backend e processi che devono funzionare senza interazione immediata con una persona.

Il flusso diventa:

Figura 3 – Flusso token

La chiamata iniziale può ancora essere associata a Domenico. La chiamata downstream, tuttavia, è autorizzata sulla base dell’identità applicativa del server MCP. Per la Orders API, l’esecutore tecnico è l’applicazione.

Il resource server non deve assumere che l’applicazione possieda gli stessi limiti dell’utente che ha scritto nella chat. Se l’app role consente di leggere tutti gli ordini, il token permette di leggere tutti gli ordini. È qui che nasce il rischio. Un utente con accesso limitato può utilizzare un intermediario molto più privilegiato di lui.

Service principal e managed identity non sono modelli autorizzativi contrapposti

Una managed identity non rappresenta un’alternativa concettuale all’identità applicativa. Rimane una workload identity ed è rappresentata in Microsoft Entra da un service principal. La differenza principale consiste nel modo in cui il workload ottiene e gestisce la propria credenziale.

Con un client secret occorre creare, proteggere, distribuire e ruotare un segreto.

Con un certificato occorre proteggere e rinnovare la chiave privata.

Con workload identity federation si utilizza una relazione di fiducia con un’identità esterna.

Con una managed identity, Azure gestisce il ciclo di vita della credenziale e permette alla risorsa di richiedere token senza conservare secret nel codice o nella configurazione.

La tassonomia corretta è quindi:

Figura 4 – Tassonomia dei modelli autorizzativi

Se il server MCP viene ospitato su Azure Functions, App Service, Container Apps o un’altra risorsa compatibile, la managed identity dovrebbe essere la prima opzione da valutare per il tratto app-only.

Non riduce i privilegi assegnati all’applicazione. Riduce il rischio legato alla gestione delle credenziali.

Il laboratorio: Contoso Orders

Per rendere il problema osservabile utilizziamo un caso di laboratorio semplice.

L’organizzazione Contoso dispone di una piccola API per la gestione degli ordini. Vogliamo costruire un agente Copilot Studio che permetta agli utenti di:

  • visualizzare i propri ordini;
  • leggere il dettaglio di un ordine;
  • annullare un ordine;
  • avviare un processo amministrativo notturno.

Il server MCP pubblica tre strumenti interattivi e uno applicativo:

get_my_orders

get_order

cancel_order

reconcile_pending_orders

Nel dataset sono presenti questi record:

Ordine Proprietario Reparto Stato
ORD-001 Domenico Caldarelli Finance Pending
ORD-002 Laura Bianchi Finance Approved
ORD-003 Direzione Executive Confidential

Gli utenti di laboratorio sono:

Utente

Autorizzazioni

Domenico Caldarelli

Legge e annulla solo i propri ordini

Laura Bianchi

Legge gli ordini Finance e può approvarli

Amministratore

Configura applicazioni e consensi

L’obiettivo è confrontare tre comportamenti:

  1. accesso delegated end-to-end;
  2. accesso applicativo downstream senza controllo sull’utente;
  3. accesso applicativo downstream con authorization near resource.

Figura 5 – Architettura laboratorio

Registrazione delle applicazioni in Microsoft Entra

Il laboratorio richiede tre identità logiche:

  1. un client OAuth utilizzato dalla connessione Copilot Studio;
  2. il server MCP, registrato come API protetta;
  3. la Orders API downstream.

Registrazione del server MCP

Nel Microsoft Entra admin center apriamo:

Identity → Applications → App registrations → New registration

Creiamo l’applicazione:

Name: Contoso MCP Orders Server

Supported account types: Accounts in this organizational directory only

Nella sezione Expose an API impostiamo:

Application ID URI:

api://<MCP-SERVER-APPLICATION-ID>

Aggiungiamo lo scope delegato:

Scope name: mcp.invoke

Who can consent: Admins and users

Admin consent display name: Invoke Contoso MCP Orders Server

User consent display name: Use the Contoso Orders agent

State: Enabled

Lo scope sarà utilizzato nel token che Copilot Studio presenta al server MCP.

Figura 6 – Registrazione dell’API MCP

Registrazione della Orders API

Creiamo una seconda app registration:

Name: Contoso Orders API

Application ID URI:

api://<ORDERS-API-APPLICATION-ID>

Esponiamo due delegated scope:

Orders.Read

Orders.Cancel

Creiamo inoltre un app role destinato esclusivamente alle applicazioni:

Display name: Reconcile orders as application

Allowed member types: Applications

Value: Orders.Reconcile.AsApp

Description: Allows the application to reconcile pending orders

State: Enabled

Limitare Allowed member types ad Applications evita che il medesimo ruolo venga assegnato accidentalmente a utenti. Microsoft Entra utilizza gli scope per le autorizzazioni delegate e gli app role come application permissions nei flussi app-only. Il resource server deve verificare esplicitamente i permessi che si aspetta.

Figura 7 – Scope e app role della Orders API

Il client OAuth usato da Copilot Studio

Per la configurazione OAuth manuale del wizard MCP occorre una registrazione client:

Name: Copilot Studio MCP Orders Client

Platform: Web

Il redirect URI verrà fornito da Copilot Studio durante il wizard. Per questo conviene creare prima la registrazione, annotare client ID e creare una credenziale temporanea, quindi completare il redirect URI dopo che Copilot Studio avrà mostrato il callback.

Nel client aggiungiamo i delegated permission verso il server MCP:

api://<MCP-SERVER-APPLICATION-ID>/mcp.invoke

Per il laboratorio possiamo utilizzare un client secret a breve durata.

In produzione è necessario ricordare che il secret appartiene al client OAuth usato dal connettore. Non è la credenziale con la quale il server MCP accede alla Orders API.

Sono due ruoli differenti:

Copilot MCP Client

→ ottiene Token A per il server MCP

MCP workload identity

→ ottiene Token B per la Orders API

Collegamento del server MCP a Copilot Studio

Apriamo l’agente in Copilot Studio.

La generative orchestration deve essere abilitata, perché è il componente che consente all’agente di selezionare e utilizzare dinamicamente i tool MCP.

Accediamo a: Tools → Add a tool → New tool → Model Context Protocol

Inseriamo:

Server name: Contoso Orders MCP

Server description: Allows authorized Contoso users to view and manage orders.

Server URL: https://mcp-orders.contoso.com/mcp

La descrizione è importante perché l’orchestratore la utilizza per comprendere quando richiamare il server. Non deve contenere istruzioni generiche o ambigue e non deve promettere capacità che il server non possiede.

Selezioniamo: Authentication type: OAuth 2.0

OAuth type: Manual

Configuriamo: 

Client ID:

<CLIENT-ID-COPILOT-MCP>

Client secret: <CLIENT-SECRET>

Authorization URL:

https://login.microsoftonline.com/<TENANT-ID>/oauth2/v2.0/authorize

Token URL:

https://login.microsoftonline.com/<TENANT-ID>/oauth2/v2.0/token

Refresh URL:

https://login.microsoftonline.com/<TENANT-ID>/oauth2/v2.0/token

Scopes:

openid profile offline_access

api://<MCP-SERVER-APPLICATION-ID>/mcp.invoke

Copilot Studio mostra un callback URL. Copiamolo nella sezione Authentication della registrazione Copilot Studio MCP Orders Client.

Torniamo nel wizard, creiamo la connessione e aggiungiamo il server all’agente.

La procedura e i campi possono cambiare nell’interfaccia nel tempo; la documentazione Microsoft aggiornata a maggio 2026 descrive però esattamente questo percorso, incluse le modalità Dynamic discovery, Dynamic e Manual.

Figura 8 – MCP onboarding wizard

Limitare gli strumenti disponibili

Quando un server MCP viene aggiunto a un agente, tutti i tool risultano inizialmente abilitati attraverso l’opzione Allow all.

Per un ambiente enterprise questa impostazione merita attenzione. Se domani il proprietario del server pubblica un nuovo tool chiamato:

delete_all_orders

lasciare ogni strumento automaticamente disponibile aumenterebbe il perimetro dell’agente senza un’esplicita revisione. Copilot Studio permette di disattivare Allow all e abilitare singolarmente i tool. Quando l’opzione è disabilitata, i nuovi strumenti aggiunti successivamente al server restano spenti per impostazione predefinita.

Nel laboratorio abilitiamo:

get_my_orders

get_order

cancel_order

Lasciamo disabilitato:

reconcile_pending_orders

Quest’ultimo sarà destinato a un processo backend app-only e non a una richiesta conversazionale generica.

Figura 9 – Selezione tool MCP

Protezione del server MCP

Il server MCP deve validare il token ricevuto da Copilot Studio.

Per una web API ASP.NET Core possiamo utilizzare Microsoft.Identity.Web.

Configurazione indicativa:

Nel Program.cs:

In un’implementazione reale, lo scope può contenere più valori separati da spazi. È quindi preferibile utilizzare i metodi di verifica forniti da Microsoft Identity Web oppure un authorization handler che analizzi correttamente l’insieme degli scope.

Microsoft ricorda inoltre che un’applicazione non dovrebbe costruire dipendenze fragili sulla presenza o sull’ordine di singoli claim. scp identifica un token utente con scope delegati, mentre roles può contenere app role assegnati a un’applicazione oppure a un utente. Il claim opzionale idtyp può aiutare a distinguere token app-only e app+user, ma il modello più sicuro consiste nel definire endpoint e policy che sappiano in anticipo quale tipo di token accettare.

Primo test: delegated end-to-end

Domenico apre l’agente e chiede:

Mostrami i miei ordini in attesa.

Copilot Studio seleziona il tool:

get_my_orders

Il server MCP riceve il token A:

Il server valida:

  • firma;
  • issuer;
  • tenant;
  • scadenza;
  • audience;
  • scope.

A questo punto deve interrogare la Orders API. Non può inoltrare il token appena ricevuto, perché la sua audience è il server MCP. Utilizza quindi OBO per ottenere un token B:

Il token B sarà destinato alla Orders API:

La Orders API usa oid per limitare i risultati:

Il risultato atteso è:

Figura 10 – Token delegated

Secondo test: accesso a un ordine non autorizzato

Domenico chiede:

Mostrami il dettaglio dell’ordine riservato della Direzione.

L’agente può decidere di invocare:

get_order(orderId=”ORD-003″)

Il fatto che il modello abbia selezionato il tool non significa che l’operazione sia autorizzata.

La Orders API verifica la proprietà dell’oggetto:

Il risultato atteso è:

HTTP/1.1 403 Forbidden

Questo test dimostra un principio importante: la descrizione del tool e le istruzioni dell’agente non sostituiscono l’autorizzazione sull’oggetto.

Figura 11 – Richiesta negata nel test chat

Figura 12 – Log di autorizzazione negata

Terzo test: app-only downstream

Il server MCP deve eseguire la riconciliazione notturna degli ordini pendenti. Non esiste un utente interattivo. Assegniamo alla managed identity del server MCP l’app role:

Orders.Reconcile.AsApp

Il server ottiene un token per la Orders API:

Il token risultante non contiene scp.

Dovrebbe contenere l’app role assegnato:

La Orders API espone un endpoint separato:

La separazione degli endpoint rende evidente quale modello autorizzativo è accettato:

/api/orders/my

→ delegated

/api/orders/{id}

→ delegated

/api/orders/reconcile

→ app-only

È più sicuro di un endpoint universale che prova a dedurre il comportamento esclusivamente dalla presenza di scp o roles.

Figura 13 – Sign-in della managed identity

Figura 14 – Token app-only

Il caso pericoloso: app-only usato per una richiesta utente

Immaginiamo ora una configurazione differente.

Domenico chiede:

Mostrami l’ordine ORD-003.

Il server MCP riceve correttamente il token delegato di Domenico, ma invece di utilizzare OBO chiama la Orders API attraverso la managed identity.

La Orders API vede:

Contoso MCP Orders Managed Identity

Non vede Domenico come principal autorizzato.

Se l’applicazione dispone di un permesso globale come:

Orders.Read.All

la richiesta potrebbe riuscire.

Dal punto di vista dei singoli componenti:

  • Domenico è autenticato;
  • Copilot Studio ha chiamato correttamente il tool;
  • il server MCP possiede un token valido;
  • la Orders API ha autorizzato l’applicazione;
  • il database ha restituito il record.

Eppure il sistema ha violato il modello autorizzativo dell’organizzazione.

Il server MCP è diventato un intermediario privilegiato.

Questa è una forma applicativa del problema del confused deputy: un componente con privilegi propri esegue un’azione per un soggetto che non dispone degli stessi privilegi, senza verificare correttamente che quel soggetto possa richiederla.

La documentazione MCP tratta espressamente i rischi di confused deputy nei server proxy e richiede controlli di consenso e separazione per client. Nel nostro scenario aziendale il principio si estende alla decisione applicativa: il possesso di un’identità privilegiata non autorizza automaticamente ogni richiesta proveniente dall’agente.

Authorization near resource

Nel modello app-only, la decisione deve essere applicata il più vicino possibile alla risorsa.

Esistono diverse possibilità:

  • il server MCP verifica l’autorizzazione prima di chiamare il backend;
  • la Orders API riceve un’attestazione attendibile sull’utente originatore;
  • un policy decision point esterno autorizza la combinazione utente-azione-oggetto;
  • il sistema separa la proposta dell’agente dall’esecuzione effettiva;
  • un workflow umano approva le operazioni più sensibili.

Nel laboratorio possiamo applicare il controllo nel server MCP:

È importante non ridurre questa soluzione all’aggiunta di un header:

X-User-Id: Domenico-object-id

Un header arbitrario può essere falsificato se non esiste un confine di fiducia ben definito.

Se il contesto dell’utente deve raggiungere la risorsa finale, è preferibile:

  • mantenere il flusso delegated tramite OBO;
  • usare un token interno firmato e destinato esclusivamente al backend;
  • utilizzare un servizio di autorizzazione consultato da MCP e API;
  • verificare il contesto prima di eseguire l’operazione app-only.

Che cosa cercare nei token

Per capire chi sta agendo non basta cercare un singolo claim.

Occorre osservare l’insieme del token e conoscere il modello previsto dall’endpoint.

I claim più utili sono:

Claim

Significato operativo

aud

Risorsa alla quale il token è destinato

iss

Tenant e security token service emittente

tid

Tenant Microsoft Entra

scp

Scope delegati; presente nei token utente

roles

App role o ruoli assegnati sul resource server

oid

Object ID del principal

azp / appid

Applicazione client che ha richiesto il token

sub

Subject del token

idtyp

Claim opzionale utile a distinguere app e app+user

jti / token identifier

Identificatore utile per correlazione e troubleshooting

L’audience deve sempre essere validata. Microsoft specifica che una risorsa deve rifiutare un token il cui aud non corrisponde al destinatario previsto. La documentazione avverte inoltre di non assumere che tutti i claim siano sempre presenti e di non usare token destinati a servizi Microsoft come contratti applicativi per il proprio codice.

Una regola pratica può essere:

scp presente

+ utente atteso

+ endpoint delegated

= richiesta delegata

app role applicativo previsto

+ endpoint app-only

+ workload identity autorizzata

= richiesta applicativa

Non:

roles presente

= sicuramente service principal

Il claim roles può essere presente anche nei token utente quando alla persona è stato assegnato un app role sulla risorsa.

Test dell’audience errata

Un controllo semplice ma molto utile consiste nel presentare al server MCP un token emesso per un’altra risorsa, per esempio Microsoft Graph o la Orders API.

Il server deve rifiutarlo:

HTTP/1.1 401 Unauthorized

L’errore deve avvenire anche se:

  • il token è firmato correttamente;
  • non è scaduto;
  • appartiene allo stesso tenant;
  • contiene scope apparentemente potenti.

La firma valida dimostra che Microsoft Entra ha emesso il token.

Non dimostra che il token sia stato emesso per quel server.

La specifica MCP richiede esplicitamente che i server accettino solo token destinati a loro e vieta di usare il server come proxy di token ottenuti per altre risorse.

Figura 15 – Audience mismatch

Logging: ricostruire chi ha fatto cosa

I sign-in log di Microsoft Entra mostrano l’autenticazione e l’ottenimento dei token.

I log del server MCP devono mostrare:

  • quale utente ha avviato la richiesta;
  • quale agente e sessione l’hanno generata;
  • quale tool è stato selezionato;
  • quale risorsa è stata richiesta;
  • quale identità downstream è stata utilizzata;
  • quale decisione di autorizzazione è stata presa.

I log della Orders API devono mostrare:

  • principal effettivamente autorizzato;
  • scope o app role;
  • oggetto interessato;
  • esito dell’operazione.

Un evento applicativo può avere questa struttura:

Non è necessario registrare il prompt completo, il token o tutti i parametri. Anzi, può essere pericoloso. Prompt, output e tool argument possono contenere:

  • dati personali;
  • informazioni aziendali riservate;
  • segreti accidentalmente forniti dall’utente;
  • identificativi finanziari;
  • contenuti provenienti da documenti.

Occorre registrare ciò che serve all’audit, mascherare i riferimenti sensibili ed evitare assolutamente di salvare access token e refresh token.

Una possibile query di correlazione in Log Analytics è:

A questa vista devono essere affiancati i log del server MCP e della Orders API utilizzando lo stesso correlationId.

Figura 16 – Correlazione end-to-end dei log

Conditional Access e step-up authentication

Nel modello delegated può essere necessario richiedere un’autenticazione più forte per una determinata operazione.

Leggere un ordine potrebbe richiedere una sessione standard.

Annullare un ordine superiore a una certa soglia potrebbe richiedere MFA recente o uno specifico authentication context.

Il middle tier non deve nascondere o aggirare la challenge. Microsoft segnala che inoltrare token tra componenti in modo improprio può impedire di soddisfare Conditional Access, token binding e scenari step-up.

Un pattern applicativo possibile è:

Figura 17 – Possibile pattern

La compatibilità concreta della challenge con l’esperienza Copilot Studio e con il connettore utilizzato deve essere verificata nel tenant. Quando non è possibile propagare correttamente lo step-up, l’alternativa più prudente consiste nel trasformare l’azione in una richiesta di approvazione separata.

Separare “decidere” da “eseguire”

Gli agenti sono particolarmente adatti a:

  • raccogliere informazioni;
  • preparare un riepilogo;
  • proporre un’azione;
  • costruire una richiesta;
  • classificare e indirizzare un’attività.

Non ogni azione proposta deve essere immediatamente eseguita. Per operazioni ad alto impatto possiamo dividere il processo:

  1. L’agente prepara la richiesta.
  2. L’utente verifica i dati.
  3. Un approvatore conferma.
  4. Un workflow applicativo esegue l’operazione.
  5. Tutti i passaggi vengono registrati.

Questo modello è particolarmente indicato per:

  • disabilitazione di account;
  • modifiche ai permessi;
  • cancellazione di dati;
  • approvazione di pagamenti;
  • modifica di configurazioni;
  • operazioni tenant-wide;
  • attività irreversibili.

L’identità app-only può quindi essere usata dal workflow esecutivo senza essere esposta direttamente a una richiesta conversazionale non approvata.

Governare il server MCP in Power Platform

L’integrazione MCP di Copilot Studio utilizza l’infrastruttura dei Power Platform connector. Di conseguenza, le data policy applicate ai connector regolano anche l’accesso del server MCP e dei relativi tool.

La governance deve quindi includere almeno:

Ambienti separati

Dev, test e produzione non dovrebbero condividere:

  • connessioni;
  • service principal;
  • endpoint MCP;
  • database;
  • secret;
  • policy permissive.

Connection references

La connessione non dovrebbe dipendere dall’account personale del maker.

Occorre documentare:

  • proprietario;
  • utenti autorizzati;
  • durata delle credenziali;
  • processo di rotazione;
  • ambiente;
  • server MCP associato.

Data policy

Il connettore MCP deve essere classificato correttamente.

Un server che accede a dati aziendali non dovrebbe poter essere combinato liberamente con connector consumer o servizi esterni non autorizzati.

Inventario

Per ogni agente occorre conoscere:

  • proprietario;
  • business owner;
  • ambiente;
  • server MCP collegati;
  • tool abilitati;
  • identità downstream;
  • permessi assegnati;
  • data policy applicabile;
  • data dell’ultima revisione.

Controllo delle modifiche

Poiché tool e risorse possono essere aggiornati dinamicamente dal server, la modifica del server MCP equivale a una modifica delle capacità dell’agente.

Disabilitare Allow all riduce il rischio, ma non sostituisce:

  • code review;
  • versionamento;
  • approvazione;
  • monitoraggio dell’integrità;
  • test prima della pubblicazione.

Ciò che l’autenticazione non risolve

Una configurazione OAuth corretta non rende automaticamente sicuro il sistema.

Rimangono altri rischi.

Tool poisoning

La descrizione di un tool può essere manipolata per influenzare il modello e indurlo a selezionare una funzione in condizioni non previste.

Prompt injection indiretta

Un documento, una risposta API o una risorsa MCP può contenere istruzioni che tentano di modificare il comportamento dell’agente.

Rug pull del server

Un server approvato può cambiare successivamente descrizioni, output o comportamento.

Combinazione di strumenti

Due tool singolarmente innocui possono diventare pericolosi se utilizzati insieme. Un tool legge dati riservati, un altro invia messaggi verso l’esterno.

Output non attendibile

Il risultato restituito dal server MCP deve essere trattato come input esterno, non come istruzione attendibile.

SSRF e discovery

I flussi di metadata discovery e gli endpoint forniti da un server malevolo possono tentare di indirizzare il client verso risorse interne o metadata service. Le linee guida MCP includono esplicitamente confused deputy, token passthrough, SSRF, session hijacking e scope minimization tra i rischi da considerare.

Questo articolo si concentra sull’identità esecutiva, ma la stessa architettura deve essere inserita in un threat model più ampio.

Delegated oppure app-only?

Non esiste una scelta universalmente corretta.

La decisione dipende dall’azione.

Scenario

Modello consigliato

Leggere “i miei ordini”

Delegated

Consultare file già accessibili all’utente

Delegated

Annullare una richiesta personale

Delegated con controllo sull’oggetto

Generare un report notturno

App-only

Sincronizzare un catalogo

App-only

Eseguire un’attività batch

App-only

Approvare un pagamento

Delegated con step-up o workflow approvativo

Modificare permessi tenant-wide

Workflow separato e app-only fortemente limitato

Operazione avviata dalla chat ma eseguita come app

Controllo esplicito dell’utente originatore

La regola più utile è:

Delegated quando il potere dell’agente deve coincidere con quello dell’utente. App-only quando l’azione appartiene realmente al servizio e può essere delimitata, approvata e verificata come tale.

Checklist di hardening

Prima di pubblicare un agente collegato a un server MCP è opportuno verificare quanto segue.

Identità e token

  • Il server MCP valida firma, issuer, scadenza, tenant e audience.
  • I token ricevuti dal client non vengono inoltrati alle API downstream.
  • Ogni risorsa riceve un token emesso per la propria audience.
  • Gli endpoint delegated verificano gli scope attesi.
  • Gli endpoint app-only verificano app role e workload identity autorizzate.
  • Le application permission sono limitate alla singola funzione.
  • Managed identity o federated credential sono preferite ai secret.
  • Gli app role applicativi hanno Allowed member types coerente.

Autorizzazione

  • La decisione viene applicata sul singolo oggetto.
  • L’identità app-only non sostituisce i diritti dell’utente senza un controllo aggiuntivo.
  • Le operazioni sensibili richiedono step-up o approvazione.
  • Proposta ed esecuzione sono separate per le azioni irreversibili.
  • Il server rifiuta token con audience errata.
  • Un errore di autorizzazione restituisce 403, non dati parziali.

Copilot Studio e Power Platform

  • Allow all è disabilitato quando non necessario.
  • Solo i tool approvati sono abilitati.
  • Le data policy regolano il connettore MCP.
  • La connessione non appartiene a un account personale non governato.
  • Dev, test e produzione utilizzano identità separate.
  • Le modifiche ai tool passano attraverso un processo di revisione.
  • L’agente viene pubblicato soltanto dopo il test delle autorizzazioni negative.

Logging

  • Ogni richiesta possiede un correlation ID.
  • Sono distinti utente originatore e identità esecutiva.
  • I log indicano tool, risorsa, decisione ed esito.
  • Access token e refresh token non vengono registrati.
  • Prompt e output sensibili vengono minimizzati o mascherati.
  • Sign-in log, log MCP e log downstream sono correlabili.

Conclusioni

MCP riduce in modo significativo la complessità necessaria per collegare un agente a strumenti e dati aziendali. Copilot Studio rende questa integrazione ancora più accessibile: il server viene aggiunto come tool, le capacità vengono rilevate dinamicamente e l’orchestratore può selezionarle durante la conversazione.

La semplicità dell’esperienza non deve però nascondere la struttura reale del sistema. Tra l’utente e la risorsa possono esistere più hop, più token e più identità.

Nel flusso delegated, il backend può continuare a vedere e autorizzare l’utente.

Nel flusso app-only, il backend autorizza il service principal o la managed identity.

Entrambe le configurazioni possono essere legittime.

Il problema nasce quando l’organizzazione crede di aver conservato il perimetro dell’utente, mentre la risorsa sta in realtà autorizzando un’applicazione molto più privilegiata. La UI non basta a rispondere. Il nome della connessione non basta. La descrizione del tool non basta. Occorre guardare quale token arriva alla risorsa, quale audience contiene, quali scope o app role vengono valutati e quale principal compare nei log.

La regola operativa può essere riassunta in una frase: Se non sai quale token vede la risorsa, non sai quale identità sta agendo. E se non sai quale identità sta agendo, non hai ancora governato il tuo agente.

Stay tuned!