ASP.NET Core 2.0 AzureAD身份验证不起作用 [英] ASP.NET Core 2.0 AzureAD Authentication not working
问题描述
我有一个ASP.NET Core 2.0应用程序设置,我想使用AzureAd对公司目录进行身份验证.我已经设置了类和启动方法,并使身份验证模块正常工作,我遇到的问题是我正在尝试为OnAuthorizationCodeReceived事件设置事件处理程序,以便可以请求一个用户令牌,用于Microsoft图形调用.
I have an ASP.NET Core 2.0 application setup that I want to use AzureAd for the authentication with my company's directory. I have setup the classes and startup method and have the authentication piece working, the problem that I'm having is that I'm trying to setup and event handler to the OnAuthorizationCodeReceived event, so that I can request a user token that will then be used for Microsoft graph calls.
在我的Startup.cs中,我有以下代码
In my Startup.cs I have the following code
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie();
services.AddMvc();
services.AddSingleton(Configuration);
services.AddSingleton<IGraphAuthProvider, GraphAuthProvider>();
services.AddTransient<IGraphSDKHelper, GraphSDKHelper>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
然后在AzureAdAuthenticationBuilderExtensions.cs中,我具有以下代码.
Then in the AzureAdAuthenticationBuilderExtensions.cs I have the following code.
public static class AzureAdAuthenticationBuilderExtensions
{
public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, IConfiguration configuration)
=> builder.AddAzureAd(_ => { }, configuration);
public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action<AzureAdOptions> configureOptions,
IConfiguration configuration)
{
builder.Services.Configure(configureOptions);
builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
builder.AddOpenIdConnect(opts =>
{
opts.ResponseType = "code id_token";
opts.ClientId = configuration["AzureAd:ClientId"];
opts.Authority = $"{configuration["AzureAd:Instance"]}{configuration["AzureAd:TenantId"]}";
opts.UseTokenLifetime = true;
opts.CallbackPath = configuration["AzureAd:CallbackPath"];
opts.ClientSecret = configuration["AzureAd:ClientSecret"];
opts.RequireHttpsMetadata = false;
opts.Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async context =>
{
var credential = new ClientCredential(context.Options.ClientId, context.Options.ClientSecret);
var distributedCache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();
var userId = context.Principal
.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
.Value;
var cache = new AdalDistributedTokenCache(distributedCache, userId);
var authContext = new AuthenticationContext(context.Options.Authority, cache);
await authContext.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code,
new Uri(context.TokenEndpointRequest.RedirectUri, UriKind.RelativeOrAbsolute), credential, context.Options.Resource);
context.HandleCodeRedemption();
}
};
});
return builder;
}
private class ConfigureAzureOptions: IConfigureNamedOptions<OpenIdConnectOptions>
{
private readonly AzureAdOptions _azureOptions;
public ConfigureAzureOptions(IOptions<AzureAdOptions> azureOptions)
{
if (azureOptions != null)
{
_azureOptions = azureOptions.Value;
}
}
public void Configure(string name, OpenIdConnectOptions options)
{
options.ClientId = _azureOptions.ClientId;
options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}";
options.UseTokenLifetime = true;
options.CallbackPath = _azureOptions.CallbackPath;
options.RequireHttpsMetadata = false;
options.ClientSecret = _azureOptions.ClientSecret;
}
public void Configure(OpenIdConnectOptions options)
{
Configure(Options.DefaultName, options);
}
}
}
然后调用了AddAzureAd方法,可以看到它遍历了该方法中的所有代码,但是当我在OnAuthorizationCodeReceived方法中放置一个断点时,断点永远不会被击中.我已经阅读了很多书,看来我的建议是对的,所以我想我在这里肯定错过了一些简单的事情,但是找不到问题.
Then AddAzureAd method is being called and I can see it walk through all of the code in this method, but when I put a breakpoint in the OnAuthorizationCodeReceived method that breakpoint never gets hit. I've done a bunch of reading and it looks like what I have is right, so I'm guessing that I must be missing something simple here, but can't find the problem.
已编辑 我现在遇到了OnAuthorizationCodeReceived事件,但是现在应用程序无法继续登录以获取以下错误
Editted I'm now hitting the OnAuthorizationCodeReceived event, but now the application is failing to continue to log in getting the following error
SecurityTokenException: Unable to validate the 'id_token', no suitable ISecurityTokenValidator was found for: ''."
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+<HandleRequestAsync>d__12.MoveNext()
Stack Query Cookies Headers
SecurityTokenException: Unable to validate the 'id_token', no suitable ISecurityTokenValidator was found for: ''."
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+<HandleRequestAsync>d__12.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
推荐答案
Asp.net core 2.0的OpenIdConnect组件使用隐式流(response_type
的值为id_token
).
The OpenIdConnect component for Asp.net core 2.0 uses implicit flow(the value of response_type
is id_token
).
要触发OnAuthorizationCodeReceived
事件,我们应该使用混合流,该流的'response_type'参数包含code
值(例如id_token code
).我们需要通过下面的OpenIdConnectOptions
类似代码进行设置:
To fire the OnAuthorizationCodeReceived
the event, we should use the hybrid flow which's 'response_type' parameter contains code
value.(eg. id_token code
). And we need set it through the OpenIdConnectOptions
like code below:
.AddOpenIdConnect(options =>
{
options.Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]);
options.ClientId = Configuration["AzureAd:ClientId"];
options.ResponseType = "code id_token";
});
options.Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async context =>
{
var credential = new ClientCredential(context.Options.ClientId, context.Options.ClientSecret);
var authContext = new AuthenticationContext(context.Options.Authority);
var authResult=await authContext.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code,
new Uri(context.TokenEndpointRequest.RedirectUri, UriKind.RelativeOrAbsolute), credential, context.Options.Resource);
context.HandleCodeRedemption(authResult.AccessToken, context.ProtocolMessage.IdToken);
},
};
这篇关于ASP.NET Core 2.0 AzureAD身份验证不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!