In this article, let’s try to setup authentication in .NET Core WPF application. Let’s use Azure AD and MSAL for this setup.
I promise there are going to be some interesting findings.
Azure AD
In this section, let’s have look at what the configurations required to register a WPF application. Please note that although the app registrations would be performed in below steps, the actual WPF application has not been created yet.
App Registration
Sign in to Azure portal and go to the top right corner and Select Azure Active Directory from the left navigation.
Next, go to App registrations and then click on New registration to register the WPF app in Azure.
Enter below inputs:
- Name, a display name for the app registration
- Supported account type, to confirm which accounts can be used to login to the application. Keep it to default for this demo.
- Platform Configuration, make sure you select
client application (Web, iOS, Android, Desktop + Devices
option.
Then click on Register button to register our new application in Azure AD.
Know More about Redirect URI
The redirect URI is an interesting input here. As we know, we are trying to register a WPF application, not a web application. So, how can it have an URI ?
So, if you take a look at the documentation here, it tells us how the redirect URIs should be set for the UWP, .NET Framework and .NET Core applications. Below is the image from the documentation
- UWP, for these applications, the redirect URI should be set to
https://login.microsoftonline.com/common/oauth2/nativeclient
- .NET Framework, for these applications, the redirect URI should be set to the return value of
WebAuthenticationBroker.GetCurrentApplicationCallbackUri()
- .NET Core, this should be set to
https://localhost
ORhttp://localhost
If you use .NET framework application, the application opens a popup which shows login screen from Azure AD. But things are not the same for .NET Core application.
For .NET Core application, the system browser is used for redirecting user to Azure AD login screen. It means when we create WPF application, and we click on login button from our application, it will open the default browser on our machine (either edge or chrome, or Mozilla, whatever is the default browser is).
I am talking about Microsoft.Identity.Client v4.14.0. And as per documentation, for .NET Core, we are setting the value to the local host to enable the user to use the system browser for interactive authentication since .NET Core does not have a UI for the embedded web view at the moment.
Additional limitations are documented here.
How does it work ?
MSAL needs to listen on on http://localhost:port
and intercept the code that AAD sends when the user is done authenticating.
So, in app registration, we can specify http://localhost
in the redirect URI without any port in it. Then while setting up the Public Client Application, we need to specify the same.
MSAL will find the random available port and will use it.
Application Authentication
Now, let’s open the newly configuration application “Sample Wpf App” from the app registrations list. Then select Authentication option from the left navigation. Then select Add a platform button.
This button will open new panel on right side, asking for type of platform. Select the Mobile and Desktop applications from the options.
Then a new panel will open which will ask to select the redirect URI. Instead of selecting any check boxes, enter a custom URI. Enter http://localhost
in the custom redirect URI text box. Then click on Configure button.
Note, that we are using HTTP scheme and not HTTPS, because it is not supported yet.
Then hit Save button to save these configurations.
WPF App
In Visual Studio, create a .NET Core WPF application. In this application, we need to setup few things:
- Add reference to Microsoft.Identity.Client NuGet package
- The configurations related to app registration in Azure AD
- The code to create PublicClientApplication instance and use it for logging in and logging out the user
In this demo, we will try to display the details of the token (like the user for whom it was issued and its expiry time), just to make sure that even though the authentication is happening outside, the application still gets the token.
App Configurations
In this app, I am just going to hard code few constants, for holding the authority information, client id, user flow names, redirect URIs.
Then using those values, PublicClientApplication instance is being created in below code snippet. All of the above things are present in app.xaml.cs
.
Token Cache
The token cache implementation below, simply tries to write the token to the file system and reads it back whenever required.
Sign In/Out Code
The below code snippet shows code for signing in and signing out the user. In addition, there is also code to display the details inside the token.
There is additional code to render the text box and toggling the display of sign in and sign out buttons based on current state of user.
Run and Verify
Now, when you run the application, it will show screen with Login button. If user clicks on the button, the system browser will open and will redirect user to the Azure AD and will show the login screen.
User can enter credentials and after successful login, the MSAL will receive the token from Azure AD as it is listening to the same port. Thus the application will show user details in the text box as shown below.
Below image shows the edge browser and our WPF application behind it.
Please note that when you sign out, and sign in again, the browser may show that you are still signed in. This is because, the browser is performing the authentication and keeping the authentication result with it. I could not find any way to clear this from browser. Did you find any way to ?
Let me know your thoughts.
Excellent article. Simple and easy to understand. i am expriancing the same issue with clearing browser holding authentication result from last sign in when signing out. Did you find any way to do that?
There can be various reasons and the reasons depend on how / where you cache the token. One thing you may try – I think it may be getting saved in windows user-specific folder somewhere, because at the time of login you have the token cached there, it generally does not ask for creds again.
I implement the solution but it skiping the MFA which is enabled on azure ad for user. If user trying to visit azure porti then MFA cames in action but with above solution the MFA not come to action. Please help me
Thank you! Worked first time and followed lots of searching. This is what the internet needs: simple, minimalist, up-to-date and working examples, not examples with too many frills and confusing complexity.
I got the same code to work in a console app (just removed the async/await [with .Result on ExecuteAsync()].
With WPF, the MS window that popped up was a clean tool-type window with an account selector, but with the console app, the default browser appeared, and with the message you show above. No doubt there is a way to customise that browser page.
Great to know that this article is helping readers. Cheers !