为什么在使用 ASP.NET Identity Core 时 OAuth 会失败?
Why does OAuth fail when using ASP.NET Identity Core?
我有一个 ASP.NET 核心 2.x 项目,配置如下:
services
.AddAuthentication(options => options.DefaultScheme = CookieAuthenticaitonDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(ConfigureFacebook);
不出所料,当我从我的一个行为中调用时:
return Challenge(new AuthenticationProperties { RedirectUri = "/test" }, "Facebook");
... 然后,我通过 Facebook OAuth 序列进行导航。当我回到我的应用程序时,HttpContext.User.Identity
填充了相关详细信息:
User.Identity.Name
- Facebook 用户名。
User.Identity.AuthenticationType
- 字符串 "Facebook"
.
User.Identity.IsAuthenticated
- true
.
这一切都很好,符合预期。但是,如果我将以下内容添加到我的应用程序配置中
services.AddIdentity<MyUserType, MyRoleType>()
.AddEntityFrameworkStores<MyDbContext>();
突然之间,OAuth 流程以 User.Identity
匿名结束,没有任何其他更改。如果我们钻入 IdentityServiceCollectionExtensions.cs,我们会发现:
options.DefaultAuthenticateScheme =
IdentityConstants.ApplicationScheme; options.DefaultChallengeScheme =
IdentityConstants.ApplicationScheme; options.DefaultSignInScheme =
IdentityConstants.ExternalScheme;
除其他外...
这是怎么回事?为什么身份会干扰 Cookie 进程,从 OAuth 提供程序返回用户的正确方法是什么?
为了结合 OAuth 和 Asp.Net Core Identity,您需要配置 facebookOptions.SignInScheme
和 CookieAuthenticationDefaults.AuthenticationScheme
。
试试下面的代码:
services
.AddAuthentication(options => options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(facebookOptions =>
{
facebookOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
facebookOptions.AppId = "xx";
facebookOptions.AppSecret = "xxx";
});
结合使用 ASP.NET Identity 和 OAuth 时,需要注意以下几点:
配置服务:
不再需要添加 AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
,因为 Identity 添加了自己的 cookie 处理程序。
将外部用户作为 ClaimsPrincipal:
如果要在 HttpContext.User
下填充外部用户,请执行以下操作:
.AddFacebook(options => {
options.SignInScheme = IdentityConstants.ApplicationScheme;
})
在您的挑战 AuthenticationProperties
中被重定向到 RedirectUri
后,您的 HttpContext.User
将被填充。
获取外部用户 ExternalLoginInfo
:
如果您需要了解有关用户的信息,例如:
,这是首选
- 他们来自哪个供应商?
- 他们在提供商上的唯一密钥是什么?
您的服务应该像这样配置:
services.AddAuthentication()
.AddFacebook(options =>
{
options.AppId = "";
options.AppSecret = "";
});
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<MyDbContext>();
在您的登录控制器中,将 SignInManager<TUser>
注入:
public DefaultController(SIgnInManager<IdentityUser> signInManager)
并在您的挑战行动中,使用 ConfigureExternalAuthenticationProperties
获得挑战属性:
public IActionResult LoginExternal() {
var props = SignInManager.ConfigureExternalAuthenticationProperties("Facebook", "/");
return Challenge(props, "Facebook");
}
在您的 return 操作中,使用 GetExternalLoginInfoAsync
获取有关用户的外部详细信息:
public async Task<IActionResult> LoginCallback() {
var loginInfo = await SignInManager.GetExternalLoginInfoAsync();
// This object will tell you everything you need to know about the incoming user.
}
我有一个 ASP.NET 核心 2.x 项目,配置如下:
services
.AddAuthentication(options => options.DefaultScheme = CookieAuthenticaitonDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(ConfigureFacebook);
不出所料,当我从我的一个行为中调用时:
return Challenge(new AuthenticationProperties { RedirectUri = "/test" }, "Facebook");
... 然后,我通过 Facebook OAuth 序列进行导航。当我回到我的应用程序时,HttpContext.User.Identity
填充了相关详细信息:
User.Identity.Name
- Facebook 用户名。User.Identity.AuthenticationType
- 字符串"Facebook"
.User.Identity.IsAuthenticated
-true
.
这一切都很好,符合预期。但是,如果我将以下内容添加到我的应用程序配置中
services.AddIdentity<MyUserType, MyRoleType>()
.AddEntityFrameworkStores<MyDbContext>();
突然之间,OAuth 流程以 User.Identity
匿名结束,没有任何其他更改。如果我们钻入 IdentityServiceCollectionExtensions.cs,我们会发现:
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme; options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme; options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
除其他外...
这是怎么回事?为什么身份会干扰 Cookie 进程,从 OAuth 提供程序返回用户的正确方法是什么?
为了结合 OAuth 和 Asp.Net Core Identity,您需要配置 facebookOptions.SignInScheme
和 CookieAuthenticationDefaults.AuthenticationScheme
。
试试下面的代码:
services
.AddAuthentication(options => options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddFacebook(facebookOptions =>
{
facebookOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
facebookOptions.AppId = "xx";
facebookOptions.AppSecret = "xxx";
});
结合使用 ASP.NET Identity 和 OAuth 时,需要注意以下几点:
配置服务:
不再需要添加 AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
,因为 Identity 添加了自己的 cookie 处理程序。
将外部用户作为 ClaimsPrincipal:
如果要在 HttpContext.User
下填充外部用户,请执行以下操作:
.AddFacebook(options => {
options.SignInScheme = IdentityConstants.ApplicationScheme;
})
在您的挑战 AuthenticationProperties
中被重定向到 RedirectUri
后,您的 HttpContext.User
将被填充。
获取外部用户 ExternalLoginInfo
:
如果您需要了解有关用户的信息,例如:
,这是首选- 他们来自哪个供应商?
- 他们在提供商上的唯一密钥是什么?
您的服务应该像这样配置:
services.AddAuthentication()
.AddFacebook(options =>
{
options.AppId = "";
options.AppSecret = "";
});
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<MyDbContext>();
在您的登录控制器中,将 SignInManager<TUser>
注入:
public DefaultController(SIgnInManager<IdentityUser> signInManager)
并在您的挑战行动中,使用 ConfigureExternalAuthenticationProperties
获得挑战属性:
public IActionResult LoginExternal() {
var props = SignInManager.ConfigureExternalAuthenticationProperties("Facebook", "/");
return Challenge(props, "Facebook");
}
在您的 return 操作中,使用 GetExternalLoginInfoAsync
获取有关用户的外部详细信息:
public async Task<IActionResult> LoginCallback() {
var loginInfo = await SignInManager.GetExternalLoginInfoAsync();
// This object will tell you everything you need to know about the incoming user.
}