Partage via


Créer une API REST avec un événement de démarrage d’émission de jeton pour Azure Functions

Cet article explique comment créer une API REST avec un événement de démarrage d’émission de jeton à l’aide d’Azure Functions dans le Portail Azure. Vous créez une application de fonction Azure et une fonction de déclencheur HTTP, qui peut retourner des revendications supplémentaires pour votre jeton.

Prérequis

Cet article explique comment créer une API REST avec un événement de démarrage d’émission de jeton en utilisant la bibliothèque NuGet Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents et comment la configurer pour l’authentification. Vous allez créer une fonction de déclencheur HTTP dans Visual Studio ou Visual Studio Code, la configurer pour l’authentification, puis la déployer sur le portail Azure, où elle sera accessible via Azure Functions.

Prérequis

Remarque

La bibliothèque NuGet Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents est actuellement en préversion. Les étapes décrites dans cet article sont susceptibles de changer. Pour mettre en disponibilité générale l’implémentation d’un événement de démarrage d’émission de jeton, vous pouvez utiliser le portail Azure.

Créer une application de fonction Azure

Dans le Portail Azure, créez une application de fonction Azure et sa ressource associée, avant de continuer à créer la fonction de déclencheur HTTP.

  1. Connectez-vous au Portail Microsoft Azure en tant qu’administrateur(-trice) d’application et administrateur(-trice) d’authentification.

  2. Dans le menu du portail Azure ou dans la page Accueil, sélectionnez Créer une ressource.

  3. Recherchez et sélectionnez Application de fonction, puis sélectionnez Créer.

  4. Sur la page de base, créez une application de fonction en utilisant les paramètres spécifiés dans le tableau suivant :

    Paramètre Valeur suggérée Description
    Abonnement Votre abonnement Abonnement dans lequel la nouvelle application de fonction sera créée.
    Groupe de ressources myResourceGroup Sélectionnez le groupe de ressources existant ou le nom du nouveau dans lequel vous allez créer votre application de fonction.
    Nom de l’application de fonction Nom globalement unique Nom qui identifie la nouvelle application de fonction. Les caractères valides sont a-z (insensible à la casse), 0-9et -.
    Déployer du code ou une image conteneur Code Option permettant de publier des fichiers de code ou un conteneur Docker. Pour les besoins de ce didacticiel, sélectionnez Code.
    Pile d’exécution .NET Votre langage de programmation préféré. Pour les besoins de ce didacticiel, sélectionnez .NET.
    Version 6 (LTS) in-process Version du runtime .NET. In-process signifie que vous pouvez créer et modifier des fonctions dans le portail, ce qui est recommandé pour ce guide
    Région Région recommandée Sélectionnez une région proche de chez vous, ou proche d’autres services auxquels vos fonctions peuvent accéder.
    Système d’exploitation Windows Le système d’exploitation est présélectionné pour vous en fonction de la pile d’exécution que vous avez sélectionnée.
    Type de plan Consommation (serverless) Plan d’hébergement qui définit la façon dont les ressources sont allouées à votre Function App.
  5. Sélectionnez Vérifier + créer pour passer en revue les sélections de configuration d’application, puis sélectionnez Créer. Le déploiement prend quelques minutes.

  6. Une fois le déploiement effectué, sélectionnez Accéder à la ressource pour voir votre nouvelle application de fonction.

Créer une fonction de déclencheur HTTP

Une fois l’application de fonction Azure créée, créez une fonction de déclencheur HTTP dans l’application. Le déclencheur HTTP vous permet d’appeler une fonction avec une requête HTTP et est référencé par l’extension d’authentification personnalisée Microsoft Entra.

  1. Dans la page Vue d’ensemble de votre application de fonction, sélectionnez le volet Fonctions , puis sélectionnez Créer une fonction sous Créer dans le Portail Microsoft Azure.
  2. Dans la fenêtre Créer une fonction, laissez la propriété Environnement de développement définie sur Développer dans le portail. Sous Modèle, sélectionnez Déclencheur HTTP.
  3. Sous Détails du modèle, entrez CustomAuthenticationExtensionsAPI comme propriété Nouvelle fonction.
  4. Pour le niveau d’autorisation, sélectionnez Fonction.
  5. Sélectionnez Créer. Capture d’écran montrant comment choisir l’environnement de développement et le modèle.

Modifier la fonction

Le code lit l’objet JSON entrant et Microsoft Entra ID envoie l’objet JSON à votre API. Dans cet exemple, il lit la valeur de l’ID de corrélation. Ensuite, le code renvoie une collection de demandes personnalisées, y compris l’ CorrelationId original, le ApiVersion de votre fonction Azure, un DateOfBirth et CustomRoles qui est renvoyé à Microsoft Entra ID.

  1. À partir du menu, sous Développeur, sélectionnez Coder + tester.

  2. Remplacez l’ensemble du code par l’extrait suivant, puis sélectionnez Enregistrer.

    #r "Newtonsoft.Json"
    using System.Net;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Newtonsoft.Json;
    public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
    
        // Read the correlation ID from the Microsoft Entra request    
        string correlationId = data?.data.authenticationContext.correlationId;
    
        // Claims to return to Microsoft Entra
        ResponseContent r = new ResponseContent();
        r.data.actions[0].claims.CorrelationId = correlationId;
        r.data.actions[0].claims.ApiVersion = "1.0.0";
        r.data.actions[0].claims.DateOfBirth = "01/01/2000";
        r.data.actions[0].claims.CustomRoles.Add("Writer");
        r.data.actions[0].claims.CustomRoles.Add("Editor");
        return new OkObjectResult(r);
    }
    public class ResponseContent{
        [JsonProperty("data")]
        public Data data { get; set; }
        public ResponseContent()
        {
            data = new Data();
        }
    }
    public class Data{
        [JsonProperty("@odata.type")]
        public string odatatype { get; set; }
        public List<Action> actions { get; set; }
        public Data()
        {
            odatatype = "microsoft.graph.onTokenIssuanceStartResponseData";
            actions = new List<Action>();
            actions.Add(new Action());
        }
    }
    public class Action{
        [JsonProperty("@odata.type")]
        public string odatatype { get; set; }
        public Claims claims { get; set; }
        public Action()
        {
            odatatype = "microsoft.graph.tokenIssuanceStart.provideClaimsForToken";
            claims = new Claims();
        }
    }
    public class Claims{
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string CorrelationId { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string DateOfBirth { get; set; }
        public string ApiVersion { get; set; }
        public List<string> CustomRoles { get; set; }
        public Claims()
        {
            CustomRoles = new List<string>();
        }
    }
    
  3. Dans le menu supérieur, sélectionnez Obtenir l’URL de fonction, puis copiez la valeur de l’URL. Cette URL de fonction peut être utilisée lors de la configuration d’une extension d’authentification personnalisée.

Créer et générer l’application de fonction Azure

Dans cette étape, vous créez une API de fonction de déclencheur HTTP en utilisant votre IDE, vous installez les packages NuGet requis et vous copiez dans l’exemple de code. Vous générez le projet et vous exécutez la fonction pour extraire l’URL de la fonction locale.

Création de l'application

Pour créer une fonction Azure, procédez comme suit :

  1. Ouvrez Visual Studio et sélectionnez Créer un projet.
  2. Recherchez et sélectionnez Azure Functions, puis sélectionnez Suivant.
  3. Attribuez un nom au projet, par exemple AuthEventsTrigger. Il est judicieux de faire correspondre le nom de la solution au nom du projet.
  4. Sélectionnez un emplacement pour le projet. Cliquez sur Suivant.
  5. Sélectionnez .NET 6.0 (prise en charge à long terme) comme version cible de .Net Framework.
  6. Sélectionnez Déclencheur HTTP comme type de Fonction, et vérifiez que Niveau d’autorisation est défini sur Fonction. Sélectionnez Créer.
  7. Dans l’Explorateur de solutions, renommez le fichier Function1.cs en AuthEventsTrigger.cs, puis acceptez la suggestion de changement de nom.

Installer des packages NuGet et générer le projet

Après avoir créé le projet, vous devez installer les packages NuGet requis et générer le projet.

  1. Dans le menu supérieur de Visual Studio, sélectionnez Projet, puis Gérer les packages NuGet.
  2. Sélectionnez l’onglet Parcourir, puis recherchez et sélectionnez Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents dans le volet droit. Sélectionnez Installer.
  3. Appliquez et acceptez les modifications apportées aux fenêtres contextuelles qui s’affichent.

Ajouter l’exemple de code

L’API de fonction est la source de revendications supplémentaires pour votre jeton. Pour les besoins de cet article, nous décodons en dur les valeurs de l’exemple d’application. En production, vous pouvez récupérer (fetch) des informations sur l’utilisateur auprès d’un magasin de données externe.

Dans votre fichier AuthEventsTrigger.cs, remplacez tout le contenu du fichier par le code suivant :

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;

namespace AuthEventsTrigger
{
    public static class AuthEventsTrigger
    {
        [FunctionName("onTokenIssuanceStart")]
        public static WebJobsAuthenticationEventResponse Run(
            [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request, ILogger log)
        {
            try
            {
                // Checks if the request is successful and did the token validation pass
                if (request.RequestStatus == WebJobsAuthenticationEventsRequestStatusType.Successful)
                {
                    // Fetches information about the user from external data store
                    // Add new claims to the token's response
                    request.Response.Actions.Add(
                        new WebJobsProvideClaimsForToken(
                            new WebJobsAuthenticationEventsTokenClaim("dateOfBirth", "01/01/2000"),
                            new WebJobsAuthenticationEventsTokenClaim("customRoles", "Writer", "Editor"),
                            new WebJobsAuthenticationEventsTokenClaim("apiVersion", "1.0.0"),
                            new WebJobsAuthenticationEventsTokenClaim(
                                "correlationId", 
                                request.Data.AuthenticationContext.CorrelationId.ToString())));
                }
                else
                {
                    // If the request fails, such as in token validation, output the failed request status, 
                    // such as in token validation or response validation.
                    log.LogInformation(request.StatusMessage);
                }
                return request.Completed();
            }
            catch (Exception ex) 
            { 
                return request.Failed(ex);
            }
        }
    }
}

Générer et exécuter le projet localement

Le projet a été créé et l’exemple de code a été ajouté. En utilisant votre IDE, nous devons générer et exécuter le projet localement pour extraire l’URL de la fonction locale.

  1. Accédez à Générer dans le menu supérieur, puis sélectionnez Générer la solution.
  2. Appuyez sur la touche F5 ou sélectionnez AuthEventsTrigger dans le menu supérieur pour exécuter la fonction.
  3. Copiez l’URL de la fonction à partir du terminal qui s’affiche lors de l’exécution de la fonction. Elle peut être utilisée lors de la configuration d’une extension d’authentification personnalisée.

Il est judicieux de tester la fonction localement avant de la déployer sur Azure. Nous pouvons utiliser un corps JSON factice qui imite la requête que Microsoft Entra ID envoie à votre API REST. Utilisez votre outil de test d’API préféré pour appeler la fonction directement.

  1. Dans votre IDE, ouvrez local.settings.json et remplacez le code par le JSON suivant. Nous pouvons définir "AuthenticationEvents__BypassTokenValidation" sur true à des fins de test locaux.

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "",
        "AzureWebJobsSecretStorageType": "files",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "AuthenticationEvents__BypassTokenValidation" : true
      }
    }
    
  2. En utilisant votre outil de test d’API préféré, créez une requête HTTP et définissez la méthode HTTP sur POST.

  3. Utilisez le corps JSON suivant, qui imite la requête envoyée par Microsoft Entra ID à votre API REST.

    {
        "type": "microsoft.graph.authenticationEvent.tokenIssuanceStart",
        "source": "/tenants/aaaabbbb-0000-cccc-1111-dddd2222eeee/applications/00001111-aaaa-2222-bbbb-3333cccc4444",
        "data": {
            "@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData",
            "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
            "authenticationEventListenerId": "11112222-bbbb-3333-cccc-4444dddd5555",
            "customAuthenticationExtensionId": "22223333-cccc-4444-dddd-5555eeee6666",
            "authenticationContext": {
                "correlationId": "aaaa0000-bb11-2222-33cc-444444dddddd",
                "client": {
                    "ip": "127.0.0.1",
                    "locale": "en-us",
                    "market": "en-us"
                },
                "protocol": "OAUTH2.0",
                "clientServicePrincipal": {
                    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
                    "appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
                    "appDisplayName": "My Test application",
                    "displayName": "My Test application"
                },
                "resourceServicePrincipal": {
                    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
                    "appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
                    "appDisplayName": "My Test application",
                    "displayName": "My Test application"
                },
                "user": {
                    "companyName": "Casey Jensen",
                    "createdDateTime": "2023-08-16T00:00:00Z",
                    "displayName": "Casey Jensen",
                    "givenName": "Casey",
                    "id": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
                    "mail": "casey@contoso.com",
                    "onPremisesSamAccountName": "Casey Jensen",
                    "onPremisesSecurityIdentifier": "<Enter Security Identifier>",
                    "onPremisesUserPrincipalName": "Casey Jensen",
                    "preferredLanguage": "en-us",
                    "surname": "Jensen",
                    "userPrincipalName": "casey@contoso.com",
                    "userType": "Member"
                }
            }
        }
    }
    
    
  4. Sélectionnez Send (Envoyer), et vous devez recevoir une réponse JSON similaire à ce qui suit :

    {
        "data": {
            "@odata.type": "microsoft.graph.onTokenIssuanceStartResponseData",
            "actions": [
                {
                    "@odata.type": "microsoft.graph.tokenIssuanceStart.provideClaimsForToken",
                    "claims": {
                        "customClaim1": "customClaimValue1",
                        "customClaim2": [
                            "customClaimString1",
                            "customClaimString2" 
                        ]
                    }
                }
    
            ]
        }
    }
    

Déployer la fonction et la publier sur Azure

La fonction doit être déployée sur Azure à l’aide de notre IDE (environnement de développement intégré). Vérifiez que vous êtes bien connecté à votre compte Azure afin que la fonction puisse être publiée.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet, puis sélectionnez Publier.

  2. Dans Cible, sélectionnez Azure puis Suivant.

  3. Dans Cible spécifique, sélectionnez Application de fonction Azure (Windows), puis sélectionnez Application de fonction Azure (Windows) et Suivant.

  4. Dans Instance de fonction, accédez à la liste déroulante Nom de l’abonnement pour sélectionner l’abonnement dans lequel l’application de fonction sera créée.

  5. Sélectionnez l’emplacement où vous souhaitez publier la nouvelle application de fonction, puis sélectionnez Créer.

  6. Dans la page Application de fonction (Windows), utilisez les paramètres d’application de fonction comme indiqué dans le tableau ci-dessous, puis sélectionnez Créer.

    Paramètre Valeur suggérée Description
    Nom Nom globalement unique Nom qui identifie la nouvelle application de fonction. Les caractères valides sont a-z (insensible à la casse), 0-9et -.
    Abonnement Votre abonnement Abonnement dans lequel est créée cette application de fonction.
    Groupe de ressources myResourceGroup Sélectionnez un groupe de ressources existant ou attribuez un nom au nouveau groupe dans lequel vous allez créer votre application de fonction.
    Type de plan Consommation (serverless) Plan d’hébergement qui définit la façon dont les ressources sont allouées à votre Function App.
    Lieu Région recommandée Sélectionnez une région proche de chez vous, ou proche d’autres services auxquels vos fonctions peuvent accéder.
    Stockage Azure Votre compte de stockage Un compte de stockage Azure est obligatoire par le runtime Functions. Sélectionnez Nouveau pour configurer un compte de stockage universel.
    Application Insights Par défaut Fonctionnalité d’Azure Monitor. Cette option est sélectionnée automatiquement. Sélectionnez celle que vous souhaitez utiliser ou configurez-en une nouvelle.
  7. Patientez quelques instants pendant que votre application de fonction est déployée. Une fois la fenêtre fermée, sélectionnez Terminer.

  8. Un nouveau volet Publier s’ouvre. En haut, sélectionnez Publier. Patientez quelques minutes pendant que votre application de fonction est déployée et publiée dans le Portail Azure.

Configurer l’authentification pour votre fonction Azure

Il existe trois façons de configurer l’authentification pour votre fonction Azure :

Par défaut, le code a été configuré pour l’authentification dans le portail Azure en utilisant des variables d’environnement. Utilisez les onglets ci-dessous pour sélectionner votre méthode préférée pour l’implémentation de variables d’environnement ; vous pouvez aussi vous reporter à l’authentification et l’autorisation Azure App Service intégrées. Pour configurer des variables d’environnement, utilisez les valeurs suivantes :

Nom Valeur
AuthenticationEvents__AudienceAppId ID d’application d’extension d’authentification personnalisée, qui est configuré dans Configurer un fournisseur de revendications personnalisées pour un événement d’émission de jeton
AuthenticationEvents__AuthorityUrl • Locataire de main-d’œuvre https://login.microsoftonline.com/<tenantID>
• Locataire externe https://<mydomain>.ciamlogin.com/<tenantID>
AuthenticationEvents__AuthorizedPartyAppId 99045fe1-7639-4a75-9d4a-577b6ca3810f ou un autre tiers autorisé

Configurer l’authentification dans le portail Azure en utilisant des variables d’environnement

  1. Connectez-vous au Portail Azure au minimum en tant qu’administrateur d’application ou administrateur d’authentification.
  2. Accédez à l’application de fonction que vous avez créée, puis, sous Paramètres, sélectionnez Configuration.
  3. Sous Paramètres d’application, sélectionnez Nouveau paramètre d’application, puis ajoutez les variables d’environnement du tableau et leurs valeurs associées.
  4. Sélectionnez Enregistrer pour enregistrer les paramètres de l’application.

Étape suivante