【发布时间】:2018-06-05 19:32:15
【问题描述】:
我正在尝试使用 ASP.NET Core 2.0 创建一个 Web API 服务器,该服务器使用 azure ad v2 端点令牌授权。我还有一个 Angular 2 应用程序,在其中进行 office365 登录。我从那里得到一个令牌,然后向 Web API 服务器中的授权操作发送一个简单的请求。但是我的令牌没有通过授权检查,我收到 401 Unauthorized 响应。提供的描述是:
Bearer error="invalid_token", error_description="找不到签名密钥"
我解码了令牌,解码器也抛出了无效签名错误。以下是我用于配置和令牌授权的代码的重要部分:
Web API 服务器:
appsettings.json
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "my-registered-app-client-id",
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
AzureAdAuthenticationBuilderExtensions.cs
public static class AzureAdServiceCollectionExtensions
{
public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder)
=> builder.AddAzureAdBearer(_ => { });
public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions)
{
builder.Services.Configure(configureOptions);
builder.Services.AddSingleton<IConfigureOptions<JwtBearerOptions>, ConfigureAzureOptions>();
builder.AddJwtBearer();
return builder;
}
private class ConfigureAzureOptions: IConfigureNamedOptions<JwtBearerOptions>
{
private readonly AzureAdOptions _azureOptions;
public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
{
_azureOptions = azureOptions.Value;
}
public void Configure(string name, JwtBearerOptions options)
{
options.Audience = _azureOptions.ClientId;
options.Authority = $"{_azureOptions.Instance}common/v2.0";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
};
}
public void Configure(JwtBearerOptions options)
{
Configure(Options.DefaultName, options);
}
}
}
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddAzureAdBearer(options => Configuration.Bind("AzureAd", options));
services.AddMvc();
services.AddCors(options =>
{
options.AddPolicy("AllowAllOrigins",
builder =>
{
builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("AllowAllOrigins");
app.UseAuthentication();
app.UseMvc();
}
}
下面是我在 Angular2 应用中用来进行身份验证的代码:
import { Injectable } from '@angular/core';
import { Headers } from '@angular/http';
import * as hello from 'hellojs/dist/hello.all.js';
import * as MicrosoftGraph from "@microsoft/microsoft-graph-types";
import * as MicrosoftGraphClient from "@microsoft/microsoft-graph-client";
import { Configs } from "../../../shared/configs"
@Injectable()
export class HttpService {
url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${Configs.appId}&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&response_mode=query&scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read&state=12345`;
getAccessToken() {
const msft = hello('msft').getAuthResponse();
const accessToken = msft.access_token;
return accessToken;
}
getClient(): MicrosoftGraphClient.Client
{
var client = MicrosoftGraphClient.Client.init({
authProvider: (done) => {
done(null, this.getAccessToken()); //first parameter takes an error if you can't get an access token
},
defaultVersion: 'v2.0'
});
return client;
}
}
当从端点返回令牌时,我会向我的 Web API 服务器上的有效端点发送请求。
重要提示:我在 Web API 和 Angular 应用程序中使用相同的 AppId,因为 AzureAd v2.0 端点需要它。
我的意思是,我认为我做的一切都是照本宣科,但显然缺少一些东西。如果有人能告诉我我在配置中做错了什么,我将不胜感激!
解码令牌的aud属性为:
【问题讨论】:
-
嗯,如果您应该调用 API,为什么还要在前端使用“MicrosoftGraphClient”?您能否检查访问令牌,例如jwt.ms 并提及 aud 声明的价值是什么?
-
当我回到我的电脑时我肯定会。但我前端图形库的主要思想是只进行适当且安全的授权并获取令牌,我计划在对我的 API 的请求中使用它来授权。
-
Microsoft Graph 与身份验证无关 :) 这是另一个 API,您可以通过从 Azure AD 获取令牌来调用它。
-
在 Angular 应用中使用 MS Graph 库的代码是从 GitHub 中的 Azure AD 示例存储库之一复制而来的。我知道它们是两个独立的东西,但我想确保我没有弄乱任何配置,所以我决定在这部分使用他们的代码。
-
@juunas 我在帖子底部添加了解码令牌的 aud 声明。
标签: c# jwt azure-active-directory microsoft-graph-api asp.net-core-2.0