Autenticazione nell'API Direct Line 3.0

Un client può autenticare le richieste all'API Direct Line 3.0 usando un segreto che si ottiene dalla pagina di configurazione del canale Direct Line nel portale di Bot Framework o un token che si ottiene in fase di esecuzione. Il segreto o token deve essere specificato nell'intestazione Authorization di ogni richiesta, usando questo formato:

Authorization: Bearer SECRET_OR_TOKEN

Segreti e token

Un segreto Direct Line è una chiave master che può essere usata per accedere a qualsiasi conversazione che appartiene al bot associato. Un segreto può essere usato anche per ottenere un token. I segreti non scadono.

Un token Direct Line è una chiave che può essere usata per accedere a un'unica conversazione. Un token scade, ma può essere aggiornato.

Per decidere se o quando usare la chiave privata o un token, è necessario esaminare i requisiti di sicurezza. L'esposizione della chiave privata può essere accettabile se eseguita intenzionalmente e con cautela. In realtà, questo è il comportamento predefinito perché consente a Direct Line di determinare se il client è legittimo. In generale, però, implica problemi di sicurezza se si cerca di salvare in modo permanente i dati dell'utente. Per altre informazioni, vedere la sezione Considerazioni relative alla sicurezza.

Creare un'applicazione da servizio a servizio, che specifichi il segreto nell'intestazione Authorization delle richieste API Direct Line, potrebbe essere l'approccio più semplice. Scrivendo un'applicazione in cui il client viene eseguito in un browser Web o app per dispositivi mobili, è possibile scambiare il segreto per un token (che funziona solo per una singola conversazione e scadrà se non aggiornato) e specificare il token nell'intestazione Authorization delle richieste API Direct Line. Scegliere il modello di sicurezza più adatto alle proprie esigenze.

Nota

Le credenziali del client Direct Line sono diverse da quelle del bot. Ciò consente di modificare le chiavi in modo indipendente e permette di condividere i token client senza rivelare la password del bot.

Ottenere un segreto Direct Line

È possibile ottenere un segreto Direct Line tramite la pagina di configurazione del canale Direct Line per il bot nel portale di Azure:

Direct Line configuration

Generare un token Direct Line

Per generare un token Direct Line che può essere usato per accedere a una singola conversazione, ottenere prima di tutto il segreto Direct Line dalla pagina di configurazione del canale Direct Line nel portale di Azure. Immettere questa richiesta per scambiare il segreto Direct Line per un token Direct Line:

POST https://directline.botframework.com/v3/directline/tokens/generate
Authorization: Bearer SECRET

Nell'intestazione Authorization della richiesta, sostituire il SEGRETO con il valore del segreto Direct Line.

I frammenti di codice seguenti offrono un esempio della richiesta e della risposta dei token.

Richiesta

POST https://directline.botframework.com/v3/directline/tokens/generate
Authorization: Bearer RCurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0

Il payload della richiesta, che contiene i parametri dei token, è facoltativo ma consigliato. Quando si genera un token che può essere inviato al servizio Direct Line, specificare il payload seguente per rendere più sicura la connessione. Includendo questi valori, Direct Line può eseguire un'ulteriore convalida di sicurezza dell'ID e del nome utente, impedendo la manomissione di questi valori da parte di clienti malintenzionati. Se si includono questi valori, migliora anche la capacità di Direct Line di inviare l'attività di aggiornamento della conversazione, consentendo di generare l'aggiornamento non appena l'utente partecipa alla conversazione. Quando queste informazioni non vengono fornite, l'utente deve inviare contenuto prima che Direct Line possa inviare l'aggiornamento della conversazione.

{
  "user": {
    "id": "string",
    "name": "string"
  },
  "trustedOrigins": [
    "string"
  ]
}
Parametro Tipo Description
user.id stringa (Facoltativo). ID specifico del canale dell'utente da codificare all'interno del token. Per un utente di Direct deve iniziare con dl_. È possibile creare un ID utente univoco per ogni conversazione e, per maggiore sicurezza, è necessario che questo ID sia indecifrabile.
user.name stringa (Facoltativo). Nome descrittivo visualizzato dell'utente da codificare all'interno del token.
trustedOrigins Matrice di stringhe (Facoltativo). Elenco di domini attendibili da incorporare all'interno del token. Si tratta dei domini che possono ospitare il client Chat del bot. Deve corrispondere all'elenco nella pagina di configurazione di Direct Line per il bot.

Response

Se la richiesta ha esito positivo, la risposta conterrà un token che è valido per una conversazione e un valore expires_in che indica il numero di secondi prima che il token scada. Perché il token rimanga utile, è necessario aggiornare il token prima che scada.

HTTP/1.1 200 OK
[other headers]
{
  "conversationId": "abc123",
  "token": "RCurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xn",
  "expires_in": 1800
}

Generazione di token e avvio di conversazione

L'operazione di generazione di token (POST /v3/directline/tokens/generate) è simile all'operazione di avvio della conversazione (POST /v3/directline/conversations) perché entrambe restituiscono un token che può essere usato per accedere a una singola conversazione. Tuttavia, a differenza dell'operazione Avvia conversazione, l'operazione Genera token non avvia la conversazione, non contatta il bot e non crea un URL WebSocket di streaming.

Se si vuole distribuire il token ai client affinché questi avviino la conversazione, usare l'operazione di generazione di token. Se si intende avviare la conversazione immediatamente, usare l'operazione di avvio di conversazione.

Aggiornare un token Direct Line

Un token Direct Line può essere aggiornato un numero illimitato di volte, purché non sia scaduto. Non è possibile aggiornare un token scaduto. Per aggiornare un token Direct Line, eseguire questa richiesta:

POST https://directline.botframework.com/v3/directline/tokens/refresh
Authorization: Bearer TOKEN_TO_BE_REFRESHED

Nell'intestazione Authorization della richiesta, sostituire TOKEN_TO_BE_REFRESHED con il token Direct Line che si desidera aggiornare.

I frammenti di codice seguenti offrono un esempio della richiesta e della risposta dei token.

Richiedi

POST https://directline.botframework.com/v3/directline/tokens/refresh
Authorization: Bearer CurR_XV9ZA.cwA.BKA.iaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xn

Risposta

Se la richiesta ha esito positivo, la risposta conterrà un nuovo token che è valido per la stessa conversazione del token precedente e un valore expires_in che indica il numero di secondi prima che il nuovo token scada. Per fare in modo che il nuovo token rimanga valido, è necessario aggiornare il token prima della scadenza.

HTTP/1.1 200 OK
[other headers]
{
  "conversationId": "abc123",
  "token": "RCurR_XV9ZA.cwA.BKA.y8qbOF5xPGfiCpg4Fv0y8qqbOF5x8qbOF5xniaJrC8xpy8qbOF5xnR2vtCX7CZj0LdjAPGfiCpg4Fv0",
  "expires_in": 1800
}

Autenticazione servizio Bot di Intelligenza artificiale di Azure

Le informazioni presentate in questa sezione si basano sull'articolo Aggiungere l'autenticazione al bot tramite Azure AI servizio Bot.

L'autenticazione di Azure AI servizio Bot consente di autenticare gli utenti e ottenere token di accesso da diversi provider di identità, ad esempio Microsoft Entra ID, GitHub, Uber e così via. È anche possibile configurare l'autenticazione per un provider di identità OAuth2 personalizzato. In questo modo è possibile scrivere una parte del codice di autenticazione che funziona in tutti i provider di identità e i canali supportati. Per usare queste funzionalità:

  1. Configurare settings in modo statico nel bot che contiene i dettagli della registrazione dell'applicazione con un provider di identità.
  2. Usare un oggetto OAuthCard, supportato dalle informazioni sull'applicazione fornite nel passaggio precedente, per l'accesso di un utente.
  3. Recuperare i token di accesso tramite l'API servizio Bot di intelligenza artificiale di Azure.

Considerazioni sulla sicurezza

Quando si usa l'autenticazione servizio Bot di intelligenza artificiale di Azure con chat Web, è necessario tenere presenti alcune importanti considerazioni sulla sicurezza.

  1. Rappresentazione. La rappresentazione è quando un utente malintenzionato convince il bot che l'autore dell'attacco è qualcun altro. In chat Web un utente malintenzionato può rappresentare un altro utente modificando l'ID utente dell'istanza di chat Web. Per evitare la rappresentazione, è consigliabile che gli sviluppatori di bot rendano l'ID utente inutilizzabile.To prevent impersonation, we recommend that bot developers make the user ID unguessable.

    Se si abilitano le opzioni di autenticazione avanzata, Azure AI servizio Bot può rilevare e rifiutare ulteriormente qualsiasi modifica dell'ID utente. In questo modo l'ID utente (Activity.From.Id) nei messaggi inviati da Direct Line al bot sarà sempre uguale a quello usato per l'inizializzazione di Web Chat. Questa funzionalità richiede che l'ID utente inizi con dl_.

    Nota

    Quando si specifica User.Id durante lo scambio di un segreto per un token, tale User.Id viene incorporato nel token. Direct Line assicura che i messaggi inviati al bot abbiano tale ID come From.Id dell'attività. Se un client invia un messaggio a Direct Line con un From.Id diverso, verrà modificato nell'ID nel token prima di inoltrare il messaggio al bot. Non è quindi possibile usare un altro ID utente dopo l'inizializzazione di un segreto del canale con un ID utente

  2. Identità utente. Ogni utente ha più identità utente:

    1. Identità dell'utente in un canale.
    2. Identità dell'utente in un provider di identità a cui è interessato il bot.

Quando un bot chiede all'utente A in un canale di accedere a un provider di identità P, il processo di accesso deve garantire che l'utente A sia quello che accede a P. Se un altro utente B è autorizzato ad accedere, l'utente A avrà accesso alla risorsa dell'utente B tramite il bot. In chat Web sono disponibili due meccanismi per garantire che l'utente corretto abbia eseguito l'accesso come descritto di seguito.

  1. Al termine dell'accesso, in passato, l'utente è stato presentato con un codice a 6 cifre generato in modo casuale (codice magic). L'utente doveva digitare questo codice nella conversazione che aveva avviato l'accesso per completare questa procedura. Questo meccanismo tende a generare un'esperienza utente insoddisfacente. Inoltre, è ancora soggetto ad attacchi di phishing. Un utente malintenzionato può ingannare un altro utente per accedere e ottenere il codice fittizio tramite phishing.

  2. A causa dei problemi con l'approccio precedente, l'intelligenza artificiale di Azure servizio Bot rimossa la necessità del codice magic. Azure AI servizio Bot garantisce che il processo di accesso possa essere completato solo nella stessa sessione del browser della chat Web stessa. Per abilitare questa protezione, in qualità di sviluppatore di bot, è necessario avviare chat Web con un token Direct Line che contiene un elenco di domini attendibili che possono ospitare il client di chat Web del bot. In passato era possibile ottenere questo token solo passando un parametro facoltativo non documentato all'API dei token di Direct Line. Ora, con le opzioni di autenticazione avanzata, è possibile specificare staticamente l'elenco di domini di origine attendibili nella pagina di configurazione di Direct Line.

Per altre informazioni, vedere Aggiungere l'autenticazione al bot tramite l'servizio Bot di Intelligenza artificiale di Azure.

Esempi di codice

Il controller .NET seguente funziona con le opzioni di autenticazione avanzata abilitate e restituisce un token di Direct Line e un ID utente.

public class HomeController : Controller
{
    public async Task<ActionResult> Index()
    {
        var secret = GetSecret();

        HttpClient client = new HttpClient();

        HttpRequestMessage request = new HttpRequestMessage(
            HttpMethod.Post,
            $"https://directline.botframework.com/v3/directline/tokens/generate");

        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", secret);

        var userId = $"dl_{Guid.NewGuid()}";

        request.Content = new StringContent(
            JsonConvert.SerializeObject(
                new { User = new { Id = userId } }),
                Encoding.UTF8,
                "application/json");

        var response = await client.SendAsync(request);
        string token = String.Empty;

        if (response.IsSuccessStatusCode)
        {
            var body = await response.Content.ReadAsStringAsync();
            token = JsonConvert.DeserializeObject<DirectLineToken>(body).token;
        }

        var config = new ChatConfig()
        {
            Token = token,
            UserId = userId
        };

        return View(config);
    }
}

public class DirectLineToken
{
    public string conversationId { get; set; }
    public string token { get; set; }
    public int expires_in { get; set; }
}
public class ChatConfig
{
    public string Token { get; set; }
    public string UserId { get; set; }
}

Il controller JavaScript seguente funziona con le opzioni di autenticazione avanzata abilitate e restituisce un token di Direct Line e un ID utente.

var router = express.Router(); // get an instance of the express Router

// Get a directline configuration (accessed at GET /api/config)
const userId = "dl_" + createUniqueId();

router.get('/config', function(req, res) {
    const options = {
        method: 'POST',
        uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
        headers: {
            'Authorization': 'Bearer ' + secret
        },
        json: {
            User: { Id: userId }
        }
    };

    request.post(options, (error, response, body) => {
        if (!error && response.statusCode < 300) {
            res.json({
                    token: body.token,
                    userId: userId
                });
        }
        else {
            res.status(500).send('Call to retrieve token from Direct Line failed');
        }
    });
});

Informazioni aggiuntive