Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added logging to auth providers #180

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions CommunityToolkit.Authentication.Msal/MsalProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ public MsalProvider(IPublicClientApplication client, string[] scopes = null, boo
/// <param name="autoSignIn">Determines whether the provider attempts to silently log in upon creation.</param>
/// <param name="listWindowsWorkAndSchoolAccounts">Determines if organizational accounts should be enabled/disabled.</param>
/// <param name="tenantId">Registered tenant id in Azure Active Directory.</param>
public MsalProvider(string clientId, string[] scopes = null, string redirectUri = null, bool autoSignIn = true, bool listWindowsWorkAndSchoolAccounts = true, string tenantId = null)
/// <param name="withLogging">Output logs.</param>
public MsalProvider(string clientId, string[] scopes = null, string redirectUri = null, bool autoSignIn = true, bool listWindowsWorkAndSchoolAccounts = true, string tenantId = null, bool withLogging = false)
{
Client = CreatePublicClientApplication(clientId, tenantId, redirectUri, listWindowsWorkAndSchoolAccounts);
Client = CreatePublicClientApplication(clientId, tenantId, redirectUri, listWindowsWorkAndSchoolAccounts, withLogging);
Scopes = scopes.Select(s => s.ToLower()).ToArray() ?? new string[] { string.Empty };

if (autoSignIn)
Expand Down Expand Up @@ -184,13 +185,28 @@ public override Task<string> GetTokenAsync(bool silentOnly = false, string[] sco
/// <param name="tenantId">An optional tenant id.</param>
/// <param name="redirectUri">Redirect uri for auth response.</param>
/// <param name="listWindowsWorkAndSchoolAccounts">Determines if organizational accounts should be supported.</param>
/// <param name="withLogging">Output logs.</param>
/// <returns>A new instance of <see cref="PublicClientApplication"/>.</returns>
protected IPublicClientApplication CreatePublicClientApplication(string clientId, string tenantId, string redirectUri, bool listWindowsWorkAndSchoolAccounts)
protected IPublicClientApplication CreatePublicClientApplication(string clientId, string tenantId, string redirectUri, bool listWindowsWorkAndSchoolAccounts, bool withLogging)
{
var clientBuilder = PublicClientApplicationBuilder.Create(clientId)
.WithClientName(ProviderManager.ClientName)
.WithClientVersion(Assembly.GetExecutingAssembly().GetName().Version.ToString());

if (withLogging)
{
clientBuilder = clientBuilder.WithLogging((level, message, containsPii) =>
{
if (containsPii)
{
// Add a PII warning to messages containing any.
message = $"[CONTAINS PII] {message}";
}

EventLogger.Log($"{level}: {message}");
});
}

if (tenantId != null)
{
clientBuilder = clientBuilder.WithTenantId(tenantId);
Expand Down Expand Up @@ -237,13 +253,15 @@ protected async Task<string> GetTokenWithScopesAsync(string[] scopes, bool silen
authResult = await Client.AcquireTokenSilent(scopes, account).ExecuteAsync();
}
}
catch (MsalUiRequiredException)
catch (MsalUiRequiredException e)
{
EventLogger.Log(e.Message);
}
catch
catch (Exception e)
{
// Unexpected exception
// TODO: Send exception to a logger.
EventLogger.Log(e.Message);
EventLogger.Log(e.StackTrace);
}

if (authResult == null && !silentOnly)
Expand Down Expand Up @@ -271,10 +289,11 @@ protected async Task<string> GetTokenWithScopesAsync(string[] scopes, bool silen

authResult = await paramBuilder.ExecuteAsync();
}
catch
catch (Exception e)
{
// Unexpected exception
// TODO: Send exception to a logger.
EventLogger.Log(e.Message);
EventLogger.Log(e.StackTrace);
}
}

Expand Down
51 changes: 24 additions & 27 deletions CommunityToolkit.Authentication.Uwp/WindowsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,11 @@ public override async Task SignOutAsync()
{
await _webAccount.SignOutAsync();
}
catch
catch (Exception e)
{
// Failed to remove an account.
EventLogger.Log(e.Message);
EventLogger.Log(e.StackTrace);
}

_webAccount = null;
Expand Down Expand Up @@ -233,7 +235,8 @@ public override async Task<string> GetTokenAsync(bool silentOnly = false, string
}
catch (Exception e)
{
// TODO: Log failure
EventLogger.Log(e.Message);
EventLogger.Log(e.StackTrace);
throw e;
}
finally
Expand Down Expand Up @@ -364,36 +367,29 @@ private async Task SetAccountAsync(WebAccount account)

private async Task<WebTokenRequestResult> AuthenticateSilentAsync(string[] scopes)
{
try
{
WebTokenRequestResult authResult = null;
WebTokenRequestResult authResult = null;

var account = _webAccount;
if (account == null)
{
// Check the cache for an existing user
if (Settings[SettingsKeyAccountId] is string savedAccountId &&
Settings[SettingsKeyProviderId] is string savedProviderId &&
Settings[SettingsKeyProviderAuthority] is string savedProviderAuthority)
{
var savedProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync(savedProviderId, savedProviderAuthority);
account = await WebAuthenticationCoreManager.FindAccountAsync(savedProvider, savedAccountId);
}
}

if (account != null)
var account = _webAccount;
if (account == null)
{
// Check the cache for an existing user
if (Settings[SettingsKeyAccountId] is string savedAccountId &&
Settings[SettingsKeyProviderId] is string savedProviderId &&
Settings[SettingsKeyProviderAuthority] is string savedProviderAuthority)
{
// Prepare a request to get a token.
var webTokenRequest = GetWebTokenRequest(account.WebAccountProvider, _webAccountProviderConfig.ClientId, scopes);
authResult = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(webTokenRequest, account);
var savedProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync(savedProviderId, savedProviderAuthority);
account = await WebAuthenticationCoreManager.FindAccountAsync(savedProvider, savedAccountId);
}

return authResult;
}
catch (HttpRequestException)

if (account != null)
{
throw; /* probably offline, no point continuing to interactive auth */
// Prepare a request to get a token.
var webTokenRequest = GetWebTokenRequest(account.WebAccountProvider, _webAccountProviderConfig.ClientId, scopes);
authResult = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(webTokenRequest, account);
}

return authResult;
}

private Task<WebTokenRequestResult> AuthenticateInteractiveAsync(string[] scopes)
Expand Down Expand Up @@ -528,9 +524,10 @@ async void OnAccountCommandsRequested(AccountsSettingsPane sender, AccountsSetti
var webAccountProvider = webAccountProviderCommandWasInvoked ? await webAccountProviderTaskCompletionSource.Task : null;
return webAccountProvider;
}
catch (TaskCanceledException)
catch (TaskCanceledException e)
{
// The task was cancelled. No provider was chosen.
EventLogger.Log(e.Message);
return null;
}
finally
Expand Down
6 changes: 6 additions & 0 deletions CommunityToolkit.Authentication/BaseProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Net.Http;
using System.Threading.Tasks;
using CommunityToolkit.Authentication.Extensions;
using CommunityToolkit.Authentication.Logging;

namespace CommunityToolkit.Authentication
{
Expand Down Expand Up @@ -34,6 +35,11 @@ protected set
}
}

/// <summary>
/// Gets or sets the logger used to log exceptions and event messages.
/// </summary>
public ILogger EventLogger { get; set; } = DebugLogger.Instance;

/// <inheritdoc />
public abstract string CurrentAccountId { get; }

Expand Down
25 changes: 25 additions & 0 deletions CommunityToolkit.Authentication/Logging/DebugLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics;

namespace CommunityToolkit.Authentication.Logging
{
/// <summary>
/// Logs messages using the <see cref="Debug"/> API.
/// </summary>
public class DebugLogger : ILogger
{
/// <summary>
/// Singleton instance.
/// </summary>
public static readonly DebugLogger Instance = new DebugLogger();

/// <inheritdoc />
public void Log(string message)
{
Debug.WriteLine(message);
}
}
}
18 changes: 18 additions & 0 deletions CommunityToolkit.Authentication/Logging/ILogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace CommunityToolkit.Authentication.Logging
{
/// <summary>
/// Defines a simple logger for handling messages during runtime.
/// </summary>
public interface ILogger
{
/// <summary>
/// Log a message.
/// </summary>
/// <param name="message">The message to log.</param>
void Log(string message);
}
}