Configurare la registrazione in Microsoft.Identity.Web

Microsoft. Identity.Web si integra con l'infrastruttura di registrazione di ASP.NET Core. Usarlo per diagnosticare i problemi tra:

  • Flussi di autenticazione - Accesso, disconnessione, convalida dei token
  • Acquisizione del token - Colpi/errori nella cache dei token, operazioni MSAL
  • Chiamate API downstream - Richieste HTTP, acquisizione di token per le API
  • Condizioni di errore - Eccezioni, errori di convalida

Comprendere i componenti registrati

Componente origine del log Scopo
Microsoft. Identity.Web Logica di autenticazione di base Configurazione, acquisizione di token, chiamate API
MSAL.NET Microsoft.Identity.Client Operazioni della cache dei token, convalida dell'autorità
Modello di identità Convalida dei token Analisi JWT, convalida della firma, estrazione delle attestazioni
ASP.NET Core Autenticazione Microsoft.AspNetCore.Authentication Operazioni sui cookie: sfida/vieta azioni

Introduzione al monitoraggio

Configurazione minima

Aggiungere le seguenti voci a livello di log a appsettings.json per abilitare la registrazione delle identità:

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

Ciò abilita il logging a livello di Informazioni per Microsoft.Identity.Web e le relative dipendenze (MSAL.NET, IdentityModel).

Configurazione di sviluppo

Per una diagnostica dettagliata durante lo sviluppo:

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

Configurazione di produzione

Per l'ambiente di produzione, ridurre al minimo il volume di log durante l'acquisizione degli errori:

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

Configurare il filtro dei log

Filtro basato sullo spazio dei nomi

Controllare il livello di dettaglio del log in base allo spazio dei nomi. La seguente configurazione imposta livelli granulari per ciascun namespace correlato all'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"
    }
  }
}

Disabilitare la registrazione specifica

Per disattivare i componenti rumorosi senza influire sugli altri utenti, impostare il livello di log su None o Warning:

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

Configurazione specifica dell'ambiente

Usare appsettings.{Environment}.json per le impostazioni per ambiente:

appsettings.Development.json:

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

appsettings.Production.json:

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

Comprendere i livelli di log

ASP.NET Core definisce i livelli di log seguenti. Scegliere il livello che bilancia i dettagli diagnostici rispetto al volume dei log per l'ambiente in uso.

ASP.NET Core livelli di log

livello Utilizzo Volume Produzione?
Traccia Più dettagliata, ogni operazione Molto alto No
Debug Flusso dettagliato, utile per lo sviluppo Alto No
Informazioni Flusso generale, eventi chiave Moderato Selettivo
Avvertenza Condizioni impreviste ma gestite Low
Error Errori ed eccezioni Molto basso
Critico Errori irreversibili Molto basso
Nessuno Disabilitare la registrazione Nessuno Selettivo

Mappare MSAL.NET nei livelli di ASP.NET Core

livello MSAL.NET L'equivalente di ASP.NET Core Descrizione
Verbose Debug oppure Trace Messaggi più dettagliati
Info Information Eventi di autenticazione chiave
Warning Warning Condizioni anomale ma gestite
Error Error oppure Critical Errori ed eccezioni

Usare le configurazioni seguenti per ambiente.

Sviluppo:

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

Staging:

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

Produzione:

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

Configurare la registrazione delle informazioni personali

Per impostazione predefinita, Microsoft.Identity.Web oscura le informazioni di identificazione personale (PII) dai log. Abilitare la registrazione delle informazioni personali solo negli ambienti di sviluppo per visualizzare i dettagli completi dell'utente.

Che cos'è il PII (informazioni di identificazione personale)?

Le informazioni personali includono :

  • Nomi utente, indirizzi di posta elettronica
  • Nomi visualizzati
  • ID oggetto, ID tenant
  • Indirizzi IP
  • Valori dei token, attestazioni

Avviso di sicurezza

AVVISO: l'utente e l'applicazione sono responsabili della conformità a tutti i requisiti normativi applicabili, inclusi quelli stabiliti dal GDPR. Prima di abilitare la registrazione delle informazioni personali, assicurarsi di poter gestire in modo sicuro questi dati potenzialmente altamente sensibili.

Abilitare la registrazione delle informazioni personali (solo sviluppo)

Imposta EnablePiiLogging su true nel file di configurazione di sviluppo:

appsettings.Development.json:

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

Controllare la registrazione dei PII tramite programmazione

Attivare o disattivare la registrazione delle informazioni personali in base all'ambiente di hosting:

var builder = WebApplication.CreateBuilder(args);

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

Cosa cambia con PII abilitato?

Senza registrazione delle informazioni personali:

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

Con le informazioni personali (PII) abilitate:

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

Redazione dei dati personali nei log

Quando la registrazione delle informazioni personali è disabilitata, i dati sensibili vengono sostituiti con:

  • {hidden} - Nasconde gli identificatori utente
  • {hash:XXXX} - Mostra l'hash anziché il valore effettivo
  • *** - Nasconde i token

Usare gli ID di correlazione

Gli ID di correlazione tracciano le richieste di autenticazione tra i servizi. Includerli nei log e nei ticket di supporto per velocizzare la risoluzione dei problemi.

Che cosa sono gli ID di correlazione?

Un ID di correlazione è un GUID che identifica in modo univoco una richiesta di autenticazione o acquisizione di token in:

  • L'applicazione
  • Microsoft Identity Platform
  • libreria MSAL.NET
  • servizi back-end di Microsoft

Ottenere gli ID di correlazione

Metodo 1: dall’AuthenticationResult

Estrarre l'ID di correlazione da AuthenticationResult dopo l'acquisizione di un token riuscito:

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

Metodo 2: da MsalServiceException

Acquisire l'ID di correlazione da MsalServiceException quando l'acquisizione del token ha esito negativo:

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

Metodo 3: Impostare un ID di correlazione personalizzato

Assegnare un ID di correlazione personalizzato per collegare le tracce dell'applicazione alle richieste di 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);
}

Fornire ID di correlazione per il supporto

Quando si contatta Microsoft supporto tecnico, specificare i dettagli seguenti:

  1. ID correlazione - Da un log o un'eccezione
  2. Timestamp - Quando si è verificato l'errore (UTC)
  3. ID tenant - Tenant del tuo Microsoft Entra ID
  4. Codice errore - Se applicabile (ad esempio, AADSTS50058)

Richiesta di supporto di esempio:

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

Abilitare la registrazione della cache dei token

La registrazione del log della cache dei token aiuta a comprendere il comportamento dei riscontri/fallimenti della cache e a diagnosticare i problemi di performance con le cache distribuite.

Abilitare la diagnostica della cache dei token

Per le app .NET Framework o .NET Core usando le cache dei token distribuiti, configurare la registrazione dettagliata:

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

Esempi di log della cache dei token

Riscontri nella cache:

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

Mancato accesso alla cache:

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

Risolvere i problemi relativi alle cache distribuite

Abilitare la registrazione specifica del provider per diagnosticare i problemi di connettività e prestazioni della 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);
});

SQL Server cache:

Configurare la cache distribuita di SQL Server con la registrazione dei log:

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

Risolvere i problemi comuni

Usare gli scenari seguenti per diagnosticare frequenti problemi di autenticazione e autorizzazione.

Scenari di registrazione comuni

Scenario 1: Errori di convalida dei token

Sintomo: 401 Risposte non autorizzate

Abilitare la registrazione dettagliata:

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

Ricerca:

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

Scenario 2: Errori di acquisizione dei token

Sintomo:MsalServiceException O MsalUiRequiredException

Abilitare la registrazione dettagliata:

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

Ricerca:

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

Scenario 3: Errori di chiamata api downstream

Sintomo: Errori di timeout o HTTP 502 durante la chiamata delle API downstream.

Abilitare la registrazione dettagliata:

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

Aggiungere log personalizzati nel controller per rilevare gli errori dell'API downstream.

[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");
    }
}

Interpretare i modelli di log

Negli esempi seguenti viene illustrato un output di log tipico per gli eventi di autenticazione comuni.

Flusso di autenticazione riuscito:

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

Consenso richiesto:

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

Aggiornamento del token:

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

Aggregare i log con provider esterni

Inoltrare i log delle identità a una piattaforma di registrazione centralizzata per il monitoraggio e gli avvisi.

Integrazione di Application Insights:

Inviare i dati di telemetria dell'identità ad Application Insights con l'arricchimento dell'ID di correlazione:

using Microsoft.ApplicationInsights.Extensibility;

builder.Services.AddApplicationInsightsTelemetry();

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

Integrazione di Serilog:

Configurare Serilog per acquisire i log delle identità nella console e gli output dei file in sequenza:

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();

Seguire le procedure consigliate per la registrazione

Applicare queste procedure per garantire la sicurezza, l'utilità e le prestazioni dei log delle identità.

Cose da fare

1. Usare la registrazione strutturata:

Passare i valori come parametri denominati in modo che gli aggregatori di log possano indicizzarli ed eseguirne query:

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

2. ID di correlazione dei log:

Includere sempre l'ID di correlazione nei log degli errori per semplificare le indagini di supporto:

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

3. Usare i livelli di log appropriati:

Abbina il livello di log alla gravità e al pubblico destinatario.

_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. Purificare i log nell'ambiente di produzione:

Mascherare i valori sensibili prima di scriverli nei log di produzione:

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

Cose da non fare

1. Non abilitare le informazioni personali nell'ambiente di produzione:

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

//  Correct
"EnablePiiLogging": false

2. Non registrare i segreti:

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

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

3. Non usare log verbosi nell'ambiente di produzione:

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

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