使用 Azure DevOps REST 的用户名和密码从 Azure AD 获取访问令牌 Api
Acquire access token from Azure AD using username and password for Azure DevOps REST Api
我们正在实施 AD 注册应用程序(部署为 Azure 应用服务)以访问 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 Framework 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}
我们正在实施 AD 注册应用程序(部署为 Azure 应用服务)以访问 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 Framework 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}