-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #192 from MartinZikmund/feature/msal
MSAL
- Loading branch information
Showing
24 changed files
with
387 additions
and
245 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/app/MZikmund/Services/Account/AuthenticationConstants.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace MZikmund.Services.Account; | ||
|
||
public static class AuthenticationConstants | ||
{ | ||
public const string ApplicationId = "7e13557a-4799-46b8-9e2b-0f31c41a051e"; | ||
|
||
public const string TenantId = "4e973842-1a98-40ec-9542-3c2019f0fb8e"; | ||
|
||
public static string[] DefaultScopes { get; } = new string[] | ||
{ | ||
"api://862d5839-f30f-41a9-ab6f-ff7eef19342c/access_as_user", | ||
"user.read", | ||
"profile", | ||
"offline_access" | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace MZikmund.Services.Account; | ||
|
||
public class AuthenticationInfo | ||
{ | ||
public required string DisplayName { get; init; } | ||
|
||
public required DateTimeOffset ExpiresOn { get; init; } | ||
|
||
public required string Token { get; init; } | ||
|
||
public required string UserId { get; init; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
using Microsoft.Identity.Client; | ||
using Uno.UI.MSAL; | ||
using MZikmund.Services.Preferences; | ||
using Microsoft.Identity.Client.Extensions.Msal; | ||
using System.Diagnostics; | ||
using System.Diagnostics.CodeAnalysis; | ||
|
||
namespace MZikmund.Services.Account; | ||
|
||
public class UserService : IUserService | ||
{ | ||
private IPublicClientApplication? _identityClient; | ||
private AuthenticationInfo? _authenticationInfo; | ||
|
||
public UserService() | ||
{ | ||
} | ||
|
||
public bool IsLoggedIn => _authenticationInfo != null; | ||
|
||
public string? UserName => _authenticationInfo?.DisplayName; | ||
|
||
public bool NeedsRefresh => _authenticationInfo?.ExpiresOn < DateTimeOffset.UtcNow.AddMinutes(-5); | ||
|
||
public string? AccessToken => _authenticationInfo?.Token; | ||
|
||
public async Task AuthenticateAsync() | ||
{ | ||
if (IsLoggedIn && !NeedsRefresh) | ||
{ | ||
return; | ||
} | ||
|
||
await EnsureIdentityClientAsync(); | ||
|
||
var accounts = await _identityClient.GetAccountsAsync(); | ||
AuthenticationResult? result = null; | ||
bool tryInteractiveLogin = false; | ||
|
||
try | ||
{ | ||
result = await _identityClient | ||
.AcquireTokenSilent(AuthenticationConstants.DefaultScopes, accounts.FirstOrDefault()) | ||
.ExecuteAsync(); | ||
} | ||
catch (MsalUiRequiredException) | ||
{ | ||
tryInteractiveLogin = true; | ||
} | ||
catch (Exception ex) | ||
{ | ||
Debug.WriteLine($"MSAL Silent Error: {ex.Message}"); | ||
} | ||
|
||
if (tryInteractiveLogin) | ||
{ | ||
try | ||
{ | ||
result = await _identityClient | ||
.AcquireTokenInteractive(AuthenticationConstants.DefaultScopes) | ||
.ExecuteAsync(); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Debug.WriteLine($"MSAL Interactive Error: {ex.Message}"); | ||
} | ||
} | ||
|
||
_authenticationInfo = new AuthenticationInfo | ||
{ | ||
DisplayName = result?.Account?.Username ?? "", | ||
ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue, | ||
Token = result?.AccessToken ?? "", | ||
UserId = result?.Account?.Username ?? "" | ||
}; | ||
} | ||
|
||
[MemberNotNull(nameof(_identityClient))] | ||
private async Task EnsureIdentityClientAsync() | ||
{ | ||
if (_identityClient == null) | ||
{ | ||
#if __ANDROID__ | ||
_identityClient = PublicClientApplicationBuilder | ||
.Create(AuthenticationConstants.ApplicationId) | ||
.WithAuthority(AzureCloudInstance.AzurePublic, AuthenticationConstants.TenantId) | ||
.WithRedirectUri($"msal{AuthenticationConstants.ApplicationId}://auth") | ||
.WithParentActivityOrWindow(() => ContextHelper.Current) | ||
.Build(); | ||
|
||
await Task.CompletedTask; | ||
#elif __IOS__ | ||
_identityClient = PublicClientApplicationBuilder | ||
.Create(AuthenticationConstants.ApplicationId) | ||
.WithAuthority(AzureCloudInstance.AzurePublic, AuthenticationConstants.TenantId) | ||
.WithIosKeychainSecurityGroup("com.microsoft.adalcache") | ||
.WithRedirectUri($"msal{AuthenticationConstants.ApplicationId}://auth") | ||
.Build(); | ||
|
||
await Task.CompletedTask; | ||
#else | ||
_identityClient = PublicClientApplicationBuilder | ||
.Create(AuthenticationConstants.ApplicationId) | ||
.WithAuthority(AzureCloudInstance.AzurePublic, AuthenticationConstants.TenantId) | ||
.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") | ||
.WithUnoHelpers() | ||
.Build(); | ||
|
||
await AttachTokenCacheAsync(); | ||
#endif | ||
} | ||
} | ||
|
||
#if !__ANDROID__ && !__IOS__ | ||
private async Task AttachTokenCacheAsync() | ||
{ | ||
#if !HAS_UNO | ||
// Cache configuration and hook-up to public application. Refer to https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/wiki/Cross-platform-Token-Cache#configuring-the-token-cache | ||
var storageProperties = new StorageCreationPropertiesBuilder("msal.cache", ApplicationData.Current.LocalFolder.Path) | ||
.Build(); | ||
|
||
var msalcachehelper = await MsalCacheHelper.CreateAsync(storageProperties); | ||
msalcachehelper.RegisterCache(_identityClient!.UserTokenCache); | ||
#else | ||
await Task.CompletedTask; | ||
#endif | ||
} | ||
#endif | ||
} |
Oops, something went wrong.