web-dev-qa-db-ja.com

'AuthenticationContext.AcquireTokenAsync()'を同期的に待機する方法は?

まず第一に、これが重要かどうかはわかりませんが、@Simon Mourierinで言及されている理由により) 彼の答え、私はADALのEXPERIMENTALビルドを使用しています、これ


以下のコードでは、AuthenticationResultを同期的に取得したいので、AcquireTokenAsyncメソッドによる認証が同期的に完了するのを待ちます。

これは、認証が完了した後にブールフラグを設定する必要があるためです(isAuthorized = true)ただし、tgisは同期的に発生する必要があります。そうでない場合は、AcquireTokenAsyncの呼び出しが終了しなかったため、オブジェクトが終了しなかったため、null参照をスローするクラスの他のメソッドを呼び出すことができます。無効です。

次のコードは機能しません。AcquireTokenAsyncメソッドを呼び出すとスレッドが無期限にフリーズするように見えるため、メソッドは返されません。

C#(オンライン翻訳のために構文が間違っている可能性があります):

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

私は少し調べて、他の2つの選択肢を試しましたが、同じことが起こります。

1位:

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();

2位:

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;
}
6
ElektroStudios

'AuthenticationContext.AcquireTokenAsync()'を同期的に待機する方法は?

この問題は、UIスレッドでasyncメソッドを呼び出すことが原因であると思われます。現在、私の回避策は、呼び出しを新しい作業スレッドにラップすることです。

    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));
        });
    }
8
Jeffrey Chen

Xamarin.Androidでこの問題と2日間戦いました。 AquireTokenAsyncメソッドから戻ることはありません。答えはほとんどコミカルです。 MainActivity.csに以下を追加する必要があります。

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
    }

おかしなことに、実際にはContinuationHelperと書かれています...

5
Kasper

'AuthenticationContext.AcquireTokenAsync()'を同期的に待機する方法は?

AcquireTokenAsync()は「タスク」を返します。 「.Wait()」を使用して待つ必要があります。メインプログラムでは、これを行う必要があります。

Task<AuthenticationResult> res = authContext.AcquireTokenAsync(resourceUri, clientID, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto));
res.Wait();
Console.WriteLine(res.Result.AccessToken);