First of all, I'm not sure if this is important, but for the reasons mentioned by @Simon Mourier in him answer, I'm using the EXPERIMENTAL build of ADAL, this one.
In the code below, I would like to retrieve an AuthenticationResult
synchronouslly, so, I will wait for completition of the authentication by AcquireTokenAsync
method in a synchronous manner.
This is because a boolean flag should be set after the authorization is done (isAuthorized = true
), but tgis need to happen in a synchronous way, because if not, then I can call other methods of the class that will throw a null reference because the call to AcquireTokenAsync
didn't finished so the object is null.
The following code does not work, the method will never return, because the call to AcquireTokenAsync
method seems that indefinitely freezes the thread.
C# (maybe wrong syntax due to online translation):
public void Authorize() {
// Use the 'Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory' Nuget package for auth.
this.authContext = new AuthenticationContext(this.authUrl, this.cache);
this.authResult = this.authContext.AcquireTokenAsync({ "https://outlook.office.com/mail.readwrite" },
null, this.clientIdB, this.redirectUriB,
new PlatformParameters(PromptBehavior.Auto, this.windowHandleB)).Result;
// Use the 'Microsoft.Office365.OutlookServices-V2.0' Nuget package from now on.
this.client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), () => Task.FromResult(this.authResult.Token));
this.isAuthorizedB = true;
}
VB.NET:
Public Sub Authorize()
' Use the 'Microsoft.Experimental.IdentityModel.Clients.ActiveDirectory' Nuget package for auth.
Me.authContext = New AuthenticationContext(Me.authUrl, Me.cache)
Me.authResult =
Me.authContext.AcquireTokenAsync({"https://outlook.office.com/mail.readwrite"},
Nothing, Me.clientIdB, Me.redirectUriB,
New PlatformParameters(PromptBehavior.Auto, Me.windowHandleB)).Result
' Use the 'Microsoft.Office365.OutlookServices-V2.0' Nuget package from now on.
Me.client = New OutlookServicesClient(New Uri("https://outlook.office.com/api/v2.0"),
Function() Task.FromResult(Me.authResult.Token))
Me.isAuthorizedB = True
End Sub
I researched a little bit and I tried other two alternatives, but happens the same..
1st:
ConfiguredTaskAwaitable<AuthenticationResult> t = this.authContext.AcquireTokenAsync(scopeUrls.ToArray(), null, this.clientIdB, this.redirectUriB, new PlatformParameters(PromptBehavior.Auto, this.windowHandleB)).ConfigureAwait(false);
this.authResult = t.GetAwaiter.GetResult();
2nd:
this.authResult == RunSync(() => { return this.authContext.AcquireTokenAsync(scopeUrls.ToArray(), null, this.clientIdB, this.redirectUriB, new PlatformParameters(PromptBehavior.Auto, this.windowHandleB)); })
private AuthenticationResult RunSync<AuthenticationResult>(Func<Task<AuthenticationResult>> func)
{
return Task.Run(func).Result;
}
How to wait for 'AuthenticationContext.AcquireTokenAsync()' synchronouslly?
I suspect this issue is caused by calling the async method in the UI thread. Currently, my workaround is wrapping the call a new work thread.
private void button1_Click(object sender, EventArgs e)
{
Authorize().Wait();
}
private Task Authorize()
{
return Task.Run(async () => {
var authContext = new AuthenticationContext("https://login.microsoftonline.com/common");
var authResult = await authContext.AcquireTokenAsync
(new string[] { "https://outlook.office.com/mail.readwrite" },
null,
"{client_id}",
new Uri("urn:ietf:wg:oauth:2.0:oob"),
new PlatformParameters(PromptBehavior.Auto, null));
});
}