【发布时间】:2019-10-16 06:04:51
【问题描述】:
我很难理解如何重用用户的安全令牌,以便在他们的数据请求流经多个 Web API 时对其进行身份验证。
-
Console App- C# / Net Framework 4.7.x 控制台应用程序。 -
WebAPI 1- C# / .Net Core 2.2 MVC WebAPI 应用程序。 -
WebAPI 2- C# / .Net Core 2.2 MVC WebAPI 应用程序。
目前,这些都在我的开发盒上运行的自己的 Visual Studio 2019 解决方案中配置为独立应用程序,但是(一旦工作!!)每个都将作为单独的实体托管在 Azure 中。
基本上,用户在控制台应用程序中进行身份验证,从 Azure Active Directory 验证他们的凭据。在 GitHub 上关注this sample,我的控制台应用程序可以成功调用WebAPI 1,并返回数据。
但是,我希望 WebAPI 1 在通话期间调用 WebAPI 2 并检索其他数据作为控制台应用程序数据集的一部分,这是我坚持的部分。
WebAPI 2在Azure Portal中的配置与WebAPI 1完全一样,只是Application Client Id不同等等。
作为示例的一部分(如上所述),我可以让WebAPI 1 调用 Microsoft 的 Graph API,然后将数据返回给调用 Console App,所以我不认为我是一个方法离开这个。下面是调用 Graph API 的代码:
public async Task<string> CallGraphApiOnBehalfOfUser()
{
string[] scopes = { "user.read" };
// we use MSAL.NET to get a token to call the API On Behalf Of the current user
try
{
string accessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUser(HttpContext, scopes);
dynamic me = await CallGraphApiOnBehalfOfUser(accessToken);
return me.userPrincipalName;
}
catch (MsalUiRequiredException ex)
{
_tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeader(HttpContext, scopes, ex);
return string.Empty;
}
}
private static async Task<dynamic> CallGraphApiOnBehalfOfUserOriginal(string accessToken)
{
//
// Call the Graph API and retrieve the user's profile.
//
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = await client.GetAsync("https://graph.microsoft.com/v1.0/me");
string content = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
dynamic me = JsonConvert.DeserializeObject(content);
return me;
}
throw new Exception(content);
}
我的计划是把上面代码中的URL改成指向WebAPI 2的地址,但是在认证过程中失败了。 如果我在WebAPI 2 中删除我的控制器上的 [Authorize] 类属性,它确实成功建立连接并返回预期的数据,但使用该属性,它甚至不会遇到断点在控制器上,向我建议问题出在我尝试使用的不记名令牌或 WebAPI 2 配置不正确。
获取安全令牌的副本并尝试重新使用此飞行中途也不起作用,因为我假设该令牌用于WebAPI 1,因此不适用于WebAPI 2。
我应该像这样进行传递身份验证吗? (将用户凭据硬编码到能够访问WebAPI 2 的WebAPI 1 感觉很脏,所以我不想这样做。另外,如果用户凭据需要更改,我有一个重新部署只是为了那个。)
有没有更好的方法来做我想做的事情?
如果您需要我提供更多信息来解释我所做的任何事情,我当然可以做到。
更新 1:这是 Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddProtectWebApiWithMicrosoftIdentityPlatformV2(Configuration)
.AddProtectedApiCallsWebApis(Configuration, new string[] { "user.read", "offline_access" })
.AddInMemoryTokenCaches();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
更新 2: 类似的 Stack Overflow 帖子 从那以后我找到了this SO post,@philippe-signoret 在他的回答中描述了它,这正是我所追求的。
更新 3: 调用 WebAPI 2 时未经授权的响应
这是我从通话中收到的错误消息:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
Server: Kestrel
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
X-SourceFiles: =?UTF-8?B?*<random-looking-code>*
X-Powered-By: ASP.NET
Date: Fri, 31 May 2019 09:48:31 GMT
Content-Length: 0
}}
如前所述,如果我从 Controller 的类中删除 [Authorize] 属性,调用将按预期进行。
【问题讨论】:
-
ConfigureService 的实现是什么?特别是 AddAuthorization
-
涉及此问题细节的最新示例:azure.microsoft.com/en-us/resources/samples/…
-
@ranton187 - 在问题中添加了一些额外的代码来显示这一点。谢谢。
-
您有 2 种可能的情况 1) 您想在登录控制台应用程序并调用 WebAPI1 的当前用户的上下文中调用 WebAPI2.. 在这种情况下,您可以使用 On代表流程 2) WebAPI2 不关心用户并隐式信任 WebAPI1.. 在这种情况下,您可以使用 Client Credentials Grant 流程..
-
@RohitSaigal 谢谢,但这是我正在尝试代表用户的调用,并且包含在上述问题的代码中,但我坚持让它工作,尽管它调用第二个 WebAPI,它似乎不正确。或者我的配置不正确,这种可能性更大。
标签: c# azure asp.net-core azure-active-directory