Logging in MSAL.NET

MSAL.NET apps generate log messages that can help diagnose issues. You can configure logging with a few lines of code, and have custom control over the level of detail and whether or not personal and organizational data is logged. Logging isn't enabled by default. We recommend you enable MSAL logging to provide a way for users to submit logs when they have authentication issues. Note that MSAL doesn't store any logs and emits logs to the destination provided in the logger implementation.

Note

Starting with MSAL.NET 4.58.0 developers can also use OpenTelemetry to aggregate logs and measure application performance.

Logging levels

There are several levels of logging detail:

  • LogAlways: Base level which includes logs of important health metrics to help with diagnostics of MSAL operations.
  • Critical: Logs that describe an unrecoverable application or system crash, or a catastrophic failure that requires immediate attention.
  • Error: Indicates something has gone wrong and an error was generated. Used for debugging and identifying problems.
  • Warning: Includes logs in scenarios when there hasn't necessarily been an error or failure, but are intended for diagnostics and pinpointing problems. This is the recommended minimum level that should be enabled in production apps.
  • Informational: MSAL will log events intended for informational purposes, not necessarily intended for debugging.
  • Verbose: MSAL logs the full details of library behavior. In production environment, verbose level should only be enabled temporarily to gather logs for a specific debugging purpose.

Personal and organizational data

By default, the MSAL logger doesn't capture any highly sensitive personal or organizational data. The library provides the option to enable logging personal and organizational data if you decide to do so. For details, see Handling of personally-identifiable information in MSAL.NET.

Configure logging in MSAL.NET

In MSAL, logging is set during application creation using the WithLogging(IIdentityLogger, Boolean) builder. This method takes the following parameters:

  • identityLogger is the logging implementation used by MSAL.NET to produce logs for debugging or health check purposes. Logs are only sent if logging is enabled.
  • enablePiiLogging enables logging personal and organizational data (PII) if set to true. By default, this parameter is set to false, so that your application doesn't log sensitive data.

IIdentityLogger interface

namespace Microsoft.IdentityModel.Abstractions
{
    public interface IIdentityLogger
    {
        //
        // Summary:
        //     Checks to see if logging is enabled at given eventLogLevel.
        //
        // Parameters:
        //   eventLogLevel:
        //     Log level of a message.
        bool IsEnabled(EventLogLevel eventLogLevel);

        //
        // Summary:
        //     Writes a log entry.
        //
        // Parameters:
        //   entry:
        //     Defines a structured message to be logged at the provided Microsoft.IdentityModel.Abstractions.LogEntry.EventLogLevel.
        void Log(LogEntry entry);
    }
}

Note

Partner libraries (Microsoft.Identity.Web, Microsoft.IdentityModel) already provide implementations of this interface for various environments (in particular ASP.NET Core).

IIdentityLogger implementation

Log level from a configuration file

It's highly recommended to configure your code to use a configuration file in your environment to set the log level as it will enable your code to change the MSAL logging level without needing to rebuild or restart the application. This is critical for diagnostic purposes, enabling to quickly gather the required logs from the application that is currently deployed in production. Verbose logging can be costly, so it's best to use the Informational level by default and enable verbose logging when an issue is encountered. See JSON configuration provider for an example on how to load data from a configuration file without restarting the application.

Log level from an environment variable

Another option we recommended is to configure your code to use an environment variable on the machine to set the log level as it will enable your code to change the MSAL logging level without needing to rebuild the application.

See EventLogLevel for details on the available log levels.

Example:

    class MyIdentityLogger : IIdentityLogger
    {
        public EventLogLevel MinLogLevel { get; }

        public MyIdentityLogger()
        {
            //Retrieve the log level from an environment variable
            var msalEnvLogLevel = Environment.GetEnvironmentVariable("MSAL_LOG_LEVEL");

            if (Enum.TryParse(msalEnvLogLevel, out EventLogLevel msalLogLevel))
            {
                MinLogLevel = msalLogLevel;
            }
            else
            {
                //Recommended default log level
                MinLogLevel = EventLogLevel.Informational;
            }
        }

        public bool IsEnabled(EventLogLevel eventLogLevel)
        {
            return eventLogLevel <= MinLogLevel;
        }

        public void Log(LogEntry entry)
        {
            //Log Message here:
            Console.WriteLine(entry.message);
        }
    }

Using MyIdentityLogger:

    MyIdentityLogger myLogger = new MyIdentityLogger(logLevel);

    var app = ConfidentialClientApplicationBuilder
        .Create(TestConstants.ClientId)
        .WithClientSecret("secret")
        .WithLogging(myLogger, enablePiiLogging)
        .Build();

Logging in a distributed token cache

If you use token cache serializers from Microsoft.Identity.Web.TokenCache package on .NET, you can enable additional caching logs.

To enable distributed cache logging, set the MinLevel property to Debug.

     app.AddDistributedTokenCache(services =>
     {
          services.AddDistributedMemoryCache();
          services.AddLogging(configure => configure.AddConsole())
               .Configure<LoggerFilterOptions>(options => options.MinLevel = Microsoft.Extensions.Logging.LogLevel.Debug);
     });

See more sample code using Microsoft Identity Web token cache serializers in the ConfidentialClientTokenCache sample. Also see Implement a custom logging provider for more details.

Network traces

Important

Network traces typically contain personally-identifiable information. Remove these sensitive details before posting the logs on GitHub.

In the case when verbose logs don't provide sufficient insight, you can get a network trace using tools like Fiddler. If such tool is not possible to use, for example on mobile, you can modify the HttpClient used by MSAL to log the HTTP traffic. See this custom HttpClient implementation with logging. (This client should not be used in production, but only for logging). Custom HttpClient can be added as following:

var msalPublicClient = PublicClientApplicationBuilder
       .Create(ClientId)
       .WithHttpClientFactory(new HttpSnifferClientFactory())
       .Build();

Correlation ID

Logs help understand MSAL's behavior on the client side. To understand what's happening on the service side, the team needs a correlation ID. This ID traces an authentication request through the various back-end services.

The correlation ID can be obtained in three ways:

  1. from a successful authentication result - AuthenticationResult.CorrelationId;
  2. from a service exception - MsalServiceException.CorrelationId, and
  3. by passing a custom correlation ID to WithCorrelationId(Guid) when building a token request.

When providing your own correlation ID, use a different ID value for each request. Don't use a constant as we won't be able to differentiate between the requests.