Universal Windows Platform (UWP) allows you to write Windows applications that run across different platforms such as Windows 10, Windows 11, HoloLens, Windows Mobile (RIP), and Xbox. In this article, we shall look at how we can implement user authentication in a UWP app using Asgardeo. Even though this article covers only UWP, we can easily adapt the code to integrate Asgardeo with .NET MAUI, WinUI 3, and even Windows Forms applications.
Asgardeo supports the OpenID Connect (OIDC) protocol, so we will be using this protocol to authenticate users. To learn about how you can create an OIDC application in Asgardeo, follow this document. Since we are creating a desktop application, it is better to create a standard-based application in Asgardeo.
To make things easy, we will be using an OIDC SDK to quickly integrate Asgardeo with our app. The SDK I would recommend is IdentityModel.OidcClient which is an OpenID-certified SDK. You can integrate this with your application using the NuGet package manager.
Configuring the SDK
To begin with, we need to pass the necessary configurations to the SDK. To do that, we need to instantiate the “OidcClientOptions” class and set the following properties.
- Authority – This is used by the SDK to send a request to the OIDC discovery endpoint. The SDK composes the discovery endpoint URL by appending “.well-known/openid-configuration” to the value of this property. So, set this property’s value to https://api.asgardeo.io/t/<tenant>/oauth2/token, replacing “<tenant>” with your tenant’s name.
- ClientId – This is the client ID of the OIDC application you created in Asgardeo.
- ClientSecret – This is the client secret of the OIDC application you created in Asgardeo.
- Scope – The scopes you would like to request. To get the ID token, make sure you include “openid”.
- Redirect URI – This is the URI to which Asgardeo should redirect your users after authenticating. In this example, we will be using a scheme URI for this purpose. Let’s see how we can create a scheme URI for our app in a while.
- PostLogoutRedirectUri – This is the URI to which Asgardeo will redirect your users after signing out. Again, we will be using a scheme URI.
- Browser – This should be set to an instance of the “IBrowser” interface. We use this to show Asgardeo’s Single Sign-On page in a browser. Let’s look at how we can implement this interface later.
- Policy – We can use this property to pass additional configurations. In Asgardeo’s case, we need to use this to pass additional endpoint base addresses. The IdentityModel SDK expects all OIDC endpoints to have the Authority endpoint as their base. However, in Asgardeo, there are endpoints with different bases. We can use this property to pass the additional endpoint bases. First, create an instance of the “Policy” class and set its “Discovery” property to an instance of the “DiscoveryPolicy” class. Then set the “AdditionalEndpointBaseAddresses” of the “DiscoveryPolicy” instance to an array consisting of the following endpoint bases. As we did before, replace “<tenant>
” with your tenant’s name. https://api.asgardeo.io/t/<tenant>/oauth2 https://api.asgardeo.io/t/<tenant>/oauth2/token https://api.asgardeo.io/t/<tenant>/oidc
Scheme URI of your UWP
Let’s now discuss how we can define our UWP app’s scheme URI. This is as simple as adding or modifying the “uap:Protocol” tag in the “Package.appxmanifest” file at the root of your app. You can either find or create this tag under “Package”, “Applications”, “Application”, and finally “Extensions”. There should be an “uap:Extension” tag with the “Category” set to “windows.protocol”. If there is none, create one. Inside this tag, create a tag called “uap:Protocol” and set “Name” to your scheme URI. If you choose “sample” as the protocol name, then your scheme URI will be “sample://”. Once you define this and rebuild your application, you will be able to open this application by entering this scheme URI in any browser. A sample configuration is given below:
You can find the “Package.appxmanifest” of a working app with the above configurations here. Now, we can pass this scheme URI as the redirect and post-logout redirect URI to the SDK configurations. But I would like to append a path in case we decide to add deep linking to our app later. So, we can use sample://callback as the redirect URIs.
Implementing the IBrowser interface
We have to do this to allow the SDK to redirect the user to the authorization endpoint and eventually the Single Sign-On page of Asgardeo. Here, we can open a new browser window or tab and redirect the user or we can use a web view. In this example, let’s look at how we can implement the web view. But if you want to open a tab in the default browser, you can find a sample implementation here.
I adapted the code below mostly from the following implementation.
I will not dwell too much on the implementation details as it is beyond the scope of this article, but I will briefly touch upon a few important things. The “InvokeAsync” method is the only method that needs to be implemented and it handles the logic to open the URL in a browser. The “TaskCompletionSource” instance is used to make the process of sending an authorization request and receiving the code an async task. We create an additional method called “ProcessResponse” so that we can call it when Asgardeo redirects the user to the app’s scheme URI.
To call this method on redirection, we need to call this method inside the “OnActivated” method in the “App.xaml.cs” file.
Now, we can pass an instance of this class to the “Browser” property of the “OidcClientOptions” instance.
Adding Sign-In to UWP
We have now come to the business end of the article. Let’s implement the logic to sign users in. But before that, let’s instantiate the “OidcClient” class. To do that, simply pass the instance of the “OidcClientOptions” as the argument into the constructor.
Next, to sign in, call the “LoginAsync” method and pass an instance of the “LoginRequest” class as the argument.
The “_authenticationResult” is an instance of the “LoginResult” class that contains information such as the access token and ID token.
Adding Sign-Out to UWP
To sign out a user, create an instance of the “LogoutRequest” class and set the “IdTokenHint” property to the ID token obtained after authentication and the “BrowserDisplayMode” to “Hidden”. Then, pass this instance to the “LogoutAsync” class to sign the user out. We can also add a conditional check to make sure we don’t destroy the authentication result in case of an error during logout.
That’s it! We can now use Asgardeo in our UWP app to sign in users. You can find the codebase of a working UWP app that uses Asgardeo for authentication here.