5

I'm trying to log in to SharePoint with my Unity app via the MSAL library (Microsoft Identity Platform). When I run it the first time I don’t see a popup at all and there are no errors. (note, I've tried in Editor and as a standalone exe)

However, I did notice after running a second time, I get a popup window entitled Oops with the message Could not register the window class win32 error 0. After some googling I think it might be because there is some kind of dangling window in the background somewhere after the first attempt that I need to somehow clean up. If I restart Unity I can run again with the first time having no error but again no popup window. If I run a second time, of course, I again get the Oops message.

Probably unrelated but worth noting is that if I hit “Ok” on the Oops window I get a null exception error. It seems the AcquireTokenInteractive is trying to open a window which fails, leaving it null, and then tries to get the token from the null.

Any advice to help figure out why the window isn’t presenting would be greatly appreciated

using Microsoft.Identity.Client;

public class MyApp: MonoBehaviour
{
    private string ClientId = "i-am-not-telling";
    private string Tenant = "common";

    void Start()
    {
        SharepointLogin();
    }

    public async void SharepointLogin()
    {
        PublicClientApp = PublicClientApplicationBuilder.Create(ClientId)
                .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
                .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
                .Build();
        IEnumerable<string> scopes = new List<string> { "User.Read" };
        AuthenticationResult result;
        result = await PublicClientApp.AcquireTokenInteractive(scopes)
                        .ExecuteAsync();
    }
}

CodeMonkey
  • 1,795
  • 3
  • 16
  • 46
  • 4
    I am also interested in the answer to this question for a project I would like to do. I have managed to create the same issue in a sample project and can't find a solution so I added a bounty. – Skyler Lauren Jun 10 '20 at 20:25

3 Answers3

0

Have you tried supplying the parent window to the Builder? In Unity it is a bit difficult to get the Window handle, but this code might work and maybe solves the issue.

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern System.IntPtr GetActiveWindow();

public static System.IntPtr GetWindowHandle() {
  return GetActiveWindow();
}

And then call it with WithParentActivityOrWindow

public async void SharepointLogin()
{
    PublicClientApp = PublicClientApplicationBuilder.Create(ClientId)
        .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
        .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
        .WithParentActivityOrWindow(GetWindowHandle)
        .Build();
    IEnumerable<string> scopes = new List<string> { "User.Read" };
    AuthenticationResult result;
    result = await PublicClientApp.AcquireTokenInteractive(scopes)
        .ExecuteAsync();
}
dowhilefor
  • 10,971
  • 3
  • 28
  • 45
  • I've done "FindWindow" from the same dll to obtain an IntPtr and passed in it just like you're showing. I can try with "GetActiveWindow()" and see if that makes any difference though. Who knows, maybe it would return something different?? – CodeMonkey Jun 16 '20 at 12:37
  • Still nothing. :-(. Thanks though! – CodeMonkey Jun 16 '20 at 12:41
0

I believe this is a bug between either Unity or the MSAL library. I will submit bug reports to both and await a fix. This method simply will not work for now. I will have to use a different method to authenticate.

Update from Unity: The problem arises from the System.Windows.Forms that we do not support in Unity. It doesn't seem that this behavior would change in the foreseeable future. On the forums, I've read that adding a System.Windows.Forms.dll to the Plugins folder helped a few users but that doesn't seem to be the case with MSAL. Even if it worked, we wouldn't be responsible for any crashes or errors.

Update from Me: I nixed this method altogether and went with the code here. So far it's only successful with an "on-prem" SharePoint site and I'm trying to obtain support to work with a "SharePoint Online" server. Will likely work for others if you don't have the same Proxy issues I'm likely facing.

CodeMonkey
  • 1,795
  • 3
  • 16
  • 46
0

I discovered needing to ensure calling the interactive browser call in a background thread. Then it worked as expected.

ie.

Task.Factory.StartNew(() =>await app.AcquireTokenInteractive(STORAGE_SCOPES).ExecuteAsync());
Dharman
  • 30,962
  • 25
  • 85
  • 135