如何在blazor Webassembly项目的服务器端控制器中对用户进行身份验证?

时间:2020-08-30 20:41:40

标签: asp.net-core authentication asp.net-identity identityserver4 blazor

我有一个使用Identityserver和Facebook身份验证的出色Webassembly项目。从Webassembly调用api控制器时,在使用.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>()设置httpclient并将useridclaimtype映射到nameidentifier后,一切工作都很好。通过UserManager.GetUserAsync可以访问该用户。

现在,我尝试添加一个纯服务器控制器,其视图希望用户能够直接从浏览器进行浏览。但是,直接浏览到服务器视图时,尽管进行了设置,但似乎没有进行身份验证:

app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();

services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();

services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

services.AddAuthentication()
.AddIdentityServerJwt().AddFacebook(facebookOptions =>
{
   facebookOptions.AppId = Configuration["id"];
   facebookOptions.AppSecret = Configuration["idpwd"];
});

services.Configure<IdentityOptions>(options => options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);

我曾期望中间件通过这种设置为我自动进行身份验证。但是,即使我先登录并携带.AspNetCore.Identity.Application cookie,该用户仍无法通过usermanager进行访问。我只会得到一个没有名称和声明的空白标识,并且如果向控制器添加Authorize属性,则会得到401。

我是否缺少一些秘诀才能使它正常工作?我对中间件应该为我做什么有错误的期望吗?

更新:

经过一番摸索,比较了一个可以正常工作的标准asp.net核心项目和我的项目。看来这是杀死服务器端控制器的行:

services.AddAuthentication().AddIdentityServerJwt()

如果我不添加AddIdentityServerJwt(),则控制器运行良好,并在需要授权时重定向我,并正确登录。谁能向我解释为什么? AddIdentityServerJwt()中间件与返回视图的Controller不兼容吗?

在我看来,添加AddIdentityServerJwt()增加了以下要求:每个请求都需要带有承载令牌的授权标头,这是由blazor客户端httpclient提供的。但是,当浏览器直接进行呼叫时,承载令牌将丢失,并且管道也不会尝试对用户进行身份验证以获取呼叫。

1 个答案:

答案 0 :(得分:1)

发生了什么

在控制器端点上AuthorizeFilter的特定混合与在身份验证构建器上AddIdentityServerJwt的用法可能是这里的罪魁祸首。 AddIdentityServerJwt adds the Jwt authentication scheme as the default authentication scheme由AddAuthentication方法中认证方案名称的传递指示。这意味着与此Jwt身份验证方案(JwtBearerHandler)关联的处理程序将是通过其HandleChallengeAsync方法发出401的类。请注意,此方法中没有用于进一步操作的重定向,这就是为什么您看不到重定向的原因。

为什么会这样?

由于控制器端点上的AuthorizeFilter,因此调用了JwtBearerHandler上的HandleChallengeAsync方法。执行AuthorizeFilter的方法是OnAuthorizationAsync方法(which is invoked right after the initialization of the filter)。由于没有在控制器上放置的Authorization属性中指定任何策略([Authorize]中没有作为参数传递任何内容),因此最终使用了默认授权策略。默认策略基本上检查是否有任何身份验证方案已成功验证了您的身份(通过查看HttpContext中的身份),然后返回response for a challenge if not。此挑战默认为默认身份验证方案的挑战,这就是为什么在JwtBearerHandler上调用HandleChallengeAsync的原因。

您可以了解有关策略here的更多信息,以及有关AuthorizationFilter(以及一般的过滤器)here的更多信息。