Authentification Direct Line API 3.0

Un client peut authentifier les demandes adressées à l’API Direct Line 3.0 soit à l’aide d’un secret que vous obtenez dans la page de configuration du canal Direct Line sur le portail Bot Framework, ou à l’aide d’un jeton que vous obtenez au moment de l’exécution. Le secret ou le jeton doivent être spécifiés dans l’en-tête Authorization de chaque demande, en utilisant le format suivant :

Authorization: Bearer SECRET_OR_TOKEN

Secrets et jetons

Un secret Direct Line est une clé principale qui peut être utilisée pour accéder à toute conversation appartenant au robot associé. Un secret peut également être utilisé pour obtenir un jeton. Les secrets n'expirent pas.

Un jeton Direct Line est une clé qui peut être utilisée pour accéder à une seule conversation. Un jeton expire, mais peut être actualisé.

Pour déterminer quand ou s’il faut utiliser la clé secrète ou un jeton, vous devez vous baser sur des considérations relatives à la sécurité. L’exposition de la clé secrète peut être acceptable si cela se fait intentionnellement et avec précaution. Il s’agit en fait du comportement par défaut, car cela permet à Direct Line de déterminer si le client est légitime. D’une façon générale, la sécurité est cependant un problème si vous essayez de conserver des données utilisateur. Pour plus d’informations, consultez la section Considérations relatives à la sécurité.

Si vous créez une application de service à service, l’approche la plus simple peut consister à spécifier le secret dans l’en-tête Authorization des demandes d’API Direct Line. Si vous écrivez une application où le client s’exécute dans un navigateur web ou une application mobile, vous souhaiterez peut-être échanger votre secret contre un jeton (qui fonctionne uniquement pour une conversation et expire sauf s’il est actualisé) et spécifier le jeton dans l’en-tête Authorization des demandes d’API Direct Line. Choisissez le modèle de sécurité qui vous convient le mieux.

Remarque

Les informations d’identification de votre client Direct Line sont différentes de celles de votre robot. Cela vous permet de réviser vos clés de manière indépendante et de partager des jetons de client sans révéler le mot de passe de votre robot.

Obtenir un secret Direct Line

Vous pouvez obtenir un secret Direct Line à partir de la page de configuration de canal Direct Line pour votre bot dans le portail Azure :

Direct Line configuration

Générer un jeton Direct Line

Pour générer un jeton Direct Line qui peut être utilisé pour accéder à une conversation unique, commencez par obtenir le secret Direct Line à partir de la page de configuration de canal Direct Line dans le portail Azure. Ensuite, émettez la demande suivante pour échanger votre secret Direct Line contre un jeton Direct Line :

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

Dans l’en-tête Authorization de cette demande, remplacez SECRET par la valeur de votre secret Direct Line.

Les extraits de code suivants illustrent la demande et la réponse dans le cadre de la génération de jeton.

Requête

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

La charge utile de la demande, qui contient les paramètres de jeton, est facultative mais recommandée. Lorsque vous générez un jeton qui peut être renvoyé au service Direct Line, fournissez la charge utile suivante pour renforcer la sécurité de la connexion. Lorsque vous incluez ces valeurs, Direct Line peut effectuer une validation de sécurité supplémentaire du nom et de l’ID utilisateur, ce qui empêche la falsification de ces valeurs par des clients malveillants. L’ajout de ces valeurs améliore également la capacité de Direct Line à envoyer l’activité de mise à jour de la conversation, ce qui lui permet de générer la mise à jour de la conversation dès que l’utilisateur rejoint la conversation. Lorsque ces informations ne sont pas fournies, l'utilisateur doit envoyer du contenu pour que Direct Line puisse envoyer la mise à jour de la conversation.

{
  "user": {
    "id": "string",
    "name": "string"
  },
  "trustedOrigins": [
    "string"
  ]
}
Paramètre Type Description
user.id string facultatif. ID spécifique au canal de l’utilisateur à encoder dans le jeton. Pour un utilisateur Direct Line, il doit commencer par dl_. Vous pouvez créer un ID utilisateur unique pour chaque conversation et, pour une meilleure sécurité, vous devez faire en sorte que cet ID ne puisse pas être deviné.
user.name string facultatif. Nom convivial complet de l’utilisateur à encoder dans le jeton.
trustedOrigins tableau de chaînes facultatif. Liste des domaines approuvés à incorporer dans le jeton. Ce sont les domaines qui peuvent héberger le client Web Chat du bot. Elle doit correspondre à la liste figurant dans la page de configuration Direct Line de votre bot.

Response

Si la demande réussit, la réponse contient un token valide pour une conversation, et une valeur expires_in qui indique le nombre de secondes avant l’expiration du jeton. Pour que le jeton reste utile, vous devez actualiser le jeton avant son expiration.

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

Générer un jeton ou démarrer une conversation

L’opération de génération de jeton (POST /v3/directline/tokens/generate) est similaire à l’opération de démarrage de conversation (POST /v3/directline/conversations) dans la mesure où les deux opérations retournent un token qui peut être utilisé pour accéder à une seule conversation. Toutefois, contrairement à l'opération de démarrage de conversation, l'opération de génération de jeton ne démarre pas la conversation, ne contacte pas le robot, et ne crée pas d'URL WebSocket de diffusion en continu.

Si vous envisagez de distribuer le jeton aux clients et souhaitez qu’ils initialisent la conversation, utilisez l’opération de génération de jeton. Si vous envisagez de démarrer la conversation immédiatement, utilisez plutôt l’opération de démarrage de conversation.

Actualiser un jeton Direct Line

Un jeton Direct Line peut être actualisé un nombre illimité de fois, tant qu'il n'a pas expiré. Un jeton expiré ne peut pas être actualisé. Pour actualiser un jeton Direct Line, émettez la demande suivante :

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

Dans l’en-tête Authorization de cette demande, remplacez TOKEN_TO_BE_REFRESHED par le jeton Direct Line à actualiser.

Les extraits de code suivants illustrent la demande et la réponse dans le cadre de l’actualisation du jeton.

Requête

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

Response

Si la demande réussit, la réponse contient un nouveau token valide pour la même conversation que le jeton précédent, et une valeur expires_in qui indique le nombre de secondes avant l’expiration du jeton. Pour que le nouveau jeton reste valide, vous devez l’actualiser avant son expiration.

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

Authentification par Azure AI Bot Service

Les informations présentées dans cette section sont en lien avec l'article Ajouter l'authentification à votre bot à partir d'Azure AI Bot Service.

L'authentification par Azure AI Bot Service vous permet d'authentifier les utilisateurs et d'obtenir des jetons d'accès de divers fournisseurs d'identité, comme Microsoft Entra ID, GitHub, Uber, etc. Vous pouvez également configurer l’authentification pour un fournisseur d’identité OAuth2 personnalisé. Tout cela vous permet d’écrire une partie de code d’authentification utilisable dans tous les fournisseurs d’identité et canaux pris en charge. Pour utiliser ces fonctionnalités :

  1. Configurez settings de manière statique sur votre bot qui contient les détails de l’inscription de votre application auprès d’un fournisseur d’identité.
  2. Utilisez un OAuthCard, basé sur les informations sur l’application que vous avez fournies à l’étape précédente, pour connecter un utilisateur.
  3. Récupérez les jetons d'accès par le biais de l'API Azure AI Bot Service.

Considérations de sécurité

Quand vous utilisez l'authentification Azure AI Bot Service avec Chat Web, gardez à l'esprit certaines considérations importantes en matière de sécurité.

  1. Emprunt d’identité. On parle d'usurpation d'identité lorsqu'un pirate utilise le bot en se faisant passer pour quelqu'un d'autre. Dans Chat Web, un pirate peut usurper l'identité de quelqu'un d'autre, en changeant l'identifiant utilisateur de l'instance Chat Web. Pour éviter l'usurpation d'identité, nous recommandons aux développeurs de bots de rendre l'identifiant de l'utilisateur indéchiffrable.

    Si vous activez les options d'authentification avancée, Azure AI Bot Service peut mieux détecter et rejeter les changements d'identifiant utilisateur. L’ID utilisateur (Activity.From.Id) sur les messages de Direct Line envoyés à votre bot sera donc toujours identique à celui avec lequel vous avez initialisé Web Chat. Cette fonction exige que l'identifiant utilisateur commence par dl_.

    Remarque

    Quand un User.Id est fourni lors de l’échange d’un secret avec un jeton, ce User.Id est incorporé dans le jeton. Direct Line vérifie que les messages envoyés au bot utilisent l'identifiant en tant que From.Id de l'activité. Si un client envoie un message à Direct Line ayant une autre From.Id, il est remplacé par l'identifiant du jeton avant de transférer le message au bot. Il n'est donc pas possible d'utiliser un autre identifiant utilisateur après l'initialisation d'un secret de chaîne avec un identifiant utilisateur.

  2. Identités utilisateur. Chaque utilisateur a plusieurs identité de l'utilisateur :

    1. L'identité de l'utilisateur dans un chaîne.
    2. L'identité de l'utilisateur auprès d'un fournisseur d'identité qui intéresse le bot.

Lorsqu'un bot demande à l'utilisateur A, dans une chaîne, de se connecter à un fournisseur d'identité P, le processus de connexion doit garantir que l'utilisateur A est celui qui se connecte à P. Si un autre utilisateur B est autorisé à se connecter, l'utilisateur A aura accès à la ressource de l'utilisateur B par l'intermédiaire du bot. Chat Web a deux mécanismes qui garantissent que l'utilisateur approprié est connecté comme décrit ci-après.

  1. Dans le passé, à la fin de la procédure de connexion, l'utilisateur recevait un code à 6 chiffres généré de manière aléatoire (code magique). L’utilisateur devait taper ce code dans la conversation à l’origine de la connexion pour terminer le processus de connexion. Ce mécanisme avait tendance à dégrader l’expérience utilisateur. De plus, il restait vulnérable aux attaques par hameçonnage. Un utilisateur malveillant pouvait inciter un autre utilisateur à se connecter et à obtenir le code magique par le biais d’un hameçonnage.

  2. En raison des problèmes rencontrés avec l'approche précédente, Azure AI Bot Service ne requiert plus l'utilisation du code magique. Azure AI Bot Service garantit que le processus de connexion ne peut être achevé que dans la même session de navigateur que le Chat Web lui-même. Pour activer cette protection, en tant que développeur de bot, vous devez démarrer Chat Web avec un jeton Direct Line qui contient une liste de domaines de confiance pouvant héberger le client Chat Web du bot. Auparavant, vous pouviez obtenir ce jeton uniquement en passant un paramètre facultatif non documenté à l’API de jeton Direct Line. Maintenant, grâce aux options d’authentification avancée, vous pouvez spécifier de façon statique la liste (d’origine) des domaines approuvés dans la page de configuration de Direct Line.

Pour plus d'informations, consultez la section Ajouter l'authentification à votre bot à partir d'Azure AI Bot Service.

Exemples de code

Le contrôleur .NET suivant utilise les options d’authentification avancée activées et retourne un jeton et un ID utilisateur Direct Line.

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; }
}

Le contrôleur JavaScript suivant utilise les options d’authentification avancée activées et retourne un jeton et un ID utilisateur Direct Line.

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');
        }
    });
});

Informations supplémentaires