Condividi tramite


Registrazione e diagnostica in Microsoft. Identity.Web

Questa guida illustra come configurare e usare l'accesso in Microsoft. Identity.Web per risolvere i problemi di autenticazione e acquisizione di token.

Microsoft. Identity.Web si integra con l'infrastruttura di registrazione di ASP.NET Core, offrendo visibilità su:

  • 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

Cosa viene registrato?

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

Avvio rapido

Configurazione minima

Aggiungi a appsettings.json:

{
  "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
  }
}

Configurazione

filtro basato su namespace

Controllare il livello di dettaglio del log per spazio dei nomi:

{
  "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:

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

configurazione specifica per l'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
  }
}

Livelli di log

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

Mappatura di MSAL.NET per 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

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

Registrazione delle informazioni personali

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)

appsettings.Development.json:

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

Controllo PII a livello di codice

Per la registrazione delle informazioni personali condizionale in base all'ambiente:

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

ID correlazione

Gli ID di correlazione tracciano le richieste di autenticazione nei servizi di Microsoft, critici per gli scenari di supporto.

Che cosa sono gli ID di correlazione?

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

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

Recupero degli ID di correlazione

Metodo 1: dall’AuthenticationResult

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

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 l'ID correlazione personalizzato

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

Uso degli ID di correlazione per il supporto

Quando si contatta Microsoft supporto tecnico, fornire:

  1. ID correlazione - Da un log o un'eccezione
  2. Timestamp - Quando si è verificato l'errore (UTC)
  3. ID Tenant - Il tenant di Microsoft Entra
  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

Registrazione della cache dei token

Abilitare la diagnostica della cache dei token

Per le app .NET Framework o .NET Core usando le cache dei token distribuiti:

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

Risoluzione dei problemi relativi alla cache distribuita

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:

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

Risoluzione dei problemi

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

Cerca:

[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

Abilitare la registrazione dettagliata:

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

Registrazione personalizzata nei controller:

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

Interpretazione dei modelli di log

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

Procedure consigliate per l'aggregazione dei log

Integrazione di Application Insights:

using Microsoft.ApplicationInsights.Extensibility;

builder.Services.AddApplicationInsightsTelemetry();

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

Integrazione di Serilog:

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

Procedure consigliate

Cose da fare

1. Usare la registrazione strutturata:

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

2. ID di correlazione dei log:

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

3. Usare i livelli di log appropriati:

_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:

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"