MicrosoftDocs / WindowsCommunityToolkitDocs

Creative Commons Attribution 4.0 International
174 stars 154 forks source link

MSAL Login loads then dismisses failing to login but no error #593

Open TheJoeFin opened 2 years ago

TheJoeFin commented 2 years ago

I am using MSAL authentication to connect to OneDrive and save files for my app. Recently I found the login no longer works. I was just testing the app and it worked well because I was already logged in, but the login process stopped working.

Steps:

  1. Click "Login" button (provided by the toolkit)
  2. Account selection window appears
  3. Pick account and click continue
  4. Next page loads
  5. Window dismisses with no error
  6. Not logged in

Where is the possible source of this issue and should the provider catch this scenario because I can see how this would be very frustrating for my users when they cannot login to the app to save and load their data to OneDrive.

TheJoeFin commented 2 years ago

Here is a video showing the error

https://user-images.githubusercontent.com/7809853/145240865-fa1351c7-2cbf-45da-9e7c-7de4f5b7ee36.mp4

.

michael-hawker commented 2 years ago

@TheJoeFin are you using the toolkit helpers to perform the login? Can you provide more info about what your OS version is and what version of the packages you're using? FYI @shweaver-MSFT

TheJoeFin commented 2 years ago

@michael-hawker Thank you for the quick response! I'm on a Surface Go 2 running Windows 11 Build 22000.348

The app has the following toolkit packages: v7.1.1 of: CommunityToolkit.Authentication.Msal CommunityToolkit.Graph.Uwp v7.1.2 of: Microsoft.Toolkit.Uwp Microsoft.Toolkit.Connectivity Microsoft.Toolkit.Uwp.Notifications Microsoft.Toolkit..Uwp.UI Microsoft.Toolkit..Uwp.UIControls

This is the production app and I upgraded the packages to the latest yesterday and had the same problem

michael-hawker commented 2 years ago

Thanks for the info @TheJoeFin. Does it only happen in your app or other apps as well? Like I wonder if you can see if the Contoso Notes sample is working for you on the same machine?

Otherwise, I'm hoping @shweaver-MSFT could point out if there's some error condition we can grab somewhere to get more details?

@TheJoeFin do you see any uncaught exceptions happening anywhere during the login process?

shweaver-MSFT commented 2 years ago

My guess is this is a redirect uri issue. Perhaps a mismatch between the way the MsalProvider is being configured and what's in the Azure app registration. Check the Authentication page in the app registration to compare it to the code.

It could also be an issue with invalid scopes. Check that you aren't accidentally requesting any AAD exclusive scopes for MSA users, such as any scope that ends with .All. Bad scopes will also cause the authorization prompt to fail.

I'll make an issue to improve the logging experience. I think we're eating Msal exceptions, so it's not very easy to troubleshoot at the moment.

TheJoeFin commented 2 years ago

@michael-hawker I'm not getting any exceptions or any details in the output. I'll build the notes sample and test that tonight.

@shweaver-MSFT I haven't changed any scopes, none of them have the .all scope. When you say a mismatch are you suggesting clientId in the app doesn't match the Azure AD Application (Client) ID? Or is there a different mismatch I should investigate?

Some more logging would be helpful since this portion of the app does go beyond my app. It is difficult for me to see if there is something I've done/configured wrong or if there is an error on Azure, or locally on device, or something else.

TheJoeFin commented 2 years ago

More strange stuff. It looks like the LoginButton is trying a Windows Provider instead of the MSAL Provider. Strange. And when I make another button to get the graphClient using this call:

PublicClientApp = PublicClientApplicationBuilder.Create(ClientID)
                .WithAuthority(Authority)
                .WithUseCorporateNetwork(false)
                .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
                .Build();

The login window pops up like before, I login and the window crashes: image

Clicking "Close the program" crashes the app, but when restarting the app it is logged in and works correctly. Confused what is going on. Did something change where the LoginButton from CommunityToolkit.Graph.Uwp.Controls only works with Windows Provider?

Later I pulled out the MSAL code and just used the WindowsProvider like in the ContosoNotes sample. This is working well. The only problem for now is testing to make sure this changes doesn't move where the app looks for files in the "AppFolder"

For now I've moved beyond this issue, but I do wonder if there is something strange going on with the LoginButton

TheJoeFin commented 2 years ago

Welp. After several days of frustrating work, I believe I figured it out. To use LoginButton the User.Read scope is required. I think adding this to the documentation would be the easiest fix, next would be a more helpful error message.

Not sure when that scope dropped from my app or if anything else changed 🤷‍♂️. Anyway glad to know what was causing me trouble. Hopefully adding a small note to the docs will help a future someone.

shweaver-MSFT commented 2 years ago

Well hey! I'm glad you figured it out :) That's a tough one to catch. Yes, User.Read is required so we can grab the user's profile info to display in the button. Thanks for the PR too, we should definitely have the required scopes documented 👍

michael-hawker commented 2 years ago

@TheJoeFin sorry for all the trouble, but really appreciate you sticking with it and finding out the root cause. That'll help us all in the future for sure! 🦙❤

@shweaver-MSFT does the platform give us any better info about scope failures? Should that be related to https://github.com/CommunityToolkit/Graph-Controls/issues/179 or a separate issue?

shweaver-MSFT commented 2 years ago

@michael-hawker the error messages don't tend to be so explicit as to really describe the problem. Usually it's 403 forbidden, your service is configured incorrectly, or something similar. But you found the right issue. I made CommunityToolkit/Graph-Controls#179 to try and help with troubleshooting provider config.

TheJoeFin commented 2 years ago

Coming back to this issue after still fighting with all of these Graph authentication problems.

I decided to return to using the MSAL Provider because if I switch to the Windows Provider the previous "AppFolder" within OneDrive does not get identified and a new (empty) one gets created. This could cause issues with users syncing their data between devices.

So while continuing to dig into this issue I cloned, fixed, and built the Contoso Notes sample app and when using the MSAL provider, it had the same failure. Not sure what is causing this error, and I'm still getting no errors just a dismissal of the box like shown in the initial video.

It seems like there has been a change in app behavior when using the MSAL provider. It used to pop up a window where I type in my email and then it would authenticate. Now the MSAL uses the Windows account picker, Why does that happen? Is there something that changed to always default to using a Windows Provider even when using the MSAL Provider?

Any clarity would be appreciated.

michael-hawker commented 2 years ago

@TheJoeFin I believe MSAL itself has a mechanism for auto-switching over to the Windows Provider. Not sure if that was recently added or not. @shweaver-MSFT knows a few more details here.

I would have that the application folder would have been tied to the client id and not which provider is used though... wonder if that's a bug we need to be filing somewhere with one of the sdk teams? Shane, thoughts?

shweaver-MSFT commented 2 years ago

Ah, yes @TheJoeFin you are correct. There was a change in functionality a while back to enable the MsalProvider to leverage the account broker in Windows. I liked this as the default experience, because the account broker will pick up any locally configured accounts on the OS, where the web-based UI won't. This is the ideal path for integrating with MSA on Windows, native prompts showing native accounts.

Now there is an interesting difference in the way the two auth providers work, MsalProvider uses the app registration data, driven by the client id from the Azure app registration. The WindowsProvider, however, uses the association with the Microsoft Store to enable access to MS identity services. Based on this it makes sense to me that switching between the providers would yield slightly different results because One Drive creates dedicated app folders based on the app's connection to identity services. There appears to be a difference in how this is handled based upon whether the app is connected through Azure or the Microsoft Store.

If you want to restore the old functionality (not using the Windows account broker) you'll have to configure the PublicClientApplication yourself and pass it to the MsalProvider constructor. This gives you full control to configure it however you like.

// Pass in your pre-configured PublicClientApplication instance.
public MsalProvider(IPublicClientApplication client, string[] scopes = null, bool autoSignIn = true)
{
    ...

Here is the function that configures the PublicClientApplitcation in MsalProvider. This way you at least have a reference. The important bit to remove is here:

#if WINDOWS_UWP || NET5_0_WINDOWS10_0_17763_0
    clientBuilder = clientBuilder.WithBroker();
#elif NETCOREAPP3_1
    clientBuilder = clientBuilder.WithWindowsBroker();
#endif
TheJoeFin commented 2 years ago

Thank you so much for the detailed response @shweaver-MSFT! I'll try these code changes this weekend