azure-devops - 使用 Azure DevOps REST Api 的用户名和密码从 Azure AD 获取访问令牌
问题描述
我们正在实施 AD 注册应用程序(部署为 Azure App Service)来访问 Azure DevOps Rest Api,我遵循了为 Azure DevOps 提供的身份验证指南,并使用身份验证上下文通过发送用户名和密码获取访问令牌。尽管 MS 不推荐这种身份验证过程,但我们这样做的原因是用户帐户有权对不同组织的多个项目进行特定访问。通过这种方式,我们获取该用户的令牌并访问用户可访问的 Azure DevOps REST Api。基本上,我们创建了一个通用用户帐户,可以从我的应用程序访问 DevOps REST Api。
在本地环境中,我可以使用以下代码获取用户的访问令牌,
AuthenticationContext ctx = new AuthenticationContext("https://login.microsoftonline.com/org.onmicrosoft.com/");
AuthenticationResult result = null;
var username = "********"; // This is your AAD username in the form user@domain.com.
var password = "********"; // This is your AAD password.
var adalCredential = new UserPasswordCredential(username, password);
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
try
{
result = ctx.AcquireTokenAsync(azureDevOpsResourceId, clientId, adalCredential).Result;
Console.WriteLine("Token expires on: " + result.ExpiresOn);
}
catch (Exception ex)
{
Console.WriteLine("{0}: {1}", ex.GetType(), ex.Message);
}
通过 Web 应用程序访问时相同的代码未按预期工作,并引发 ADAL 异常,
System.AggregateException: One or more errors occurred. ---> Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException: 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 inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
为什么parsing_wstrust_response_failed
从应用程序运行时会发生此错误?我也想知道我们遵循的方法是否正确?我们是否有可以实施以实现我们正在寻找的替代解决方案?
解决方案
老实说,这段代码看起来不错。但是,从错误信息来看,似乎没有收到成功的响应。
我使用您的代码创建了一个测试网络应用程序以获取令牌。我的环境:.NET 框架 4.7.2 和 ADAL 5.2.7。结果是我可以成功拿到一个token。
因此,您可以尝试更新以使用最新的 ADAL 版本并将您的 Web 应用程序部署到新的 Web 应用程序。
如果问题依旧,可以尝试直接发起http请求获取token:
POST https://login.microsoftonline.com/{tenant-id}/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=password
&resource={resource}
&username={username}
&password={password}
&client_id={client-id}
推荐阅读
- python - 如何使用 python 使用单独的名称列表文件从文本中删除名称
- python - 我需要使用 dom python 更新 xml 文件中的多个元素
- python - Williams p+1 整数分解
- python - 如何在二进制数组中找到相邻像素的数量
- asp.net-mvc - 如何从 ASP.NET MVC 项目的前端将数据插入数据库表?
- ruby-on-rails - 使用 TinyMCE 和 Rails 7 上传图片
- python - 不进入函数-python
- css - 生产版本中的字体与开发版本 Next.js 中的字体不同
- git - 使用 git filter-repo 将子目录拆分到自己的存储库
- html - 如何在 SVG 图像前渲染文本