使用 Oauth 通过 Azure 活动目录保护 WebAPI

Using Oauth to protect WebAPI with Azure active directory

我在线浏览了所有关于使用Oauth 保护Azure 活动目录中的WebAPI 的教程。但不幸的是,其中 none 个可以工作。

我使用的是 VS 2017,我的项目是 .net core。

到目前为止我尝试过的是:

public void ConfigureServices(IServiceCollection services)
{
     services.AddMvc();
     ervices.AddAuthentication(); // -----------> newly added
 } 

在"Configure"中,我添加了:

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
     AutomaticAuthenticate = true,
     AutomaticChallenge = true,
     Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAD:Tenant"]),
     Audience = Configuration["AzureAd:Audience"],         
 });

这是我的配置:

"AzureAd": {
    "AadInstance": "https://login.microsoftonline.com/{0}",
    "Tenant": "tenantname.onmicrosoft.com",
    "Audience": "https://tenantname.onmicrosoft.com/webapiservice"
  }

我已经在我的 AAD 上注册了这个 "webapiservice"(link 是:http://webapiservice.azurewebsites.net)。

此外,为了访问此网络 api 服务,我创建了一个网络 api 客户端 "webapiclient" 这也是一个网络 api 并且还在我的 AAD 上注册了它并请求访问 "webapiservice" 的权限。 Webapi 客户端 link 是:http://webapiclient.azurewebsites.net

HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://webapiservice.azurewebsites.net/");
//is this uri correct? should it be the link of webapi service or the one of webapi client?

HttpResponseMessage response = client.GetAsync("api/values").Result;
if (response.IsSuccessStatusCode)
{
     var result = response.Content.ReadAsAsync<IEnumerable<string>>().Result;
     return result;
}
else
{
     return new string[] { "Something wrong" };
} 

所以理论上,我应该从 webapiservice 收到正确的结果。但我总是收到 "Something wrong"。

我在这里遗漏了什么吗?

要调用受 azure ad 保护的网络 api,您应该使用承载方案在授权 header 中传递此获得的访问令牌:

client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);

您需要来自 Azure AD 的访问令牌

GitHub 上有很多很好的示例应用程序,这里是一个守护程序应用程序:https://github.com/Azure-Samples/active-directory-dotnet-daemon/blob/master/TodoListDaemon/Program.cs#L96

AuthenticationResult authResult = await authContext.AcquireTokenAsync(todoListResourceId, clientCredential);

此应用为 API 获取带有其客户端 ID 和客户端密码的访问令牌。您可以在您的案例中采用类似的方法。例如,对于 Azure AD Graph API,您可以将 todoListResourceId 替换为 "https://graph.windows.net/",或者将 Microsoft Graph API 替换为 "https://graph.microsoft.com/"。那是您想要令牌的 API 的标识符。

这是它在 AAD 中的工作方式。您想要访问 API,您向 AAD 请求该访问权限。在成功的响应中,您将取回一个访问令牌,您必须将其作为 header:

附加到 HTTP 调用
Authorization: Bearer accesstokengoeshere......

现在,如果您正在构建 Web 应用程序,您可能希望以不同的方式进行操作,因为您现在正在以客户端应用程序而非用户的身份访问 API。如果您想拨打委托电话,则需要使用例如授权代码流程,您向用户显示浏览器,将他们重定向到正确的地址,然后他们将被发送回您的应用程序以进行登录。