使用Azure DevOps REST Api的用户名和密码从Azure AD获取访问令牌

Acquire access token from Azure AD using username and password for Azure DevOps REST Api

我们正在实现AD注册的应用程序(部署为Azure App Service)来访问Azure DevOps Rest Api,我已遵循为Azure DevOps提供的身份验证指南,并使用身份验证上下文通过发送用户名和密码来获取访问令牌。尽管MS不建议使用此身份验证过程,但我们这样做的原因是用户帐户具有对不同组织中多个项目的特定访问权限。这样,我们为该用户获取令牌并访问该用户可访问的Azure DevOps REST Api。基本上,我们创建了一个通用用户帐户,该帐户可以从我的应用程序访问DevOps REST Api。

在本地环境中,我可以使用以下代码获取用户的访问令牌,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
AuthenticationContext ctx = new AuthenticationContext("https://login.microsoftonline.com/org.onmicrosoft.com/");            
AuthenticationResult result = null;

var username ="********"; // This is your AAD username in the form [email protected].
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异常以下,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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?我也想知道我们遵循的方法是正确的吗?我们是否可以实施另一种解决方案来实现我们正在寻找的目标?


老实说,这段代码看起来不错。但是,从错误消息来看,似乎没有收到成功的响应。

我用您的代码创建了一个测试Web应用程序以获取令牌。我的环境:.NET Framework 4.7.2和ADAL 5.2.7。结果是我可以成功获得令牌。

enter

因此,您可以尝试更新以使用最新的ADAL版本,并将Web应用程序部署到新的Web应用程序。

如果问题仍然存在,您可以尝试直接发出http请求以获取令牌:

1
2
3
4
5
6
7
8
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}

enter