先前正常运行的ADAL.net代码现在会生成“ ErrorParsingWsTrustResponse”错误

时间:2018-07-30 16:59:15

标签: c# .net azure-active-directory adal

我遇到了一个看起来有点像this one的问题,但是我在一个稍有不同的环境中遇到了这个问题,除了“尝试使用一个不同的身份验证流程”,我认为这对我不起作用。

我在Azure中托管了一个Web API,并使用活动目录承载令牌进行保护。作为VSTS构建/发布流程的一部分,我希望能够对此进行一些自动化集成测试。

为此,我的第一步是构建一个使用AD本机应用程序的控制台应用程序,这样我就可以使用非交互式身份验证流程,并且在上周末,该代码似乎可以正常工作。相关代码为:

private async Task<string> GetToken(string username, string password)
{
    string resourceId = <application ID of AD web API app>;
    string clientId = <application ID of AD native app>;
    string authority = "https://login.microsoftonline.com/<mytennant>.onmicrosoft.com";

    AuthenticationContext authContext = new AuthenticationContext(authority);
    UserCredential credential = new UserCredential(username, password);

    var result = await authContext.AcquireTokenAsync(resourceId, clientId, credential);
    return result.AccessToken; 
}

当我星期五离开工作时,此代码正在工作。我今天回来时,它提供了以下堆栈跟踪:

parsing_wstrust_response_failed: Parsing WS-Trust response failed at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.WsTrust.WsTrustResponse.CreateFromResponseDocument(XDocument responseDocument, WsTrustVersion version) at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.WsTrust.WsTrustRequest.<SendRequestAsync>d__3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenNonInteractiveHandler.<PreTokenRequestAsync>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<RunAsync>d__57.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenCommonAsync>d__37.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions.<AcquireTokenAsync>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at GetToken.Program.<GetToken>d__5.MoveNext()

在本地运行时,无论如何我都可以故障转移到您首次需要使用的交互式登录,以授予非交互式登录的权限。为此,我将上面代码中对AcquireToken的调用替换为:

AuthenticationResult result = null;
try
{
   // the same as the old call to AcquiteTokneAsync
   result = await authContext.AcquireTokenAsync(resourceId, clientId, credential);
}
catch (AdalException aex)
{
    // this failover uses an interactive flow, so can't be used to run
    // automated deployment integration tests
    string replyUri = <one of the reply URIs in the native AD app>;
    result = await authContext.AcquireTokenAsync(resourceId, clientId, new Uri(replyUri));
}

因此,我可以以交互方式获取令牌,并且令牌获得了工作(就像我上周使用非交互式流程获得的令牌一样)。但是,此错误使我无法对已部署的Web应用程序进行自动化测试,这是我持续交付流程的一部分。有办法避免这种解析错误吗?

2 个答案:

答案 0 :(得分:1)

axfd回答的第一行提供了按键输入。

我遗漏了一些细节,我错误地认为这是无关紧要的。在我们的开发环境中,我们有一个单独的Azure AD组件,并且我们将在质量检查,生产前和生产中使用的所有帐户都邀请为来宾帐户。

Resource Owner Password Credentials Grant流不适用于访客帐户。在某些说明中提到了这一点,因为由于流程中相对较低的安全性而不允许进行菊花复制。我曾经愚蠢地使用了我的帐户,该帐户是开发AAD中的访客帐户,但在生产AAD中是真实帐户。

在dev AAD中创建和使用新帐户,然后将其与工具一起使用即可解决我的问题。

答案 1 :(得分:0)

根据您的错误消息,该用户未与WS-Trust联合。

实际上,不建议使用资源所有者密码凭证授予流程。仅当资源所有者和客户端之间存在高度信任时(例如,客户端是设备操作系统或高度特权的应用程序的一部分),并且其他授权授予类型不可用时,才应使用此方法。作为授权码)。

我建议您使用客户端凭据来获取访问令牌。我的代码如下。

        string authority = "https://login.microsoftonline.com/b29343ba-***/oauth2/token"; //token endpoint
        string resourceUri = "";
        string clientId = "your application id";
        string clientkey = "your app key";
        try
        {
            AuthenticationContext authContext = new AuthenticationContext(authority);
            ClientCredential clientCredential = new ClientCredential(clientId, clientkey);
            AuthenticationResult authenticationResult = authContext.AcquireTokenAsync(resourceUri, clientCredential).Result;
            Console.WriteLine("--------------------------------");
            Console.WriteLine(authenticationResult.AccessToken);
            Console.Read();
        }
        catch (Exception ex)
        {


        }

此外,您还可以参考the blog