对我来说,我正在将.NET 4.6.1 MVC 网站迁移到核心 1.1。在我让它工作之前工作就停止了,当我把它捡起来时,我正在迁移到 2.x。
我的问题是来自 Google 的回调是404
来自我的网站的。我认为它应该命中AccountController.ExternalLoginCallback
,所以我添加了一个[Route(...)]
,果然,谷歌的回调命中了动作。
这然后命中了null
这一行中的返回(什么样的疯子返回一个null
?)
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
我对它进行了逆向工程,以在引擎盖下找到它最终得到的处理程序ExternalScheme
,我的 cookie 处理程序就是为它处理程序!
这一切似乎都是错误的,我觉得中间件应该只是拦截回调 URI,所以我删除了我[Route(...)]
的,404
问题又回来了。
然后我发现我需要在启动时添加这个。
applicationBuilder.UseAuthentication();
这解决了404
但又带来了另一个问题。
没有指定 authenticationScheme,也没有找到 DefaultSignInScheme。
通过在此处添加默认方案,我解决了上述错误。
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions => Configuration.Bind("OAuth2:Providers:Google", googleOptions))
.AddExternalCookie();
现在AccountController.ExternalLoginCallback
被一些魔法再次调用,但我回到了null
返回值。
我在有问题的行上方添加了这段代码,这基本上就是幕后发生的事情(查看微软在 GitHub 上的代码)。有趣的是,h
它是类型的CookieAuthenticationHandler
,a
里面有我所有的声明和来自谷歌的信息!
var authHandler = this.HttpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
var h = await authHandler.GetHandlerAsync(this.HttpContext, IdentityConstants.ExternalScheme);
var a = await h.AuthenticateAsync();
var externalLoginInfo = await this.SignInManager.GetExternalLoginInfoAsync();
挖掘 GitHub 并将其运行的内部代码复制粘贴到我的控制器中,我可以看到它在我的声明中找不到ClaimTypes.NameIdentifier
,这是ProviderKey
稍后使用的。
唔....
担心我使用的是旧的 1.xAccountController
代码和更新的 2.x 标识位,我确实找到了一些仍然使用这些东西的示例,以及一些使用 Razor Pages 的示例。我会继续我所拥有的。
因此,接下来我将研究将其他 Google 用户 JSON 有效负载项映射到声明中。我认为如果我的 Google 帐户 ID(我猜是数字)被映射,那么一切都会正常工作。
https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2
最终修复
我终于通过添加“声明操作”将我的 Google 标识符从 Google 返回的 JSON 中提取出来解决了这个问题!
serviceCollection.AddAuthentication(IdentityConstants.ExternalScheme)
.AddGoogle(googleOptions =>
{
Configuration.Bind("OAuth2:Providers:Google", googleOptions);
googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
})
.AddExternalCookie();
该sub
字段包含最终在声明中结束的内容,nameidentifier
然后进入想要的内容。ProviderKey
AccountController