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 :
- Enregistrer l'API dans Entra ID → Inscriptions d'applications
- Créer une extension d'authentification personnalisée dans Entra ID → Identités externes → Extensions d'authentification personnalisées
- 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
- Valider tous les entrées — Ne jamais faire confiance aux données de requête ; valider avant traitement
- Gérer les erreurs correctement — Retourner les réponses d'erreur appropriées
- Journaliser les ID de corrélation — Utiliser
CorrelationIdpour le dépannage - Garder les fonctions rapides — Les événements d'authentification ont des limites de délai d'expiration
- Utiliser une identité gérée — Accéder aux ressources Azure de manière sécurisée
- Mettre en cache les données externes — Éviter les recherches lentes à chaque requête
- Tester localement — Utiliser Azure Functions Core Tools avec des charges utiles d'exemple
- 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 |