Я читал множество руководств для получения базовой аутентификации пользователей с использованием внешних служб аутентификации, и я просто не могу заставить эту чертову работать.Аутентификация Google +/Facebook в ядре ASP.NET
Я начал работу с проекта «Core plate» .NET Core с уровнем безопасности на уровне пользователя. Я создал свои ключи для доступа к Google и Facebook и включил необходимые библиотеки. Я установил свой класс пользователей, например, так:
public class ApplicationUser : IdentityUser<Guid>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Nickname { get; set; }
}
Мой Startup.cs файл выглядит следующим образом:
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder =
new ConfigurationBuilder().SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true);
if (env.IsDevelopment())
builder.AddUserSecrets();
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(
options => options.UseNpgsql(Configuration.GetConnectionString("ApplicationDb")));
services.AddIdentity<ApplicationUser, ApplicationRole>(opt =>
{
opt.Password.RequireNonAlphanumeric = false;
opt.Password.RequireUppercase = false;
opt.Password.RequireLowercase = false;
opt.Password.RequireDigit = false;
opt.Password.RequiredLength = 8;
opt.User.RequireUniqueEmail = true;
opt.User.AllowedUserNameCharacters = "abcd[email protected].";
opt.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
opt.Lockout.MaxFailedAccessAttempts = 5;
opt.SignIn.RequireConfirmedEmail = true;
opt.SignIn.RequireConfirmedPhoneNumber = false;
})
.AddEntityFrameworkStores<ApplicationDbContext, Guid>()
.AddDefaultTokenProviders();
services.AddMvc(options => { options.Filters.Add(new RequireHttpsAttribute()); });
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
// 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.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
//Add external authentication middleware below.To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
var facebookOptions = new FacebookOptions
{
AppId = Configuration["Authentication:Facebook:AppId"],
AppSecret = Configuration["Authentication:Facebook:AppSecret"]
};
app.UseFacebookAuthentication(facebookOptions);
var googleOptions = new GoogleOptions
{
ClientId = Configuration["Authentication:Google:AppId"],
ClientSecret = Configuration["Authentication:Google:AppSecret"]
};
app.UseGoogleAuthentication(googleOptions);
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
}
}
До сих пор, так хорошо. Я запускаю проект, нажимаю ссылку «Вход», и я могу выбрать для входа в Google или Facebook. Я выбираю Google, и ... в первый раз, когда я пытаюсь, я получаю запрос на одобрение от Google и указываю на страницу «Реестр», где я создаю свою локальную учетную запись с псевдонимом и т. Д.
Теперь я могу пойти добавьте локальный пароль в мою учетную запись. Все работает плавно. Поэтому я выхожу из системы и снова пытаюсь войти в систему, используя мои учетные данные Google, после удаления моего файла cookie. Удивительно, но меня снова заносят на страницу «Регистрация», но я не могу зарегистрироваться, потому что я уже зарегистрирован. Мой локальный пароль также не будет работать.
Так что я копаю в это немного больше. В AccountController
существует метод, называемый ExternalLoginCallback
, где все волшебство, кажется, происходит. Мой метод выглядит следующим образом:
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
return View(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
return RedirectToAction(nameof(Login));
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);
if (result.Succeeded)
{
_logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
return RedirectToAction(nameof(SendCode), new
{
ReturnUrl = returnUrl
});
if (result.IsLockedOut)
return View("Lockout");
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
var firstName = info.Principal.FindFirstValue(ClaimTypes.GivenName);
var lastName = info.Principal.FindFirstValue(ClaimTypes.Surname);
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel
{
Email = email,
FirstName = firstName,
LastName = lastName
});
}
трассировать код, как он проходит через _signInManager.GetExternalLoginInfoAsync()
вызов, и ... результат NotAllowed
?
NotAllowed
является одним из 4-х возможных результатов, насколько я могу сказать, другие 3 будучи Succeeded
, RequiresTwoFactor
и IsLockedOut
. Остальные 3 значения отправляются где-то еще, поэтому я должен предположить, что NotAllowed
ожидается, когда локальная учетная запись не существует ... кроме того, что существует локальный счет.
Может кто-нибудь дать мне представление о том, что здесь происходит? Как только я подписываюсь с Google (или Facebook, там происходит то же самое), я не могу войти в систему с ними, и есть почти нулевая полезная обратная связь, чтобы определить, какова фактическая проблема.