Facebook登录asp.net核心无效并返回500

时间:2017-04-15 15:07:50

标签: facebook asp.net-core

我一直在使用facebook登录我的一个asp.net核心项目。然而,它突然停止为Facebook登录工作。我收到HTTP 500错误。

问题是,即使在调试中,asp.net核心也没有提到任何错误。它只是500个错误代码。没别了。

当我尝试在public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null)函数的第一行设置断点时,我意识到它甚至没有达到那个并且在此之前就失败了。

我不确定如何进一步调试。我在这里错过了什么吗?或者登录方面的FB是否有任何变化?

被Facebook点击的返回网址是:

https://localhost:44300/signin-facebook?code=AQBxGGw7ZCoa9xtXc3CCsVGRD9TJLL428bZ_eJpUu4CtVu3K4UrfOZuYYdwFBXzGZ6GOGXpOi2Nme_jfbewB84otVZhKZfs4i7Dhi9Y3E_rloU9ouLeIvuOsm29jr7IDCtTj_HM7rKuKjj3zmc4yz5i_fniZ9ZhMfXtSus5KyKa4EFkZTsmKrz2ngMlGQalUAob_52GJNhvSIXDlmiNSrZLJV3m7Zbkf9eXETQkqhu2L1kgXPvWkMzVP8EN00GwRCYB3xT1kQMOimDANRKhziZjoVS5QZFUJTP0Faj47tE1xNfmAzb30iuwcaRORCOTMipUrnRvOO4nGRo8JuUNdPJaO&state=CfDJ8EHIO3qHMHFClr5BAt4EC1Wj7LyAs5Pg1XOqKo4uFiJM2Jr1rNyooxLIu2fbXr6Z3X5_kqbF_7WwFfvF3L3H4xgyooo-3Y9BV8Zh1S5wXlLJDAyCT5_LwkPJ1j8Zrwx4umQJp6NOl76GwRXpi1_BHlWGRxnh_naTL35iqeGovOa8oEDC0jOQ4trRe7YG3fV_ptjWk4yOnvJnsI81O-6wfyhdc3jm-LTP7ZO7-duf_lPZXZ8mL42XyLXDTIyOJ__S2yLYdvwItdDVntsM8Hwq94goXdU-RaH7ZkDA8iAzeCl3Ke0tWAdYBKy9vooJIXmE9Q#_=_

根据这篇文章,它在URL中也应该有state_token。但这似乎在这里缺失。我怎么能在这里弄清楚实际的错误是什么?

我正在使用asp.net核心RC2版本。

我的回调功能是:

public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null)
{
    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, isPersistent: 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");
    }
    else
    {
        // 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.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);

        if (email == null)
        {
            return View("Error");
        }

        /* Determine user from external login info */
        var name = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Name);
        string firstName;
        string lastName = "";
        if (!string.IsNullOrWhiteSpace(name))
        {
            firstName = name.Split(' ').Length > 1? name.Split(new[] { ' ' }, 2)[0] : name;
            lastName = name.Split(' ').Length > 1 ? name.Split(new[] { ' ' }, 2)[1] : "";
        }
        else
            firstName = email.Split('@')[0];

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            /* No user with same email ID. So, create a new user.*/
            var newUser = new ApplicationUser
            {
                UserName = email,
                Email = email,
                FirstName = firstName,
                LastName = lastName,
                PasswordLastModifiedTime = DateTime.UtcNow,
                UserSignUpDate = DateTime.UtcNow
            };

            var userCreationResult = await _userManager.CreateAsync(newUser);
            if (userCreationResult.Succeeded)
            {
                userCreationResult = await _userManager.AddLoginAsync(newUser, info);
                if (userCreationResult.Succeeded)
                {
                    // Add user claims TODO:// Test if the claims are added successfully.
                    await _userManager.AddClaimAsync(newUser, new Claim("FirstName", newUser.FirstName));
                    await _userManager.AddClaimAsync(newUser, new Claim("LastName", newUser.LastName));

                    // Set user email to confirmed. This is more of work around
                    var code = await _userManager.GenerateEmailConfirmationTokenAsync(newUser);
                    userCreationResult = await _userManager.ConfirmEmailAsync(newUser, code);
                    if (userCreationResult.Succeeded)
                    {
                        //Create Subscription for user
                        var planService = new PlanServices();
                        var plan = planService.Find((int)SubscriptionType.Basic);

                        await _subscriptionService.CreateSubscription(newUser, plan, null);

                        await _signInManager.SignInAsync(newUser, isPersistent: false);
                        _logger.LogInformation(6, "User created an account using {Name} provider.",
                            info.LoginProvider);
                        await _emailSender.SendWelcomeEmailAsync(newUser.Email, newUser.FirstName);
                        return RedirectToLocal(returnUrl);
                    }
                }
            }
        }
        else
        {
            /* A user with email ID exists. Associate the account with that.*/
            var loginAddResult = await _userManager.AddLoginAsync(user, info);
            if (loginAddResult.Succeeded)
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return RedirectToLocal(returnUrl);
            }
        }


        return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email, FirstName = firstName, LastName = lastName});
    }
}

ConfigureServices方法是:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddApplicationInsightsTelemetry(Configuration);

    services.AddScoped<ApplicationDbContext>();

    services.AddIdentity<ApplicationUser, IdentityRole>(o =>
    {
        o.Password.RequireDigit = false;
        o.Password.RequireLowercase = false;
        o.Password.RequireUppercase = false;
        o.Password.RequireNonLetterOrDigit = false;
        o.Password.RequiredLength = 8;
    })
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();


    services.AddCaching();

    services.AddSession();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.AddTransient<ISubscriptionService, SubscriptionService>();
    services.Configure<AuthMessageSenderOptions>(Configuration);
    services.Configure<RecaptchaOptions>(Configuration);

    __serviceProvider = services.BuildServiceProvider();
}

问题是,它长时间运作良好,现在已经停止工作了。此外,它甚至没有击中ExternalLoginCallback,所以我不确定在哪里进一步调试它。

2 个答案:

答案 0 :(得分:0)

你应该升级到asp.net核心RC3版本......开个玩笑

这个 state = 是state_token。查看您发布的返回网址。

请发布有关身份验证中间件配置的ConfigureServices方法的代码

HTTP 500错误表明您网站的服务器存在问题...

希望这会有所帮助......

答案 1 :(得分:0)

@skjoshi,你的ExternalLoginCallback方法很好,并且在那里找不到错误的来源。

请注意,您发布的返回网址格式如下: https://localhost:44300/signin-facebook?code=AUTH_CODE&state=STATE_TOKEN

如果仔细查看问题中弹出的网址文字,您会发现代码和状态。此网址代表Facebook 初始重定向到您的ASP.NET应用程序,作为回报,它向Facebook发送请求以交换AUTH_CODE 使用访问令牌...在应用程序服务器和Facebook服务器之间的通信中的某个地方 出现问题,因此不会触及ExternalLoginCallback。

您是否在Configure方法中启用了以下内容:

app.UseFacebookAuthentication(options =>
            {
                options.AppId = Configuration["Authentication:Facebook:AppId"];
                options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
            });