microsoft-azure-webjobs-extensions-authentication-events-dotnet

SDK Microsoft Entra Authentication Events pour .NET. Déclencheurs Azure Functions pour les extensions d'authentification personnalisées. À utiliser pour l'enrichissement de token, les claims personnalisés, la collecte d'attributs et la personnalisation OTP dans Entra ID. Déclencheurs : « Authentication Events », « WebJobsAuthenticationEventsTrigger », « OnTokenIssuanceStart », « OnAttributeCollectionStart », « custom claims », « token enrichment », « Entra custom extension », « authentication extension ».

npx skills add https://github.com/microsoft/skills --skill microsoft-azure-webjobs-extensions-authentication-events-dotnet

Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents (.NET)

Extension Azure Functions pour gérer les événements d'authentification personnalisés de Microsoft Entra ID.

Installation

dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents

Version actuelle : v1.1.0 (stable)

Événements pris en charge

Événement Objectif
OnTokenIssuanceStart Ajouter des réclamations personnalisées aux jetons lors de l'émission
OnAttributeCollectionStart Personnaliser l'interface de collecte d'attributs avant affichage
OnAttributeCollectionSubmit Valider/modifier les attributs après soumission par l'utilisateur
OnOtpSend Livraison personnalisée du code OTP (SMS, email, etc.)

Workflows principaux

1. Enrichissement des jetons (Ajouter des réclamations personnalisées)

Ajouter des réclamations personnalisées aux jetons d'accès ou d'ID lors de la connexion.

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

public static class TokenEnrichmentFunction
{
    [FunctionName("OnTokenIssuanceStart")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
        ILogger log)
    {
        log.LogInformation("Token issuance event for user: {UserId}", 
            request.Data?.AuthenticationContext?.User?.Id);

        // Create response with custom claims
        var response = new WebJobsTokenIssuanceStartResponse();

        // Add claims to the token
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string, string>
            {
                { "customClaim1", "customValue1" },
                { "department", "Engineering" },
                { "costCenter", "CC-12345" },
                { "apiVersion", "v2" }
            }
        });

        return response;
    }
}

2. Enrichissement des jetons avec données externes

Récupérer des réclamations à partir de systèmes externes (bases de données, API).

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Text.Json;

public static class TokenEnrichmentWithExternalData
{
    private static readonly HttpClient _httpClient = new();

    [FunctionName("OnTokenIssuanceStartExternal")]
    public static async Task<WebJobsAuthenticationEventResponse> Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
        ILogger log)
    {
        string? userId = request.Data?.AuthenticationContext?.User?.Id;

        if (string.IsNullOrEmpty(userId))
        {
            log.LogWarning("No user ID in request");
            return new WebJobsTokenIssuanceStartResponse();
        }

        // Fetch user data from external API
        var userProfile = await GetUserProfileAsync(userId);

        var response = new WebJobsTokenIssuanceStartResponse();
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string, string>
            {
                { "employeeId", userProfile.EmployeeId },
                { "department", userProfile.Department },
                { "roles", string.Join(",", userProfile.Roles) }
            }
        });

        return response;
    }

    private static async Task<UserProfile> GetUserProfileAsync(string userId)
    {
        var response = await _httpClient.GetAsync($"https://api.example.com/users/{userId}");
        response.EnsureSuccessStatusCode();
        var json = await response.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<UserProfile>(json)!;
    }
}

public record UserProfile(string EmployeeId, string Department, string[] Roles);

3. Collecte d'attributs - Personnaliser l'interface (événement de démarrage)

Personnaliser la page de collecte d'attributs avant affichage.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class AttributeCollectionStartFunction
{
    [FunctionName("OnAttributeCollectionStart")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsAttributeCollectionStartRequest request,
        ILogger log)
    {
        log.LogInformation("Attribute collection start for correlation: {CorrelationId}",
            request.Data?.AuthenticationContext?.CorrelationId);

        var response = new WebJobsAttributeCollectionStartResponse();

        // Option 1: Continue with default behavior
        response.Actions.Add(new WebJobsContinueWithDefaultBehavior());

        // Option 2: Prefill attributes
        // response.Actions.Add(new WebJobsSetPrefillValues
        // {
        //     Attributes = new Dictionary<string, string>
        //     {
        //         { "city", "Seattle" },
        //         { "country", "USA" }
        //     }
        // });

        // Option 3: Show blocking page (prevent sign-up)
        // response.Actions.Add(new WebJobsShowBlockPage
        // {
        //     Message = "Sign-up is currently disabled."
        // });

        return response;
    }
}

4. Collecte d'attributs - Valider la soumission (événement de soumission)

Valider et modifier les attributs après soumission par l'utilisateur.

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class AttributeCollectionSubmitFunction
{
    [FunctionName("OnAttributeCollectionSubmit")]
    public static WebJobsAuthenticationEventResponse Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsAttributeCollectionSubmitRequest request,
        ILogger log)
    {
        var response = new WebJobsAttributeCollectionSubmitResponse();

        // Access submitted attributes
        var attributes = request.Data?.UserSignUpInfo?.Attributes;

        string? email = attributes?["email"]?.ToString();
        string? displayName = attributes?["displayName"]?.ToString();

        // Validation example: block certain email domains
        if (email?.EndsWith("@blocked.com") == true)
        {
            response.Actions.Add(new WebJobsShowBlockPage
            {
                Message = "Sign-up from this email domain is not allowed."
            });
            return response;
        }

        // Validation example: show validation error
        if (string.IsNullOrEmpty(displayName) || displayName.Length < 3)
        {
            response.Actions.Add(new WebJobsShowValidationError
            {
                Message = "Display name must be at least 3 characters.",
                AttributeErrors = new Dictionary<string, string>
                {
                    { "displayName", "Name is too short" }
                }
            });
            return response;
        }

        // Modify attributes before saving
        response.Actions.Add(new WebJobsModifyAttributeValues
        {
            Attributes = new Dictionary<string, string>
            {
                { "displayName", displayName.Trim() },
                { "city", attributes?["city"]?.ToString()?.ToUpperInvariant() ?? "" }
            }
        });

        return response;
    }
}

5. Livraison personnalisée du code OTP

Envoyer des mots de passe à usage unique via des canaux personnalisés (SMS, email, notification push).

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.Framework;
using Microsoft.Extensions.Logging;

public static class CustomOtpFunction
{
    [FunctionName("OnOtpSend")]
    public static async Task<WebJobsAuthenticationEventResponse> Run(
        [WebJobsAuthenticationEventsTrigger] WebJobsOnOtpSendRequest request,
        ILogger log)
    {
        var response = new WebJobsOnOtpSendResponse();

        string? phoneNumber = request.Data?.OtpContext?.Identifier;
        string? otp = request.Data?.OtpContext?.OneTimeCode;

        if (string.IsNullOrEmpty(phoneNumber) || string.IsNullOrEmpty(otp))
        {
            log.LogError("Missing phone number or OTP");
            response.Actions.Add(new WebJobsOnOtpSendFailed
            {
                Error = "Missing required data"
            });
            return response;
        }

        try
        {
            // Send OTP via your SMS provider
            await SendSmsAsync(phoneNumber, $"Your verification code is: {otp}");

            response.Actions.Add(new WebJobsOnOtpSendSuccess());
            log.LogInformation("OTP sent successfully to {PhoneNumber}", phoneNumber);
        }
        catch (Exception ex)
        {
            log.LogError(ex, "Failed to send OTP");
            response.Actions.Add(new WebJobsOnOtpSendFailed
            {
                Error = "Failed to send verification code"
            });
        }

        return response;
    }

    private static async Task SendSmsAsync(string phoneNumber, string message)
    {
        // Implement your SMS provider integration (Twilio, Azure Communication Services, etc.)
        await Task.CompletedTask;
    }
}

6. Configuration de la Function App

Configurer la Function App pour les événements d'authentification.

// Program.cs (Isolated worker model)
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .Build();

host.Run();
// host.json
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true
      }
    }
  },
  "extensions": {
    "http": {
      "routePrefix": ""
    }
  }
}
// local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}

Référence des types clés

Type Objectif
WebJobsAuthenticationEventsTriggerAttribute Attribut de déclenchement de fonction
WebJobsTokenIssuanceStartRequest Requête d'événement d'émission de jeton
WebJobsTokenIssuanceStartResponse Réponse d'événement d'émission de jeton
WebJobsProvideClaimsForToken Action pour ajouter des réclamations
WebJobsAttributeCollectionStartRequest Requête de démarrage de collecte d'attributs
WebJobsAttributeCollectionStartResponse Réponse de démarrage de collecte d'attributs
WebJobsAttributeCollectionSubmitRequest Requête de soumission d'attributs
WebJobsAttributeCollectionSubmitResponse Réponse de soumission d'attributs
WebJobsSetPrefillValues Préremplir les valeurs du formulaire
WebJobsShowBlockPage Bloquer l'utilisateur avec un message
WebJobsShowValidationError Afficher les erreurs de validation
WebJobsModifyAttributeValues Modifier les valeurs soumises
WebJobsOnOtpSendRequest Requête d'événement d'envoi OTP
WebJobsOnOtpSendResponse Réponse d'événement d'envoi OTP
WebJobsOnOtpSendSuccess OTP envoyé avec succès
WebJobsOnOtpSendFailed Échec de l'envoi du OTP
WebJobsContinueWithDefaultBehavior Continuer avec le flux par défaut

Configuration d'Entra ID

Après déploiement de votre Function App, configurez l'extension personnalisée dans Entra ID :

  1. Enregistrer l'API dans Entra ID → Inscriptions d'applications
  2. Créer une extension d'authentification personnalisée dans Entra ID → Identités externes → Extensions d'authentification personnalisées
  3. Lier au flux utilisateur dans Entra ID → Identités externes → Flux utilisateurs

Paramètres d'inscription d'application requis

Expose an API:
  - Application ID URI: api://<your-function-app-name>.azurewebsites.net
  - Scope: CustomAuthenticationExtension.Receive.Payload

API Permissions:
  - Microsoft Graph: User.Read (delegated)

Bonnes pratiques

  1. Valider tous les entrées — Ne jamais faire confiance aux données de requête ; valider avant traitement
  2. Gérer les erreurs correctement — Retourner les réponses d'erreur appropriées
  3. Journaliser les ID de corrélation — Utiliser CorrelationId pour le dépannage
  4. Garder les fonctions rapides — Les événements d'authentification ont des limites de délai d'expiration
  5. Utiliser une identité gérée — Accéder aux ressources Azure de manière sécurisée
  6. Mettre en cache les données externes — Éviter les recherches lentes à chaque requête
  7. Tester localement — Utiliser Azure Functions Core Tools avec des charges utiles d'exemple
  8. Surveiller avec App Insights — Suivre l'exécution des fonctions et les erreurs

Gestion des erreurs

[FunctionName("OnTokenIssuanceStart")]
public static WebJobsAuthenticationEventResponse Run(
    [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request,
    ILogger log)
{
    try
    {
        // Your logic here
        var response = new WebJobsTokenIssuanceStartResponse();
        response.Actions.Add(new WebJobsProvideClaimsForToken
        {
            Claims = new Dictionary<string, string> { { "claim", "value" } }
        });
        return response;
    }
    catch (Exception ex)
    {
        log.LogError(ex, "Error processing token issuance event");

        // Return empty response - authentication continues without custom claims
        // Do NOT throw - this would fail the authentication
        return new WebJobsTokenIssuanceStartResponse();
    }
}

SDKs associés

SDK Objectif Installation
Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents Événements d'authentification (ce SDK) dotnet add package Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
Microsoft.Identity.Web Authentification d'application web dotnet add package Microsoft.Identity.Web
Azure.Identity Authentification Azure dotnet add package Azure.Identity

Liens de référence

Ressource URL
Package NuGet https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents
Vue d'ensemble des extensions personnalisées https://learn.microsoft.com/entra/identity-platform/custom-extension-overview
Événements d'émission de jeton https://learn.microsoft.com/entra/identity-platform/custom-extension-tokenissuancestart-setup
Événements de collecte d'attributs https://learn.microsoft.com/entra/identity-platform/custom-extension-attribute-collection
Source GitHub https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/entra/Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents

Skills similaires