Настройка ведения журнала в Microsoft. Identity.Web

Microsoft.Identity.Web интегрируется с инфраструктурой логирования ASP.NET Core. Используйте его для диагностики проблем в разных странах:

  • Потоки проверки подлинности — вход, выход, проверка маркеров
  • Получение токена — попадания и промахи кэша токенов, операции MSAL
  • Вызовы дочернего API — HTTP-запросы, получение токенов для API
  • Условия ошибки — исключения, сбои проверки

Общие сведения о зарегистрированных компонентах

Компонент Источник журнала событий Purpose
Microsoft. Identity.Web Основная логика проверки подлинности Конфигурация, получение токена, вызовы API
MSAL.NET Microsoft.Identity.Client Операции кэша токенов, проверка полномочий
Модель идентичности Проверка токенов Анализ JWT, проверка подписи, извлечение утверждений
ASP.NET Core Auth Microsoft.AspNetCore.Authentication Операции cookie, вызовы и запреты действий

Как начать работать с логированием

Минимальная конфигурация

Чтобы включить логирование идентификации, добавьте следующие записи уровня журнала в appsettings.json:

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

Это позволяет Information-level логирование для Microsoft.Identity.Web и его зависимостей (MSAL.NET, IdentityModel).

Конфигурация разработки

Для подробной диагностики во время разработки:

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

Рабочая конфигурация

Для рабочей среды свести к минимуму объем журнала при записи ошибок:

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

Настройка фильтрации журналов

Фильтрация на основе пространства имен

Управление уровнем детализации логов по пространству имен. Для каждого пространства имен, связанного с идентификацией, устанавливаются следующие уровни конфигурации:

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

Отключение определенного ведения журнала

Чтобы отключить шумные компоненты, не затрагивая другие, задайте для их уровня журнала значение None или Warning.

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

Конфигурация для конкретной среды

Используйте appsettings.{Environment}.json для установки параметров для каждой среды.

appsettings.Development.json:

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

appsettings.Production.json:

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

Понять уровни журнала

ASP.NET Core определяет следующие уровни журнала. Выберите уровень, который балансирует данные диагностики с объемом журнала для вашей среды.

уровни логирования ASP.NET Core

Уровень Использование Объем Производственный процесс?
Трассировка Подробно описана каждая операция Очень высокий Нет
Debug Подробный поток, полезный для разработки Высокий Нет
Информация Общий поток, ключевые события Умеренно Выборочный
Предупреждение Непредвиденные, но обрабатываемые условия Низкий Да
Error Ошибки и исключения Очень низкий Да
Критический Неустранимые сбои Очень низкий Да
Нет Отключение ведения журнала Нет Выборочный

Соотнесение MSAL.NET с уровнями ASP.NET Core

уровень MSAL.NET эквивалент ASP.NET Core Описание
Verbose Debug или Trace Наиболее подробные сообщения
Info Information События проверки подлинности ключей
Warning Warning Аномальные, но обрабатываемые условия
Error Error или Critical Ошибки и исключения

Используйте следующие конфигурации для каждой среды.

Разработка:

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

Стейджинг:

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

Производства:

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

Настройка логирования персональных данных

По умолчанию Microsoft. Identity.Web редактирует персональные данные (PII) из журналов. Включите ведение журнала PII только в средах разработки, чтобы просмотреть полные сведения о пользователе.

Что такое PII?

Личные сведения (PII) включают:

  • Имена пользователей, адреса электронной почты
  • Отображаемые имена
  • Идентификаторы объектов, идентификаторы клиента
  • IP-адреса
  • Значения маркеров, утверждения

Предупреждение системы безопасности

ПРЕДУПРЕЖДЕНИЕ. Вы и ваше приложение отвечают за соблюдение всех применимых нормативных требований, включая те, которые определены GDPR. Перед включением ведения журнала piI убедитесь, что вы можете безопасно обрабатывать эти потенциально конфиденциальные данные.

Включение ведения журнала PII (только для разработки)

Задайте значение EnablePiiLoggingtrue в файле конфигурации разработки:

appsettings.Development.json:

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

Управление логированием PII программным способом

Переключение логирования PII в зависимости от среды размещения:

var builder = WebApplication.CreateBuilder(args);

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

Какие изменения происходят при включении PII?

Без ведения журнала PII:

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

С включенным piI:

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

Редактура PII в журналах

При отключении ведения журнала piI конфиденциальные данные заменяются следующим образом:

  • {hidden} — скрывает идентификаторы пользователей
  • {hash:XXXX} — отображает хэш вместо фактического значения
  • *** — скрывает токены

Использование идентификаторов корреляции

Идентификаторы корреляции используются для отслеживания запросов аутентификации между различными службами. Включите их в журналы и запросы в службу поддержки, чтобы ускорить разрешение проблем.

Что такое идентификаторы корреляции?

Идентификатор корреляции — это идентификатор GUID , который однозначно идентифицирует запрос на проверку подлинности или получение маркеров по всему:

  • Ваше приложение
  • платформа удостоверений Microsoft
  • библиотека MSAL.NET
  • серверные службы Microsoft

Получение идентификаторов корреляции

Метод 1: из AuthenticationResult

Извлеките идентификатор корреляции из 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);
    }
}

Метод 2: от MsalServiceException

Зафиксировать идентификатор корреляции при 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
    });
}

Метод 3. Настройка пользовательского идентификатора корреляции

Назначьте пользовательский идентификатор корреляции для связывания трассировок приложений с запросами 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);
}

Предоставление идентификаторов корреляции для поддержки

При обращении к Microsoft поддержке укажите следующие сведения:

  1. Идентификатор корреляции — из журналов или исключений
  2. Метка времени — при возникновении ошибки (UTC)
  3. идентификатор Tenant ID — клиент Microsoft Entra ID
  4. Код ошибки : если применимо (например, AADSTS50058)

Пример запроса на поддержку:

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

Включить журналирование кэша токенов

Ведение журнала кэша токенов помогает понять поведение попаданий/промахов кэша и диагностировать проблемы с производительностью распределенных кэшей.

Включить диагностику кэша токенов

Для приложений .NET Framework или .NET Core с помощью распределенных кэшей маркеров настройте подробное ведение журнала:

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

Примеры логов кэша токенов

Попадание в кэш:

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

Промах кэша:

[Debug] Token cache: No token found in cache for scopes 'user.read'
[Information] Token source: IdentityProvider
[Debug] Token cache: Token stored in 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:

Настройка распределенного кэша SQL Server с ведением журнала:

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

Устранение распространенных неполадок

Используйте следующие сценарии для диагностики частых проблем проверки подлинности и авторизации.

Распространенные сценарии ведения журнала

Сценарий 1: Ошибки проверки токенов

Симптом: 401 Несанкционированные ответы

Включите подробное ведение журнала:

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

Ищите:

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

Сценарий 2: Ошибки получения токена

Симптом:MsalServiceException Или MsalUiRequiredException

Включите подробное ведение журнала:

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

Ищите:

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

Сценарий 3. Сбои вызовов низкоуровневого API

Симптом: Ошибки HTTP 502 или ошибки времени ожидания при вызове нижестоящего API

Включите подробное ведение журнала:

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

Добавьте настраиваемое ведение журнала в контроллер для записи ошибок нижестоящего API:

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

Интерпретация шаблонов журналов

В следующих примерах показаны типичные выходные данные журнала для распространенных событий проверки подлинности.

Успешный поток проверки подлинности:

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

Требуется согласие:

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

Обновление токена:

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

Агрегировать журналы регистрации у внешних поставщиков услуг.

Переадресация идентификационных журналов в централизованную платформу логирования для мониторинга и оповещения.

Интеграция с Application Insights:

Отправка телеметрии идентификационных данных в Application Insights с обогащением идентификаторов корреляции:

using Microsoft.ApplicationInsights.Extensibility;

builder.Services.AddApplicationInsightsTelemetry();

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

Интеграция Serilog:

Настройте 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();

Следуйте рекомендациям по ведению журнала

Примените эти методики, чтобы обеспечить безопасность, полезность и производительность журналов удостоверений.

Что нужно делать

1. Используйте структурированное ведение журнала:

Передайте значения в качестве именованных параметров, чтобы агрегаторы журналов могли индексировать и запрашивать их:

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

2. Идентификаторы корреляции журналов:

Всегда включать идентификатор корреляции в журналы ошибок, чтобы упростить исследования поддержки:

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

3. Используйте соответствующие уровни журналов:

Соотнесите уровень логирования с серьезностью и аудиторией:

_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. Очистка журналов в рабочей среде:

Маскировать конфиденциальные значения перед записью в рабочие журналы:

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

Чего не следует делать

1. Не включайте персонально идентифицируемые данные в рабочей среде:

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

//  Correct
"EnablePiiLogging": false

2. Не записывайте секреты:

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

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

3. Не используйте подробное ведение журнала в рабочей среде:

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

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