azuread / microsoft-authentication-extensions-for-dotnet Goto Github PK
View Code? Open in Web Editor NEWSecure cross-platform token cache for MSAL public client apps
License: MIT License
Secure cross-platform token cache for MSAL public client apps
License: MIT License
Encountered by @erich-wang while testing. No known user impact.
Repro steps
Actual: PowerShell hangs. On the desktop session KeyRing displays a window asking the user to unlock the session.
Expected: PowerShell should not hang
Potential fix: detect if the current session is interactive or not (simple to do). If it is not interactive, do not try KeyRing, immediately use the fallback.
In order to have my macOS app to break at the location where an exception is thrown, I enabled a global Exception catchpoint:
Now this causes my app to break every time I call MsalCacheHelper.CreateAsync
because a PlatformNotSupportedException is being thrown internally (see #61).
Is there perhaps a way to prevent the exception to be thrown so my app is not switching into debugging mode?
This is a fallback mechanism in case LibSecret does not work, for example in SSH scenarios. Details here:
MSAL extension should provide encrption/decryption methods for general purpose, it may look like:
byte[] Encrypt(SecureString ); //or return as base64 string?
SecureString Decrypt(byte[] );
Besides token info, we want to protect client secret of service principal as well, currently in Azure PowerShell client secret of service principal is saved as plain text which doesn’t meet secret review. MSAL extension for Python has provided similar functionality, you may find the sample code here
MsalCacheHelper
PublicClientApplication
objects (common scenario - one per authority, one per client id, etc.)PublicClientApplication
call helper.RegisterCache(pca.UserTokenCache)
PublicClientApplication
be garbage collectedActual: the UserTokenCache objects do not get cleanded up leading to a small memory leak.
Note: this is a customer reported problem
The login Keychain is not unlocked when connecting via an SSH session. You can manually do this by running:
security unlock-keychain -p $PASSWORD $KEYCHAIN
..where PASSWORD is the user’s password, and KEYCHAIN is the path to the user’s login Keychain (i.e, /Users//Library/Keychains/login.keychain-db).
It’s not very elegant but does seem to work in my limited testing.
Probably something you could detect (a locked keychain from a remote session), catch the error, and tell the user to manually unlock the login Keychain with that command?
Context
Msal Extension has two ways of achieving the same thing, i.e. providing a token cache:
MsalCacheStorage, a low level access to the persistence level, that is not protected with locks. Developers need to write their own token cache delegates, which they often get wrong.
MsalCacheHelper, a higher level abstraction, which provides token cache delegates that are consistent cross-process.
Problem
Developers tend to choose the lower-level API MsalCacheStorage
. This breaks other libraries or results in high contention, because there are strict rules about file locking, file writing etc. which are not followed.
Proposed Solution
Make MsalCacheStorage
internal. Developers must use MsalCacheHelper
only (example usage here)
There may some functionality that people rely on for MsalCacheStorage
, which we need to capture:
MsalCacheStorage
. This can be fixed by adding Import / Export methods in MsalCacheHelper
When reacting to a cachefile changed event, we create a new PCA and read the cache, looking for added/removed accounts. This isn't behind a CrossPlatLock though, so it can and will try to access the actual cache when it's not available. The fix is to add a CrossPlatLock in the temporary PCA created in that method.
I don't see any documentation, or links to documentation on MSDN, to outline what this library does or what use cases it is intended to help.
Desired behavior
I would like to be able to read the accounts from the cache, even when the user does not have an internet connection. It is my understanding that this functionality works when using MSAL with token caches on other platforms. Is there any reason offline functionality should not be possible with the token cache provided in this repo?
Actual behavior
When I call MsalCacheHelper.CreateAsync
, it throws a HttpRequestException
with the message No such host is known
.
Miscellaneous
I was super excited to try this out instead of doing my own serialization for my UWP app.
But it doesn't work due to code here:
https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/blob/c23dd2c211f88143b583a3dd69e50cc55b8c7e43/src/Shared/SharedUtilities.cs
As it is trying to retrieve information about the OS en
Exception thrown: 'System.PlatformNotSupportedException' in System.Diagnostics.Process.dll
Retrieving information about local processes is not supported on this platform.
The documentation here:
https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization
Isn't very clear about serialization for UWP apps.
It mentions "in-memory" followed "serialization by default". Does that mean that I don't need to serialize to disk for UWP apps (mine is running on a non-mobile platform).
That documentation also states that custom serialization isn't available for UWP, which is odd, because that's precisely what I'm currently doing :)
Signed builds in the output have the DLL marked SHA256: Code Sign Test (DO NOT TRUST).
Following offline talk with Bogdan, we agreed that it is better instead of deprecating the MsalCacheHelper.Clear() method, to change its behavior that it will only clear the cache entries relevant to the specific public client application id that the MsalCacheHelper object was created with, and not whole entries in the cache file itself.
I tried to implement token serialization as described here for my Xamarin.MacOS app. However, I am hitting this exception:
System.PlatformNotSupportedException: Operation is not supported on this platform.
at System.IO.FileSystemWatcher.StartRaisingEvents () [0x00000] in /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs:23
at System.IO.FileSystemWatcher.StartRaisingEventsIfNotDisposed () [0x00019] in /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs:664
at System.IO.FileSystemWatcher.set_EnableRaisingEvents (System.Boolean value) [0x0001d] in /Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac/external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs:163
at (wrapper remoting-invoke-with-check) System.IO.FileSystemWatcher.set_EnableRaisingEvents(bool)
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.CreateAsync (Microsoft.Identity.Client.Extensions.Msal.StorageCreationProperties storageCreationProperties, System.Diagnostics.TraceSource logger) [0x000bc] in <e1855c7c1c93442fa2635ff71c06cc54>:0
My code:
var storageProperties = new StorageCreationPropertiesBuilder("msal_cache.dat", Environment.GetFolderPath(Environment.SpecialFolder.Personal), ClientId)
.WithMacKeyChain("msal_service", "msal_account")
.Build();
var cacheHelper = await MsalCacheHelper.CreateAsync(storageProperties);
I'm trying to test whether token caching works for our desktop app on linux, but I can't do it over ssh. I noticed the wiki states
KeyRings does not work in headless mode (e.g. when connected over SSH or when running Linux in a container) due to a dependency on X11. To overcome this, a fallback to a plaintext file can be configured. See this example for how to configure it.
But when I click the link to the example, I get a github 404 error. Can the wiki please be updated?
@henrik-me @jmprieur -
Can we archive this repo now that the extensions are in the same repo as MSAL ? There is one outstanding PR from Mark and 1-2 issues that we'd need to move.
Hi,
I am trying to acquire Token using certificate to connect Graph API. Its works in console application and local IIS express.
However, when hosted same in IIS it get stuck and timed out.
Code Snippet:
var msalClient = ConfidentialClientApplicationBuilder
.Create(config.ClientID)
.WithCertificate(GetCertificateByThumbprint(config.ApplicationThumbprint))
.WithAuthority(AadAuthorityAudience.AzureAdMyOrg, true)
.WithTenantId(config.TenantID)
.Build();
result = await msalClient.AcquireTokenForClient(scopes).ExecuteAsync(); // **Gets Stuck** - IT DOES EVEN GO TO NEXT STEP
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("bearer", await GetAccessTokenAsync());
var users = await graphClient.Users.Request().Filter($"mail eq '{emailAddress}'").GetAsync();
I have createD ASP.NET MVC for poc and will convert into Web API.
I do not want to use user login token or such... There is no login page and we want to interact MS Graph API using application specific Client ID.
Please some one help on this.
thank you!
Not all Refresh Tokens (RT) are the same. RTs are different after Conditional Access mechanism have been satisfied.
Current locking strategy around AcquireTokenSilent is:
Bug repro
app A begins an AcquireTokenSilent and releases the lock after step 1
app B begins an AcquireTokenInteractive and user resolves CA. An RT with CA claims is saved to the cache.
app A receives new tokens and merges them into the token cache (step 3). This overrides the RT with CA claims.
Actual: RT with CA state should be in the cache
Expected: RT with CA state is deleted
Note: because AcquireTokenInteractive
takes much longer than AcquireTokenSilent
, it is unlikely that this bug will occur
Release build does not have nuget symbol packages for publishing. Need to get those.
The APIs that are being used on MacOS are not deprecated, but are marked as "Legacy" and their use is discouraged.
This may not be an immediate issue, but Apple may deprecate and then remove them in the future, and they don't support more advanced scenarios such as Sharing Access to Keychain Items Among a Collection of Apps.
The P/Invoke also doesn't use utf-8 encoded strings, so may cause issues with non-ascii characters in the service or account names.
We're trying to enable user token caching in our desktop application in OS X. We modeled the caching after the manual test app https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/blob/d32a5a6eb699cc652ca08c477140af1a0a0dbd42/tests/ManualTestApp/Program.cs. However, when running on mac, once we sign in the first time, get a Keychain Access entry and then try to sign in again, we get the error "SecKeychainFindGenericPassword failed with error code -25293" with the following stack trace:
at Microsoft.Identity.Client.Extensions.Msal.MacKeyChain.DeleteKey(String serviceName, String accountName) at Microsoft.Identity.Client.Extensions.Msal.MsalCacheStorage.ClearCore() at Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.RegisterCache(ITokenCache tokenCache)
.
The problem goes away after we manually go into Keychain Access, click on the keychain entry corresponding to our token, and change the Access Control setting to "Allow all applications to access this item". I noticed the wiki mentions this:
Mac offers a more restricted scope, ensuring that only the application that created the cache can access it, and prompting the user if others apps want access.
Does this mean this is the intended behavior? Is there anyway to circumvent this issue that doesn't require users to manually change the Keychain Access Control settings for their entry?
The code in this file: https://github.com/AzureAD/microsoft-authentication-extensions-for-dotnet/blob/master/src/Microsoft.Identity.Client.Extensions.Web/Resource/AadIssuerValidator.cs
is replicated in many MSFT samples using AADv2, aka https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/master/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs
Also, this code is not part of a nuget package, even a preview, at this time.
should one just copy this code into their own project if they want to use the AadIssuerValidator?
We should have automated tests for validating interoperability in between Java, Python, and Node extensions libraries. The tests can live in one repository, as the cache interoperability tests do.
app = PublicClientApplicationBuilder.Create(clientId).WithTenantId(tenant).WithAuthority(authority).Build();
StorageCreationPropertiesBuilder storageCreationPropertiesBuilder = new StorageCreationPropertiesBuilder("tokenCache.dat", "tokencache", clientId).
WithLinuxKeyring("test", "default", "Get Access Token",
new System.Collections.Generic.KeyValuePair<string, string>("Version", "1"),
new System.Collections.Generic.KeyValuePair<string, string>("ProductGroup", "Test")).WithMacKeyChain("Test", "default");
var task = Task.Run(async () => await MsalCacheHelper.CreateAsync(storageCreationPropertiesBuilder.Build()));
MsalCacheHelper msalCacheHelper = task.Result;
try
{
msalCacheHelper.RegisterCache(app.UserTokenCache);
Task<AuthenticationResult> result = app.AcquireTokenByIntegratedWindowsAuth(scopes).WithUsername(username).ExecuteAsync();
Console.Write(result.Result.AccessToken);
}
I am using Microsoft.Identity.Client -> 4.15.0 and Microsoft.Identity.Client.Extensions -> 2.12.0. The issue is that tokencache folder gets created but tokenCache.dat doesnt get created. I am having the DLLs downloaded from the respective Nuget packages and adding them as a Reference in the .NET core console project.
This works absolutelyt fine and cache file gets created If I directly link the package from Nuget package manager. I am not really sure what is happening here. It might not be a bug, but want to see if anyone can help here?
The issue comes from Azure/azure-powershell#14861. Please let us know what needs user's further check? and Is there any workaround.
A similar issue is Azure/azure-powershell#13691. but stack trace is a little different.
Which Version of MSAL are you using ?
Microsoft.Identity.Client.Extensions.Msal 2.16.6.0
Platform
What authentication flow has the issue?
Other? - please describe;
Is this a new or existing app?
Repro
var your = (code) => here;
Expected behavior
A clear and concise description of what you expected to happen (or code).
Actual behavior
A clear and concise description of what happens, e.g. exception is thrown, UI freezes
Possible Solution
Additional context/ Logs / Screenshots
Add any other context about the problem here, such as logs and screebshots.
DEBUG: InteractiveBrowserCredential.Authenticate was unable to retrieve an access token. Scopes: [
https://management.core.windows.net//.default ] ParentRequestId: Exception:
Azure.Identity.AuthenticationFailedException (0x80131500): InteractiveBrowserCredential authentication failed:
Persistence check failed. Inspect inner exception for details
---> Microsoft.Identity.Client.Extensions.Msal.MsalCachePersistenceException (0x80131500): Persistence check failed.
Inspect inner exception for details
---> System.Security.Cryptography.CryptographicException (0x80070000): The operation completed successfully.
WARNING: Unable to acquire token for tenant 'organizations'
WARNING: Please run 'Connect-AzAccount -DeviceCode' if browser is not supported in this session.
DEBUG: Azure.Identity.AuthenticationFailedException: InteractiveBrowserCredential authentication failed: Persistence
check failed. Inspect inner exception for details --->
Microsoft.Identity.Client.Extensions.Msal.MsalCachePersistenceException: Persistence check failed. Inspect inner
exception for details ---> System.Security.Cryptography.CryptographicException: The operation completed successfully.
at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy,
DataProtectionScope scope)
at Microsoft.Identity.Client.Extensions.Msal.DpApiEncryptedFileAccessor.Read()
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheStorage.VerifyPersistence()
--- End of inner exception stack trace ---
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheStorage.VerifyPersistence()
at Azure.Identity.PersistentTokenCache.<GetCacheHelperAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Azure.Identity.PersistentTokenCache.<RegisterCache>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Azure.Identity.MsalClientBase`1.<GetClientAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Azure.Identity.MsalPublicClient.<AcquireTokenInteractiveAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Azure.Identity.InteractiveBrowserCredential.<GetTokenViaBrowserLoginAsync>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Azure.Identity.InteractiveBrowserCredential.<AuthenticateImplAsync>d__30.MoveNext()
--- End of inner exception stack trace ---
at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex)
at Azure.Identity.InteractiveBrowserCredential.<AuthenticateImplAsync>d__30.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Azure.Identity.InteractiveBrowserCredential.<AuthenticateAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.PowerShell.Authenticators.MsalAccessToken.<GetAccessTokenAsync>d__34.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Azure.Commands.Common.Authentication.Factories.AuthenticationFactory.Authenticate(IAzureAccount
account, IAzureEnvironment environment, String tenant, SecureString password, String promptBehavior, Action`1
promptAction, IAzureTokenCache tokenCache, String resourceId)
at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.AcquireAccessToken(IAzureAccount account,
IAzureEnvironment environment, String tenantId, SecureString password, String promptBehavior, Action`1 promptAction)
at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.ListAccountTenants(IAzureAccount account,
IAzureEnvironment environment, SecureString password, String promptBehavior, Action`1 promptAction)
at Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient.Login(IAzureAccount account, IAzureEnvironment
environment, String tenantId, String subscriptionId, String subscriptionName, SecureString password, Boolean
skipValidation, Action`1 promptAction, String name, Boolean shouldPopulateContextList, Int32 maxContextPopulation)
at Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass111_2.<ExecuteCmdlet>b__4()
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at
Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand.<>c__DisplayClass111_0.<ExecuteCmdlet>b__1(AzureRmProfile
localProfile, RMProfileClient profileClient, String name)
Microsoft.Identity.Client.Extensions.TraceSource Error: 0 : An exception was encountered while reading data from the MsalCacheStorage : System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheStorage.ReadData() in /home/bogdan/microsoft-authentication-extensions-for-dotnet/src/Microsoft.Identity.Client.Extensions.Msal/MsalCacheStorage.cs:line 135
Actual: SSO is lost, user needs to re-login
Expected: SSO should not be lost
Solution: instead of overwriting token cache file, just touch it.
Is your feature request related to a problem? Please describe.
I'm used to most other credential manager type functions to use Credential Manager in windows (e.g. git and nuget credential managers both do this on windows IIRC). It seems inherently more secure -- I'm assuming cred manager access is audited, and that permissions are more tightly controlled than they might be in a file system. This feature request might just as well be the question: Why is MSAL using local file storage instead of the credential manager store?
Describe the solution you'd like
Having windows execution use Credential Manager to store tokens.
Describe alternatives you've considered
I think the existing implementation is an alternative, but it seems less secure than using credential manager.
When trying to use MsalCacheHelper
with a ClientId for ADFS which is not a GUID the followoing exception is thrown.
MSAL.NetCore.4.16.1.0.MsalClientException:
ErrorCode: client_id_must_be_guid
Microsoft.Identity.Client.MsalClientException: Error: ClientId is not a Guid.
at Microsoft.Identity.Client.AbstractApplicationBuilder1.Validate()
at Microsoft.Identity.Client.PublicClientApplicationBuilder.Validate()
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.GetAccountIdentifiersAsync(StorageCreationProperties storageCreationProperties, TraceSourceLogger logger)
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.CreateAsync(StorageCreationProperties storageCreationProperties, TraceSource logger)
To reproduce this you can run the following.
StorageCreationProperties storageProperties = new StorageCreationPropertiesBuilder("msal.cache", ".", "AdfsNonGuidClientId").Build();
await MsalCacheHelper.CreateAsync(storageProperties).ConfigureAwait(false);
To work around this issue I'm updating the code to supply a random guid rather than a specific client id. The client id doesn't seem to be necessary as the MsalCacheHelper
only uses it to create a PublicClientApplication
to iterate through the accounts in a serialized cache, in the method GetAccountIdentifiersAsync
I want to use the cache helper to share the cache between my system tray UI app (.NET Framework Desktop app) and my background service (.NET Framework service)
My UI app can read and write my cache file but my system is not able to access it.
Any Hints ?
The three nuget packages need:
By default when an application creates a macOS Keychain item the access control list contains the calling application's identity. This prevents those allow/deny/always allow security prompts when the same application accesses the item.
If an application that is not present in the ACL attempts to read/write the entry the security prompt is shown. Clicking "Deny" obviously declines the access request, and clicking "Allow" permits the operation just-this-time. Clicking "Always Allow" adds a new ACL for the calling application to the item, preventing future prompts.
Given one of the reasons to use this library is to facilitate sharing of a token cache between applications, it would be nice if there was a utility method on the MsalCacheHelper
to forcibly add/ensure the calling application is present on the item's ACL.
The benefit here would be that users are only prompted once and that the option to just "Allow [once]" is not presented.
If there are other ways to avoid this prompt, such as Keychain groups/sharing based on the codesigning team identifier, then that would be even better, but there should be documentation about how to correctly use the library and set up such sharing.
Note that I'm not sure that Keychain groups/sharing is supported on non-iOS/iCloud keychains? There isn't a great deal of documentation from Apple here.
All releases in Azure DevOps for this repo have failed. It looks like the access token for nuget.org is invalid or expired. Example: https://identitydivision.visualstudio.com/IDDP/_releaseProgress?_a=release-environment-logs&releaseId=13686&environmentId=14399
We've received the following build warning for our UWP app which uses Microsoft.Identity.Client 4.22.0
and Microsoft.Identity.Client.Extensions.Msal 2.16.5
.
The app and authentication appears to be working ok, but I wondered if this is a problem, or there is something we need to do to fix the warning?
##[warning]C:\Users\VssAdministrator\.nuget\packages\microsoft.net.native.compiler\2.2.9-rel-29512-01\tools\Microsoft.NetNative.targets(805,5): Warning : MCG : warning MCG0007: Unresolved P/Invoke method 'libsecret-1.so.0!secret_schema_new' for method 'System.IntPtr Microsoft.Identity.Client.Extensions.Msal.Libsecret.secret_schema_new(System.String, System.Int32, System.String, System.Int32, System.String, System.Int32, System.IntPtr)'. Calling this method would throw exception at runtime. Please make sure the P/Invoke either points to a Windows API allowed in UWP applications, or a native DLL that is part of the package. If for some reason your P/Invoke does not satisfy those requirements, please use [DllImport(ExactSpelling=true) to indicate that you understand the implications of using non-UWP APIs.
We receive about 10 similar warnings for different P/Invoke methods related to the package - is the possible runtime exception something we can fix?
Hello, I have a WinForms (legacy) client application that consumes WCF services and uses its own authentication model... (on-premises)
However, the company wants to migrate to Azure and use an app service to host the wcf and authenticate it with Azure AD (JWT).
Do you have any example with this scenario?
winforms + (app service + wcf + azure AD (JWT))
Thank you
We were on .NETCore 3.0 and these versions:
PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="2.15.0"
PackageReference Include="Microsoft.Identity.Client" Version="4.25.0"
Now upgraded to .NETCore 3.1 with the latest:
PackageReference Include="Microsoft.Identity.Client" Version="4.25.0"
PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="2.16.8"
I was not able to see precisely which version broke things because of NuGet pkg downgrade dependency hell.
Msal continues to work prompting for authentication via the browser (and succeeds) but saving to the cache no longer works. A new cache file is created but upon subsequent relaunch of the app the cache no longer succeeds and the user is prompted again.
var user = "unknown";
string domainaccount = WindowsIdentity.GetCurrent().Name;
if (!String.IsNullOrWhiteSpace(domainaccount))
{
var domainaccountSplit = domainaccount.Split('\\');
if (domainaccountSplit.Length >= 2)
{
user = domainaccountSplit[1];
}
}
var myApp_AppData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft\\MyApp");
var storageCreationPropertiesBuilder = new StorageCreationPropertiesBuilder(
$"MyApp.{user}.msalcache.bin3",
myApp_AppData,
MyAppClientAppGuid.ToString()
);
var storageCreationProperties = storageCreationPropertiesBuilder.Build();
var msalCacheHelper = MsalCacheHelper.CreateAsync(storageCreationProperties).GetAwaiter().GetResult();
msalCacheHelper.RegisterCache(app.UserTokenCache);
AuthenticationResult result;
var account = app.GetAccountsAsync().GetAwaiter().GetResult().FirstOrDefault();
try
{
result = app
.AcquireTokenSilent(scopes, account)
.ExecuteAsync()
.GetAwaiter()
.GetResult();
}
catch (MsalUiRequiredException)
{
result = app
.AcquireTokenInteractive(scopes)
.ExecuteAsync()
.GetAwaiter()
.GetResult();
}
return result;
</Code Snippet>
Currently, the top level object requires to be created by passing in a client ID. Internally this is only used to produce the CacheChanged
event, which many consumers do not care about.
We should allow creation of this top level object without a client ID.
Currently if decryption of the cache fails we delete the cache. The same should be true if the cache cannot be deserialized.
If the cache is not deleted then using the cache will cause the public client application to not function since it can never load it off disk and just throws an exception .
For example take a cache, and corrupt it, or just put a space in the file. You should see this exception. You will continue to get this exception until the cache is manually deleted.
'Microsoft.Identity.Client.MsalClientException: MSAL V3 Deserialization failed to parse the cache contents. Is this possibly an earlier format needed for DeserializeMsalV2? (See https://aka.ms/msal-net-3x-cache-breaking-change)
at IDictionary<string, JToken> Microsoft.Identity.Client.Cache.TokenCacheJsonSerializer.Deserialize(byte[] bytes, bool clearExistingCacheData)
at void Microsoft.Identity.Client.TokenCache.Microsoft.Identity.Client.ITokenCacheSerializer.DeserializeMsalV3(byte[] msalV3State, bool shouldClearExistingCache)
at Task<HashSet> Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.GetAccountIdentifiersAsync(StorageCreationProperties storageCreationProperties)+(TokenCacheNotificationArgs args) => { }
at async Task Microsoft.Identity.Client.TokenCache.Microsoft.Identity.Client.ITokenCacheInternal.OnBeforeAccessAsync(TokenCacheNotificationArgs args)
at async Task Microsoft.Identity.Client.Cache.CacheSessionManager.RefreshCacheForReadOperationsAsync(TokenTypes cacheEventType)
at async Task<IEnumerable> Microsoft.Identity.Client.Cache.CacheSessionManager.GetAccountsAsync(string authority)
at async Task<IEnumerable> Microsoft.Identity.Client.ClientApplicationBase.GetAccountsAsync()
at async Task<HashSet> Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.GetAccountIdentifiersAsync(StorageCreationProperties storageCreationProperties)
at async Task Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.CreateAsync(StorageCreationProperties storageCreationProperties, TraceSource logger)
Right now FallBackAuthority and AzureADIssuerMetadataUrl are hardcoded. Can you make these configurable with defaults to the most common one?
var cacheHelper = await MsalCacheHelper.CreateAsync(storageProperties).ConfigureAwait(false);
Produces a null ref on Xamarin.Mac only.
Workaround - use a TraceSource for logging:
var cacheHelper = await MsalCacheHelper.CreateAsync(storageProperties, new TraceSource("my_app_token_cache")).ConfigureAwait(false);
Current locking strategy around AcquireTokenSilent
is:
This exposes the possibility of:
AcquireTokenSilent
and releases the lock after step 1Actual: the current user is still logged in
Expected: the current user should be logged out
For some reason, when installing the NuGet package in a .NET Core console app, a link to the package's License file appears under the .csproj.
When trying to remove this link, I get the following message:
Examining this file reveals the following section which adds the link to the License file:
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<None Include="$(NuGetPackageRoot)microsoft.identity.client.extensions.msal\2.1.0-preview\contentFiles\any\netcoreapp2.1\LICENSE" Condition="Exists('$(NuGetPackageRoot)microsoft.identity.client.extensions.msal\2.1.0-preview\contentFiles\any\netcoreapp2.1\LICENSE')">
<NuGetPackageId>Microsoft.Identity.Client.Extensions.Msal</NuGetPackageId>
<NuGetPackageVersion>2.1.0-preview</NuGetPackageVersion>
<NuGetItemType>None</NuGetItemType>
<Private>False</Private>
<Link>LICENSE</Link>
</None>
</ItemGroup>
Is this intentional? I believe it is a bug and not a feature.
I tried on both VS2017 and VS2019 Preview.
When multiple threads / two processes use the MsalCacheHelper, it throws the following exception:
System.InvalidOperationException: Could not get access to the shared lock file. ---> System.IO.IOException: The process cannot access the file 'C:\Users\yosefd\AppData\Roaming\Kusto\userTokenCache.data.lockfile' because it is being used by another process.
We experienced this via a command line tool we have. When it runs for enough time, sporadically, authentication pop-ups appear and if not confirmed, the connection fails on timeout. Each time there is a pop-up, we see that exception.
More background about how we’re reproducing the error:
This happened on Windows 10, both when Kusto Explorer (another tool of ours that uses the MsalCacheHeper) was running and also when it was not running. The exception happens in the context of that command-line tool, and not Kusto Explorer. The tool that hits these exceptions was running alone (one process). It had many concurrent threads, about 150, and all were performing remote calls.
the following line in CrossPlatLock.cs
does not work on UWP and results in a SystemException: Retrieving information about local processes is not supported on this platform.
writer.WriteLine($"{Process.GetCurrentProcess().Id} {Process.GetCurrentProcess().ProcessName}");
Actual:
An exception of type 'System.DllNotFoundException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'Unable to load shared library 'libsecret-1.so.0' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibsecret-1.so.0: cannot open shared object file: No such file or directory'
at Microsoft.Identity.Client.Extensions.Msal.Libsecret.secret_schema_new(String name, Int32 flags, String attribute1, Int32 attribute1Type, String attribute2, Int32 attribute2Type, IntPtr end)
at Microsoft.Identity.Client.Extensions.Msal.CacheAccessorLinux.GetLibsecretSchema() in /home/bogdan/microsoft-authentication-extensions-for-dotnet/src/Microsoft.Identity.Client.Extensions.Msal/Os/Linux/CacheAccessorLinux.cs:line 148
at Microsoft.Identity.Client.Extensions.Msal.CacheAccessorLinux.Clear() in /home/bogdan/microsoft-authentication-extensions-for-dotnet/src/Microsoft.Identity.Client.Extensions.Msal/Os/Linux/CacheAccessorLinux.cs:line 31
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheStorage.ReadData() in /home/bogdan/microsoft-authentication-extensions-for-dotnet/src/Microsoft.Identity.Client.Extensions.Msal/MsalCacheStorage.cs:line 140
at Microsoft.Identity.Client.Extensions.Msal.MsalCacheHelper.RegisterCache(ITokenCache tokenCache) in /home/bogdan/microsoft-authentication-extensions-for-dotnet/src/Microsoft.Identity.Client.Extensions.Msal/MsalCacheHelper.cs:line 242
at ManualTestApp.Program.d__4.MoveNext() in /home/bogdan/microsoft-authentication-extensions-for-dotnet/tests/ManualTestApp/Program.cs:line 223
Taking to account that file locks are not completely reliable on non Win platforms, It would be nice to implement following features to be race conditions resilient:
details can be found here -> https://github.com/AzureAD/microsoft-authentication-extensions-for-java/wiki/Race-conditions
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.