Configurez la journalisation dans Microsoft. Identity.Web

Microsoft. Identity.Web s'intègre à l'infrastructure de journalisation de ASP.NET Core. Utilisez-le pour diagnostiquer les problèmes :

  • Flux d’authentification - Connexion, déconnexion, validation des jetons
  • Acquisition de jetons - Accès/échecs du cache de jetons, opérations MSAL
  • Appels d’API en aval - Requêtes HTTP, acquisition de jetons pour les API
  • Conditions d’erreur - Exceptions, échecs de validation

Comprendre les composants journalisés

Composant Source de log Objectif
Microsoft. Identity.Web Logique d’authentification principale Configuration, acquisition de jetons, appels d’API
MSAL.NET Microsoft.Identity.Client Opérations de cache de jetons, validation d’autorité
Modèle d’identité Validation du jeton Analyse JWT, validation de signature, extraction de revendications
ASP.NET Core Auth Microsoft.AspNetCore.Authentication Opérations de cookie, actions de défi/interdiction

Commencez avec la journalisation

Configuration minimale

Ajoutez les entrées du niveau de journal suivantes à appsettings.json pour activer la journalisation des identités :

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.Identity": "Information"
    }
  }
}

Cela permet la journalisation au niveau d'information pour Microsoft.Identity.Web et ses dépendances (MSAL.NET, IdentityModel).

Configuration du développement

Pour obtenir des diagnostics détaillés pendant le développement :

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Identity": "Debug",
      "Microsoft.AspNetCore.Authentication": "Information"
    }
  },
  "AzureAd": {
    "EnablePiiLogging": true  // Development only!
  }
}

Configuration de production

Pour la production, réduisez le volume des journaux tout en enregistrant les erreurs :

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning",
      "Microsoft": "Warning",
      "Microsoft.Identity": "Warning"
    }
  },
  "AzureAd": {
    "EnablePiiLogging": false  // Never true in production
  }
}

Configurer le filtrage des journaux

Filtrage basé sur un espace de noms

Régler la verbosité des journaux par espace de noms. La configuration suivante définit des niveaux granulaires pour chaque espace de noms lié à l’identité :

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",

      // General Microsoft namespaces
      "Microsoft": "Warning",
      "Microsoft.AspNetCore": "Warning",

      // Identity-specific namespaces
      "Microsoft.Identity": "Information",
      "Microsoft.Identity.Web": "Information",
      "Microsoft.Identity.Client": "Information",

      // ASP.NET Core authentication
      "Microsoft.AspNetCore.Authentication": "Information",
      "Microsoft.AspNetCore.Authentication.JwtBearer": "Information",
      "Microsoft.AspNetCore.Authentication.OpenIdConnect": "Debug",

      // Token validation
      "Microsoft.IdentityModel": "Warning"
    }
  }
}

Désactiver la journalisation spécifique

Pour faire taire les composants bruyants sans affecter les autres, définissez leur niveau de journalisation sur None ou Warning:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.Identity.Web": "None",  // Completely disable
      "Microsoft.Identity.Client": "Warning"  // Only errors/warnings
    }
  }
}

Configuration spécifique à l’environnement

Utiliser appsettings.{Environment}.json pour les paramètres par environnement :

appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity": "Debug"
    }
  },
  "AzureAd": {
    "EnablePiiLogging": true
  }
}

appsettings.Production.json:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity": "Warning"
    }
  },
  "AzureAd": {
    "EnablePiiLogging": false
  }
}

Comprendre les niveaux de journalisation

ASP.NET Core définit les niveaux de journal suivants. Choisissez le niveau qui équilibre les détails de diagnostic par rapport au volume de journal pour votre environnement.

ASP.NET Core niveaux de journalisation

Niveau Utilisation Volume Production?
Trace La plus détaillée, chaque opération Très élevé Non
Déboguer Flux détaillé, utile pour le développement Élevé Non
Information Flux général, événements clés Modéré Sélective
Avertissement Conditions inattendues mais gérées Low Oui
Error Erreurs et exceptions Très faible Oui
Critique Échecs irrécupérables Très faible Oui
Aucun Désactiver la journalisation Aucun Sélective

Mapper MSAL.NET aux niveaux de ASP.NET Core

niveau MSAL.NET équivalent ASP.NET Core Description
Verbose Debug ou Trace Messages les plus détaillés
Info Information Événements d’authentification de clé
Warning Warning Conditions anormales mais gérées
Error Error ou Critical Erreurs et exceptions

Utilisez les configurations suivantes par environnement.

Développement:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity": "Debug",
      "Microsoft.Identity.Client": "Information"
    }
  }
}

Staging:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity": "Information",
      "Microsoft.Identity.Client": "Warning"
    }
  }
}

Production:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity": "Warning",
      "Microsoft.Identity.Client": "Error"
    }
  }
}

Configurer la journalisation des informations personnelles

Par défaut, Microsoft. Identity.Web réacte les informations d’identification personnelle (PII) à partir des journaux. Activez la journalisation des informations personnelles uniquement dans les environnements de développement pour afficher les détails complets de l’utilisateur.

Qu’est-ce que l’IPI ?

Les informations d’identification personnelle (PII) incluent :

  • Noms d’utilisateur, adresses e-mail
  • Noms d’affichage
  • ID d’objet, ID de locataire
  • Adresses IP
  • Valeurs de jeton, revendications

Avertissement de sécurité

AVERTISSEMENT : Vous et votre application êtes responsable de la conformité à toutes les exigences réglementaires applicables, y compris celles définies par le RGPD. Avant d’activer la journalisation des informations personnelles, assurez-vous que vous pouvez gérer en toute sécurité ces données potentiellement hautement sensibles.

Activer la journalisation des informations personnelles (développement uniquement)

Définissez EnablePiiLogging sur true dans le fichier de configuration de développement :

appsettings.Development.json:

{
  "AzureAd": {
    "EnablePiiLogging": true  //  Development/Testing ONLY
  },
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity": "Debug"
    }
  }
}

Contrôler la journalisation des informations personnelles par programmation

Activez la journalisation des informations personnelles en fonction de l’environnement d’hébergement :

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<MicrosoftIdentityOptions>(options =>
{
    // Only enable PII in Development
    options.EnablePiiLogging = builder.Environment.IsDevelopment();
});

Quelles modifications avec l’authentification personnelle activée ?

Sans journalisation des informations personnelles :

[Information] Token validation succeeded for user '{hidden}'
[Information] Acquired token from cache for scopes '{hidden}'

Une fois les informations d’identification personnelle activées :

[Information] Token validation succeeded for user 'john.doe@contoso.com'
[Information] Acquired token from cache for scopes 'user.read api://my-api/.default'

Rédaction des informations personnelles dans les logs

Lorsque la journalisation des informations personnelles est désactivée, les données sensibles sont remplacées par :

  • {hidden} - Masque les identificateurs d’utilisateur
  • {hash:XXXX} - Affiche le hachage au lieu de la valeur réelle
  • *** - Masque les jetons

Utiliser des ID de corrélation

Les ID de corrélation tracent les demandes d’authentification à travers les services. Incluez-les dans les journaux de bord et les demandes d'assistance pour accélérer la résolution des problèmes.

Qu’est-ce que les ID de corrélation ?

Un ID de corrélation est un GUID qui identifie de manière unique une demande d’acquisition d’authentification ou de jeton entre :

  • Votre application.
  • plateforme Microsoft Identity
  • bibliothèque MSAL.NET
  • services backend de Microsoft

Obtenir des ID de corrélation

Méthode 1 : à partir d’AuthenticationResult

Extrayez l'ID de corrélation de AuthenticationResult après une acquisition de jeton réussie :

using Microsoft.Identity.Web;

public class TodoController : ControllerBase
{
    private readonly ITokenAcquisition _tokenAcquisition;
    private readonly ILogger<TodoController> _logger;

    public TodoController(
        ITokenAcquisition tokenAcquisition,
        ILogger<TodoController> logger)
    {
        _tokenAcquisition = tokenAcquisition;
        _logger = logger;
    }

    [HttpGet]
    public async Task<IActionResult> GetTodos()
    {
        var result = await _tokenAcquisition.GetAuthenticationResultForUserAsync(
            new[] { "user.read" });

        _logger.LogInformation(
            "Token acquired. CorrelationId: {CorrelationId}, Source: {TokenSource}",
            result.CorrelationId,
            result.AuthenticationResultMetadata.TokenSource);

        return Ok(result.CorrelationId);
    }
}

Méthode 2 : à partir de MsalServiceException

Capturez l'ID de corrélation lorsque l'acquisition de jeton MsalServiceException échoue.

using Microsoft.Identity.Client;

try
{
    var token = await _tokenAcquisition.GetAccessTokenForUserAsync(
        new[] { "user.read" });
}
catch (MsalServiceException ex)
{
    _logger.LogError(ex,
        "Token acquisition failed. CorrelationId: {CorrelationId}, ErrorCode: {ErrorCode}",
        ex.CorrelationId,
        ex.ErrorCode);

    // Return correlation ID to user for support
    return StatusCode(500, new {
        error = "authentication_failed",
        correlationId = ex.CorrelationId
    });
}

Méthode 3 : Définir un ID de corrélation personnalisé

Attribuez un ID de corrélation personnalisé pour lier des traces d’application avec des requêtes Microsoft Entra ID :

[HttpGet("{id}")]
public async Task<IActionResult> GetTodo(int id)
{
    // Use request trace ID as correlation ID
    var correlationId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

    var todo = await _downstreamApi.GetForUserAsync<Todo>(
        "TodoListService",
        options =>
        {
            options.RelativePath = $"api/todolist/{id}";
            options.TokenAcquisitionOptions = new TokenAcquisitionOptions
            {
                CorrelationId = Guid.Parse(correlationId)
            };
        });

    _logger.LogInformation(
        "Called downstream API. TraceId: {TraceId}, CorrelationId: {CorrelationId}",
        HttpContext.TraceIdentifier,
        correlationId);

    return Ok(todo);
}

Fournir des ID de corrélation pour la prise en charge

Lorsque vous contactez Microsoft support technique, fournissez les détails suivants :

  1. ID de corrélation - À partir des journaux ou des exceptions
  2. Horodatage - Lorsque l’erreur s’est produite (UTC)
  3. ID de locataire - Votre locataire Microsoft Entra ID
  4. Code d’erreur : le cas échéant (par exemple, AADSTS50058)

Exemple de demande de support :

Subject: Token acquisition failing for user.read scope

Correlation ID: 12345678-1234-1234-1234-123456789012
Timestamp: 2025-01-15 14:32:45 UTC
Tenant ID: contoso.onmicrosoft.com
Error Code: AADSTS50058

Activer la journalisation du cache de jetons

La journalisation du cache de jetons vous aide à comprendre le comportement de réussite/échec du cache et à diagnostiquer les problèmes de performance avec les caches distribués.

Activer les diagnostics du cache de jetons

Pour les applications .NET Framework ou .NET Core à l’aide de caches de jetons distribués, configurez la journalisation détaillée :

using Microsoft.Extensions.Logging;
using Microsoft.Identity.Web.TokenCacheProviders;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDistributedTokenCaches();

// Enable detailed token cache logging
builder.Services.AddLogging(configure =>
{
    configure.AddConsole();
    configure.AddDebug();
})
.Configure<LoggerFilterOptions>(options =>
{
    options.MinLevel = LogLevel.Debug;  // Detailed cache operations
});

Exemples de journal du cache de jetons

Accès au cache :

[Debug] Token cache: Token found in cache for scopes 'user.read'
[Information] Token source: Cache

Manque de cache :

[Debug] Token cache: No token found in cache for scopes 'user.read'
[Information] Token source: IdentityProvider
[Debug] Token cache: Token stored in cache

Résoudre les problèmes liés aux caches distribués

Activez la journalisation spécifique au fournisseur pour diagnostiquer les problèmes de connectivité et de performances du cache.

Cache Redis :

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration["Redis:ConnectionString"];
});

// Enable Redis logging
builder.Services.AddLogging(configure =>
{
    configure.AddFilter("Microsoft.Extensions.Caching", LogLevel.Debug);
});

cache SQL Server cache :

Configurez SQL Server cache distribué avec la journalisation :

builder.Services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = builder.Configuration["SqlCache:ConnectionString"];
    options.SchemaName = "dbo";
    options.TableName = "TokenCache";
});

// Enable SQL cache logging
builder.Services.AddLogging(configure =>
{
    configure.AddFilter("Microsoft.Extensions.Caching.SqlServer", LogLevel.Information);
});

Résoudre les problèmes courants

Utilisez les scénarios suivants pour diagnostiquer les problèmes d’authentification et d’autorisation fréquents.

Scénarios de journalisation courants

Scénario 1 : Échecs de validation des jetons

Symptôme : 401 Réponses non autorisées

Activez la journalisation détaillée :

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Authentication.JwtBearer": "Debug",
      "Microsoft.IdentityModel": "Information"
    }
  }
}

Rechercher :

[Information] Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:
  Failed to validate the token.
[Debug] Microsoft.IdentityModel.Tokens: IDX10230: Lifetime validation failed.
  The token is expired.

Scénario 2 : Échecs d’acquisition de jetons

Symptôme:MsalServiceException Ou MsalUiRequiredException

Activez la journalisation détaillée :

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity.Web": "Debug",
      "Microsoft.Identity.Client": "Information"
    }
  }
}

Rechercher :

[Error] Microsoft.Identity.Web: Token acquisition failed.
  ErrorCode: invalid_grant, CorrelationId: {guid}
[Information] Microsoft.Identity.Client: MSAL returned exception:
  AADSTS50058: Silent sign-in failed.

Scénario 3 : Échecs d’appel d’API en aval

Symptôme: Erreurs HTTP 502 ou de délai d’attente appelant des API en aval

Activez la journalisation détaillée :

{
  "Logging": {
    "LogLevel": {
      "Microsoft.Identity.Abstractions": "Debug",
      "System.Net.Http": "Information"
    }
  }
}

Ajoutez une journalisation personnalisée dans votre contrôleur pour capturer les erreurs d’API en aval :

[HttpGet]
public async Task<IActionResult> GetUserProfile()
{
    try
    {
        _logger.LogInformation("Acquiring token for Microsoft Graph");

        var user = await _downstreamApi.GetForUserAsync<User>(
            "MicrosoftGraph",
            options => options.RelativePath = "me");

        _logger.LogInformation(
            "Successfully retrieved user profile for {UserPrincipalName}",
            user.UserPrincipalName);

        return Ok(user);
    }
    catch (MsalUiRequiredException ex)
    {
        _logger.LogWarning(ex,
            "User interaction required. CorrelationId: {CorrelationId}",
            ex.CorrelationId);
        return Challenge();
    }
    catch (HttpRequestException ex)
    {
        _logger.LogError(ex, "Failed to call Microsoft Graph API");
        return StatusCode(502, "Downstream API error");
    }
}

Interpréter les modèles de journal

Les exemples suivants montrent une sortie de journal classique pour les événements d’authentification courants.

Flux d’authentification réussi :

[Info] Authentication scheme OpenIdConnect: Authorization response received
[Debug] Correlation id: {guid}
[Info] Authorization code received
[Info] Token validated successfully
[Info] Authentication succeeded for user: {user}

Consentement requis :

[Warning] Microsoft.Identity.Web: Incremental consent required
[Info] AADSTS65001: User consent is required for scopes: {scopes}
[Info] Redirecting to consent page

Actualisation du jeton :

[Debug] Token expired, attempting silent token refresh
[Info] Token source: IdentityProvider
[Info] Token refreshed successfully

Agréger des journaux de logs avec des fournisseurs externes

Transférez les journaux d’identité vers une plateforme de journalisation centralisée pour la surveillance et les alertes.

Intégration d’Application Insights :

Envoyer des données de télémétrie d’identité à Application Insights avec enrichissement d’ID de corrélation :

using Microsoft.ApplicationInsights.Extensibility;

builder.Services.AddApplicationInsightsTelemetry();

// Enrich telemetry with correlation IDs
builder.Services.AddSingleton<ITelemetryInitializer, CorrelationIdTelemetryInitializer>();

Intégration de Serilog :

Configurez Serilog pour capturer les journaux d’identité dans les sorties sur console et fichier rotatif :

using Serilog;

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft.Identity", Serilog.Events.LogEventLevel.Debug)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("logs/identity-.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Host.UseSerilog();

Suivez les bonnes pratiques de journalisation

Appliquez ces pratiques pour sécuriser vos journaux d’identité, les rendre utiles et performants.

Choses à faire

1. Utilisez la journalisation structurée :

Transmettez des valeurs en tant que paramètres nommés afin que les agrégateurs de journaux puissent les indexer et les interroger :

_logger.LogInformation(
    "Token acquired for user {UserId} with scopes {Scopes}",
    userId, string.Join(" ", scopes));

2. ID de corrélation de journal :

Incluez toujours l’ID de corrélation dans les journaux d’erreurs pour simplifier les enquêtes de support :

_logger.LogError(ex,
    "Operation failed. CorrelationId: {CorrelationId}",
    ex.CorrelationId);

3. Utilisez les niveaux de journal appropriés :

Faire correspondre le niveau de journalisation à la gravité et au public :

_logger.LogDebug("Detailed diagnostic info");      // Development
_logger.LogInformation("Key application events");  // Selective production
_logger.LogWarning("Unexpected but handled");      // Production
_logger.LogError(ex, "Operation failed");          // Production

4. Assainir les journaux en production :

Masquez les valeurs sensibles avant de les écrire dans les journaux de production :

var sanitizedEmail = environment.IsProduction()
    ? MaskEmail(email)
    : email;
_logger.LogInformation("Processing request for {Email}", sanitizedEmail);

Choses à ne pas faire

1. N’activez pas les informations d’identification personnelle en production :

//  Wrong
"EnablePiiLogging": true  // In production config!

//  Correct
"EnablePiiLogging": false

2. Ne consignez pas les secrets :

//  Wrong
_logger.LogInformation("Token: {Token}", accessToken);

//  Correct
_logger.LogInformation("Token acquired, expires: {ExpiresOn}", expiresOn);

3. N’utilisez pas la journalisation détaillée en production :

//  Wrong - production appsettings.json
"Microsoft.Identity": "Debug"

//  Correct
"Microsoft.Identity": "Warning"