I have SharePoint online site that uses Multi Factor Authentication: I am presented with a login screen where I supply my username and password. After this I am taken to another popup where I can choose a second authentication method like Microsoft Authenticator, RSA Token, or Smartcard etc.
The idea behind my WinForm app is to also authenticate in the same way described above and once authenticated I will perform some actions on the SharePoint site (see WebFullUrl below) with my WinForm app. My knowledge is rather limited but I understand that I need to get a token before actually gaining access to the site. Please feel free to correct me where you can. :)
The biggest issue I am facing at the moment is for my app to get a token. This is my project until now.
using System.Security.Principal;
using System.Security;
using System.Diagnostics;
using PnP.Framework;
using Microsoft.SharePoint.Client;
using Microsoft.Graph;
using System.Globalization;
using Microsoft.Identity.Client;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Formats.Asn1.AsnWriter;
using System.Windows.Interop;
using Microsoft.AspNetCore.Components;
using Microsoft.IdentityModel.Abstractions;
namespace AuthDemoWinForms
{
public partial class MainForm : System.Windows.Forms.Form
{
private static readonly string[] scopesArray = ["User.Read", "Contacts.Read"];
private static readonly string Username = "[email protected]";
private static readonly string Password = "ThisIsMyPassword";
private static readonly string AuthEndPoint = "https://login.microsoftonline.com/common/oauth2/token";
private static readonly string ClientId = "00000003-0000-0ff1-ce00-000000000000";
private static IPublicClientApplication? SharePointApplication = null;
private static readonly string WebFullUrl = "https://domainname.sharepoint.com/teams/DEFILES/Shared%20Documents/Forms/AllItems.aspx";
public MainForm()
{
InitializeComponent();
SharePointApplication = PublicClientApplicationBuilder.Create(ClientId)
.WithDefaultRedirectUri()
.WithLogging(new IdentityLogger(EventLogLevel.Warning), enablePiiLogging: false)
.Build();
}
private void LoginButton_Click(object sender, EventArgs e)
{
if (SharePointApplication != null)
{
Task<AuthenticationResult?> authenticationResultTask = GetTokenInteractively(SharePointApplication);
authenticationResultTask.Wait();
AuthenticationResult? authenticationResult = authenticationResultTask.Result;
OutputTextBox.Text = authenticationResult == null ? string.Empty : authenticationResult.Account.Username;
}
}
private static async Task<AuthenticationResult?> GetTokenInteractively(IPublicClientApplication? publicClientApplication)
{
try
{
return await publicClientApplication!.AcquireTokenInteractive(scopesArray)
.WithParentActivityOrWindow(new WindowInteropHelper(System.Windows.Application.Current.MainWindow))
.ExecuteAsync();
}
catch (Exception ex)
{
Debug.WriteLine($"InnerException : {ex.InnerException}\nMessage : {ex.Message}\nStackTrace : {ex.StackTrace}");
return null;
}
}
private static async Task<AuthenticationResult?> Login()
{
try
{
}
catch (Exception ex)
{
}
return null;
}
}
}
I have a question regarding .WithParentActivityOrWindow(new WindowInteropHelper(System.Windows.Application.Current.MainWindow)).
Will this present me with the Authentication Popup or do I need to still build a Dialogue that will handle this? Also, where and when do I need to enter my username and password?
As extra remark, it appears as if the Async Task doesn't finalise.
I am lost!
Initially, I registered one Azure AD application and granted SharePoint API permissions with admin consent:
Make sure to add redirect URI in Mobile and desktop applications platform and enable public client applications like this:
Form1.cs:
Form1.Designer.cs:
When I ran the WinForms application and clicked on
Loginbutton, pop-up window appeared to sign in like this:If MFA is enabled for user, it will ask for two-factor authentication based on configured method:
After successful authentication, it displayed below screen with signed-in Azure AD username, along with access token value:
To confirm that, you can decode the access token by pasting it in jwt.ms website and check
aud&scpclaims to validate permissions:I have one SharePoint site named
sritestsite10with below files in Shared Documents folder:When I used generated token to call SharePoint API in Postman with below query, I got response with files details successfully like this:
Response:
Reference: Modern authentication with Azure AD for WinForms (native) apps (cmatskas.com) by C Matkas