我遇到了一个看起来有点像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应用程序进行自动化测试,这是我持续交付流程的一部分。有办法避免这种解析错误吗?
答案 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。