【问题标题】:Previously working ADAL.net code now generating a `ErrorParsingWsTrustResponse` error以前工作的 ADAL.net 代码现在会生成“ErrorParsingWsTrustResponse”错误
【发布时间】:2018-08-01 01:39:53
【问题描述】:

我遇到了一个看起来有点像 this one 的问题,但我在一个稍微不同的上下文中遇到了这个问题,并且除了“尝试使用不同的身份验证”之外,原始问题没有令人满意的答案flow',我认为这对我不起作用。

我有一个托管在 Azure 中的 Web API,使用 Active Directory 不记名令牌进行保护。作为 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 应用程序运行自动化测试作为我的持续交付管道的一部分。有没有办法避免这种解析错误?

【问题讨论】:

  • 我已尝试将 ADAL.Net nuget 包更新到最新版本。这并没有解决问题。
  • 嗯,我已经有一段时间无法使用 ADAL.NET 进行非交互式登录了。在 API 集成测试中,我已针对令牌端点手动完成令牌获取。

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


【解决方案1】:

axfd 答案的第一行提供了关键输入。

我遗漏了一些细节,我错误地认为这些细节无关紧要。在我们的开发环境中,我们有一个单独的 Azure AD 组件,我们在 QA、预生产和生产中使用的所有帐户都被邀请为来宾帐户。

Resource Owner Password Credentials Grant 流程不适用于访客帐户。在某些文档中提到了这一点,因为流中的安全性相对较低,因此不允许菊花连接。愚蠢地,我一直在使用我的帐户,这是开发 AAD 中的访客帐户,但在生产 AAD 中是真实帐户。

在开发 AAD 中创建和使用一个新帐户并将其与该工具一起使用解决了我的问题。

【讨论】:

  • 单独 AAD 的原因是因为对生产版本的更改是通过向管理团队提交工单来完成的,平均需要 1 周的时间来完成。我们想要一个我们可以完全控制的设置来尝试设置,这样我们就可以提交一个我们相信会解决我们问题的请求。
【解决方案2】:

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

事实上,不推荐使用 Resource Owner Password Credentials Grant 流程。仅当资源所有者和客户端之间存在高度信任时(例如,客户端是设备操作系统或高特权应用程序的一部分)以及其他授权授予类型不可用时(例如作为授权码)。

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

        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

【讨论】:

  • 这将使我作为服务主体登录。为了使测试真实,我需要以用户帐户登录。目的是测试用户登录应用程序时会发生什么。
  • 好的。我懂了。关于您的错误,我认为您的密码已过期。据我所知,如果你只在Azure AD中创建用户,而不使用它登录Azure Portal,你的密码是临时的。
  • 嗯。但是我在故障转移交互流程中使用了相同的用户名/密码,这样我就可以登录,而不会出现用户名/密码问题...
  • 对于开发测试,我使用的是我自己的帐户。我可以交互式登录,但不能通过此工具登录。因此,如果密码已过期,我会感到惊讶...
猜你喜欢
  • 1970-01-01
  • 2016-03-26
  • 2017-12-20
  • 1970-01-01
  • 2018-10-18
  • 2014-11-15
  • 2016-08-09
  • 2017-05-29
  • 1970-01-01
相关资源
最近更新 更多