{"id":3296,"date":"2015-08-07T13:15:06","date_gmt":"2015-08-07T20:15:06","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=3296"},"modified":"2015-08-07T13:16:10","modified_gmt":"2015-08-07T20:16:10","slug":"adal-diagnostics","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2015\/08\/07\/adal-diagnostics\/","title":{"rendered":"ADAL Diagnostics"},"content":{"rendered":"<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/61941008.jpg\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"61941008\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/61941008_thumb.jpg\" alt=\"61941008\" width=\"400\" height=\"400\" border=\"0\" \/><\/a><\/p>\n<p>Every time somebody needs help troubleshooting an app using ADAL, one of the first things we ask is to provide ADAL logs (and possibly a <a href=\"http:\/\/www.telerik.com\/download\/fiddler\">Fiddler<\/a> trace as well).<\/p>\n<p>I usually have to write something like \u201cyou can find instructions on how to capture ADAL .NET logs in the Diagnostics section of <a title=\"https:\/\/github.com\/AzureAD\/azure-activedirectory-library-for-dotnet\/blob\/master\/README.md\" href=\"https:\/\/github.com\/AzureAD\/azure-activedirectory-library-for-dotnet\/blob\/master\/README.md\">https:\/\/github.com\/AzureAD\/azure-activedirectory-library-for-dotnet\/blob\/master\/README.md<\/a>\u201d, which is more typing work than I\u2019d like (and occasionally people still can\u2019t find the right section). And \u2013 there\u2019s a different readme repo for each ADAL flavor. Hence, I am <em>pasting<\/em> here only that section from\u00a0 commonly used ADALs (.NET, Android, iOS) and plan to send a link to\u00a0 this post instead <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-smile.png\" alt=\"Smile\" \/> there you go:<\/p>\n<h2>Diagnostics for ADAL .NET<\/h2>\n<p>The following are the primary sources of information for diagnosing issues:<\/p>\n<ul>\n<li>Exceptions<\/li>\n<li>Logs<\/li>\n<li>Network traces<\/li>\n<\/ul>\n<p>Also, note that correlation IDs are central to the diagnostics in the library. You can set your correlation IDs on a per request basis (by setting <code>CorrelationId<\/code> property on <code>AuthenticationContext<\/code> before calling an acquire token method) if you want to correlate an ADAL request with other operations in your code. If you don&#8217;t set a correlations id, then ADAL will generate a random one which changes on each request. All log messages and network calls will be stamped with the correlation id.<\/p>\n<h3>Exceptions<\/h3>\n<p>This is obviously the first diagnostic. We try to provide helpful error messages. If you find one that is not helpful please file an <a href=\"https:\/\/github.com\/AzureAD\/azure-activedirectory-library-for-dotnet\/issues\">issue<\/a> and let us know. Please also provide the target platform of your application (e.g. Desktop, Windows Store, Windows Phone).<\/p>\n<h3>Logs<\/h3>\n<p>You can configure the library to generate log messages that you can use to help diagnose issues. You configure logging by setting properties of the static class <code>AdalTrace<\/code>; however, depending on the platform, logging methods and the properties of this class differ. Here is how logging works on each platform:<\/p>\n<h4>Desktop Applications<\/h4>\n<p>ADAL.NET for desktop applications by default logs via <code>System.Diagnostics.Trace<\/code> class. You can add a trace listener to receive those logs. You can also control tracing using this method (e.g. change trace level or turn it off) using <code>AdalTrace.LegacyTraceSwitch<\/code>.<\/p>\n<p>The following example shows how to add a Console based listener and set trace level to <code>Information<\/code> (the default trace level is <code>Verbose<\/code>):<\/p>\n<pre><code>Trace.Listeners.Add(new ConsoleTraceListener());\r\nAdalTrace.LegacyTraceSwitch.Level = TraceLevel.Info;\r\n<\/code><\/pre>\n<p>You can achieve the same result by adding the following lines to your application&#8217;s config file:<\/p>\n<pre><code>  &lt;system.diagnostics&gt;\r\n    &lt;sharedListeners&gt;\r\n      &lt;add name=\"console\" \r\n        type=\"System.Diagnostics.ConsoleTraceListener\" \r\n        initializeData=\"false\"\/&gt;\r\n    &lt;\/sharedListeners&gt;\r\n    &lt;trace autoflush=\"true\"&gt;\r\n      &lt;listeners&gt;\r\n        &lt;add name=\"console\" \/&gt;\r\n      &lt;\/listeners&gt;\r\n    &lt;\/trace&gt;    \r\n    &lt;switches&gt;\r\n      &lt;add name=\"ADALLegacySwitch\" value=\"Info\"\/&gt;\r\n    &lt;\/switches&gt;\r\n  &lt;\/system.diagnostics&gt;\r\n<\/code><\/pre>\n<p>If you would like to have more control over how tracing is done in ADAL, you can add a <code>TraceListener<\/code> to ADAL&#8217;s dedicated <code>TraceSource<\/code> with name <strong>&#8220;Microsoft.IdentityModel.Clients.ActiveDirectory&#8221;<\/strong>.<\/p>\n<p>The following example shows how to write ADAL&#8217;s traces to a text file using this method:<\/p>\n<pre><code>Stream logFile = File.Create(\"logFile.txt\");\r\nAdalTrace.TraceSource.Listeners.Add(new TextWriterTraceListener(logFile));\r\nAdalTrace.TraceSource.Switch.Level = SourceLevels.Information;\r\n<\/code><\/pre>\n<p>You can achieve the same result by adding the following lines to your application&#8217;s config file:<\/p>\n<pre><code>  &lt;system.diagnostics&gt;\r\n    &lt;trace autoflush=\"true\"\/&gt;\r\n    &lt;sources&gt;\r\n      &lt;source name=\"Microsoft.IdentityModel.Clients.ActiveDirectory\" \r\n        switchName=\"sourceSwitch\" \r\n        switchType=\"System.Diagnostics.SourceSwitch\"&gt;\r\n        &lt;listeners&gt;\r\n          &lt;add name=\"textListener\" \r\n            type=\"System.Diagnostics.TextWriterTraceListener\" \r\n            initializeData=\"logFile.txt\"\/&gt;\r\n          &lt;remove name=\"Default\" \/&gt;\r\n        &lt;\/listeners&gt;\r\n      &lt;\/source&gt;\r\n    &lt;\/sources&gt;    \r\n    &lt;switches&gt;\r\n      &lt;add name=\"sourceSwitch\" value=\"Information\"\/&gt;\r\n    &lt;\/switches&gt;\r\n  &lt;\/system.diagnostics&gt;\r\n<\/code><\/pre>\n<h4>Windows Store and Windows Phone Applications<\/h4>\n<p>Tracing in ADAL for Windows Store and Windows Phone is done via an instance of class <code>System.Diagnostics.Tracing.EventSource<\/code> with name <strong>&#8220;Microsoft.IdentityModel.Clients.ActiveDirectory&#8221;<\/strong>. You can define your own <code>EventListener<\/code>, connect it to the event source and set your desired trace level. Here is an example:<\/p>\n<pre><code>var eventListener = new SampleEventListener();\r\n\r\nclass SampleEventListener : EventListener\r\n{\r\n    protected override void OnEventSourceCreated(EventSource eventSource)\r\n    {\r\n        if (eventSource.Name == \"Microsoft.IdentityModel.Clients.ActiveDirectory\")\r\n        {\r\n            this.EnableEvents(eventSource, EventLevel.Verbose);\r\n        }\r\n    }\r\n\r\n    protected override void OnEventWritten(EventWrittenEventArgs eventData)\r\n    {\r\n        ...\r\n    }\r\n}\r\n\r\n<\/code><\/pre>\n<p>There is also a default event listener which writes logs to a local file named <strong>&#8220;AdalTraces.log&#8221;<\/strong>. You can control the level of tracing to that event listener using the property <code>AdalTrace.Level<\/code>. By default, trace level for this event listener is set to &#8220;None&#8221; and to enable tracing to this particular listener, you need to set the above property. This is an example:<\/p>\n<pre><code>AdalTrace.Level = AdalTraceLevel.Informational;\r\n<\/code><\/pre>\n<h6>Windows Phone Silverlight Applications<\/h6>\n<p>Since Silverlight does not support EventSource\/EventListener, we use <code>LoggingChannel\/LoginSession<\/code> for logging. There is a <code>LoggingChannel<\/code> in <code>AdalTrace<\/code> which you can connect your own <code>LoggingSession\/FileLoggingSession<\/code> to it and also control trace level using it. Here is an example:<\/p>\n<pre><code>LoggingSession loggingSession = new LoggingSession(\"ADAL Logging Session\");\r\nloggingSession.AddLoggingChannel(AdalTrace.AdalLoggingChannel, LoggingLevel.Verbose);\r\n<\/code><\/pre>\n<p>and then use <code>loggingSession.SaveToFileAsync(...)<\/code> to copy the logs to a file. If you use emulator, you can then use <code>ISETool.exe<\/code> and <code>tracerpt.exe<\/code> tools to copy log file and convert it to text format.<\/p>\n<h3>Network Traces<\/h3>\n<p>You can use various tools to capture the HTTP traffic that ADAL generates. This is most useful if you are familiar with the OAuth protocol or if you need to provide diagnostic information to Microsoft or other support channels.<\/p>\n<p>Fiddler is the easiest HTTP tracing tool. In order to be useful it is necessary to configure fiddler to record unencrypted SSL traffic.<\/p>\n<p>NOTE: Traces generated in this way may contain highly privileged information such as access tokens, usernames and passwords. If you are using production accounts, do not share these traces with 3rd parties. If you need to supply a trace to someone in order to get support, reproduce the issue with a temporary account with usernames and passwords that you don&#8217;t mind sharing.<\/p>\n<p>=================================<\/p>\n<h2>Diagnostics for ADAL Android<\/h2>\n<p>The following are the primary sources of information for diagnosing issues:<\/p>\n<ul>\n<li>Exceptions<\/li>\n<li>Logs<\/li>\n<li>Network traces<\/li>\n<\/ul>\n<p>Also, note that correlation IDs are central to the diagnostics in the library. You can set your correlation IDs on a per request basis if you want to correlate an ADAL request with other operations in your code. If you don&#8217;t set a correlations id then ADAL will generate a random one and all log messages and network calls will be stamped with the correlation id. The self generated id changes on each request.<\/p>\n<h3>Exceptions<\/h3>\n<p>This is obviously the first diagnostic. We try to provide helpful error messages. If you find one that is not helpful please file an issue and let us know. Please also provide device information such as model and SDK#.<\/p>\n<h3>Logs<\/h3>\n<p>You can configure the library to generate log messages that you can use to help diagnose issues. You configure logging by making the following call to configure a callback that ADAL will use to hand off each log message as it is generated.<\/p>\n<pre> Logger.getInstance().setExternalLogger(new ILogger() {\r\n     @Override\r\n     public void Log(String tag, String message, String additionalMessage, LogLevel level, ADALError errorCode) {\r\n      ...\r\n      \/\/ You can write this to logfile depending on level or errorcode.\r\n      writeToLogFile(getApplicationContext(), tag +\":\" + message + \"-\" + additionalMessage);\r\n     }\r\n }<\/pre>\n<p>Messages can be written to a custom log file as seen below. Unfortunately, there is no standard way of getting logs from a device. There are some services that can help you with this. You can also invent your own, such as sending the file to a server.<\/p>\n<pre>private syncronized void writeToLogFile(Context ctx, String msg) {      \r\n       File directory = ctx.getDir(ctx.getPackageName(), Context.MODE_PRIVATE);\r\n       File logFile = new File(directory, \"logfile\");\r\n       FileOutputStream outputStream = new FileOutputStream(logFile, true);\r\n       OutputStreamWriter osw = new OutputStreamWriter(outputStream);\r\n       osw.write(msg);\r\n       osw.flush();\r\n       osw.close(); \r\n}<\/pre>\n<h6>Logging Levels<\/h6>\n<ul>\n<li>Error(Exceptions)<\/li>\n<li>Warn(Warning)<\/li>\n<li>Info(Information purposes)<\/li>\n<li>Verbose(More details)<\/li>\n<\/ul>\n<p>You set the log level like this:<\/p>\n<pre>Logger.getInstance().setLogLevel(Logger.LogLevel.Verbose);<\/pre>\n<p>All log messages are sent to logcat in addition to any custom log callbacks. You can get log to a file form logcat as shown belog:<\/p>\n<pre><code>  adb logcat &gt; \"C:\\logmsg\\logfile.txt\"\r\n<\/code><\/pre>\n<p>More examples about adb cmds: <a href=\"https:\/\/developer.android.com\/tools\/debugging\/debugging-log.html#startingLogcat\">https:\/\/developer.android.com\/tools\/debugging\/debugging-log.html#startingLogcat<\/a><\/p>\n<h3>Network Traces<\/h3>\n<p>You can use various tools to capture the HTTP traffic that ADAL generates. This is most useful if you are familiar with the OAuth protocol or if you need to provide diagnostic information to Microsoft or other support channels.<\/p>\n<p>Fiddler is the easiest HTTP tracing tool. Use the following links to setup it up to correctly record ADAL network traffic. In order to be useful it is necessary to configure fiddler, or any other tool such as Charles, to record unencrypted SSL traffic. NOTE: Traces generated in this way may contain highly privileged information such as access tokens, usernames and passwords. If you are using production accounts, do not share these traces with 3rd parties. If you need to supply a trace to someone in order to get support, reproduce the issue with a temporary account with usernames and passwords that you don&#8217;t mind sharing.<\/p>\n<ul>\n<li><a href=\"http:\/\/docs.telerik.com\/fiddler\/configure-fiddler\/tasks\/ConfigureForAndroid\">Setting Up Fiddler For Android<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/AzureAD\/azure-activedirectory-library-for-android\/wiki\/How-to-listen-to-httpUrlConnection-in-Android-app-from-Fiddler\">Configure Fiddler Rules For ADAL<\/a><\/li>\n<\/ul>\n<p>=================================<\/p>\n<h2>Diagnostics for ADAL iOS<\/h2>\n<p>The following are the primary sources of information for diagnosing issues:<\/p>\n<ul>\n<li>NSError<\/li>\n<li>Logs<\/li>\n<li>Network traces<\/li>\n<\/ul>\n<p>Also, note that correlation IDs are central to the diagnostics in the library. You can set your correlation IDs on a per request basis if you want to correlate an ADAL request with other operations in your code. If you don&#8217;t set a correlations id then ADAL will generate a random one and all log messages and network calls will be stamped with the correlation id. The self generated id changes on each request.<\/p>\n<h3>NSError<\/h3>\n<p>This is obviously the first diagnostic. We try to provide helpful error messages. If you find one that is not helpful please file an issue and let us know. Please also provide device information such as model and SDK#. The error message is returned as a part of the ADAuthenticationResult where the status is set to AD_FAILED.<\/p>\n<h3>Logs<\/h3>\n<p>You can configure the library to generate log messages that you can use to help diagnose issues. ADAL uses NSLog by default to log the messages. Each API method call is decorated with API version and every other message is decorated with correlation id and UTC timestamp. This data is important to look of server side diagnostics. SDK also exposes the ability to provide a custom Logger callback as follows.<\/p>\n<pre>    [ADLogger setLogCallBack:^(ADAL_LOG_LEVEL logLevel, NSString *message, NSString *additionalInformation, NSInteger errorCode) {\r\n        \/\/HANDLE LOG MESSAGE HERE\r\n    }]<\/pre>\n<h6>Logging Levels<\/h6>\n<ul>\n<li>No_Log(Disable all logging)<\/li>\n<li>Error(Exceptions. Set as default)<\/li>\n<li>Warn(Warning)<\/li>\n<li>Info(Information purposes)<\/li>\n<li>Verbose(More details)<\/li>\n<\/ul>\n<p>You set the log level like this:<\/p>\n<pre>[ADLogger setLevel:ADAL_LOG_LEVEL_INFO]<\/pre>\n<h3>Network Traces<\/h3>\n<p>You can use various tools to capture the HTTP traffic that ADAL generates. This is most useful if you are familiar with the OAuth protocol or if you need to provide diagnostic information to Microsoft or other support channels.<\/p>\n<p>Charles is the easiest HTTP tracing tool in OSX. Use the following links to setup it up to correctly record ADAL network traffic. In order to be useful it is necessary to configure Charles, to record unencrypted SSL traffic. NOTE: Traces generated in this way may contain highly privileged information such as access tokens, usernames and passwords. If you are using production accounts, do not share these traces with 3rd parties. If you need to supply a trace to someone in order to get support, reproduce the issue with a temporary account with usernames and passwords that you don&#8217;t mind sharing.<\/p>\n<ul>\n<li><a href=\"http:\/\/www.charlesproxy.com\/documentation\/faqs\/ssl-connections-from-within-iphone-applications\/\">Setting Up SSL For iOS Simulator or Devices<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Every time somebody needs help troubleshooting an app using ADAL, one of the first things we ask is to provide ADAL logs (and possibly a Fiddler trace as well). I usually have to write something like \u201cyou can find instructions on how to capture ADAL .NET logs in the Diagnostics section of https:\/\/github.com\/AzureAD\/azure-activedirectory-library-for-dotnet\/blob\/master\/README.md\u201d,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":3294,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3296","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3296","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=3296"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3296\/revisions"}],"predecessor-version":[{"id":3299,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3296\/revisions\/3299"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/3294"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=3296"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=3296"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=3296"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}