SignInManager.ExternalSignInAsync with Facebook always returns failure

非 Y 不嫁゛ 提交于 2020-01-06 02:41:54

问题


Google+ works, but Facebook always returns a failure. When I examine loginInfo it shows that authenticated = true.

This is the code in Statup.Auth.cs - I included the Google+ code which works.

public void ConfigureAuth(IAppBuilder app)
        {
            // Configure the db context, user manager and signin manager to use a single instance per request
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

            // Enable the application to use a cookie to store information for the signed in user
            // and to use a cookie to temporarily store information about a user logging in with a third party login provider
            // Configure the sign in cookie
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                Provider = new CookieAuthenticationProvider
                {
                    // Enables the application to validate the security stamp when the user logs in.
                    // This is a security feature which is used when you change a password or add an external login to your account.  
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));

            // Enables the application to remember the second login verification factor such as phone or email.
            // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
            // This is similar to the RememberMe option when you log in.
            app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

            // Uncomment the following lines to enable logging in with third party login providers
            //app.UseMicrosoftAccountAuthentication(
            //    clientId: "",
            //    clientSecret: "");

            //app.UseTwitterAuthentication(
            //   consumerKey: "",
            //   consumerSecret: "");

            var options = new FacebookAuthenticationOptions();
            options.Scope.Add("email");
            options.Scope.Add("friends_about_me");
            options.Scope.Add("friends_photos");
            options.AppId = "xxxxxxxxx";
            options.AppSecret = "xxxxxxx";
            options.Provider = new FacebookAuthenticationProvider()
           {
               OnAuthenticated = context =>
                   {

                       var userDetail = context.User;

                       string id = (dynamic)context.Id;

                       string emmail = (dynamic)context.Email;

                       var currentUser = UserManager.FindByName(emmail);
                       if (currentUser.UserProfile == null)
                       {
                           currentUser.EmailConfirmed = true;

                           try
                           {
                               currentUser.UserProfile = new UserProfile
                               {
                                   UserProfileId = currentUser.ToString(),
                                   Avatar = ConvertImageURLToBase64(@"https://graph.facebook.com/" + id + "/picture?type=large"),
                                   LastName = ((dynamic)context.User).first_name.Value,
                                   FirstName = ((dynamic)context.User).last_name.Value,
                                   MemberSince = DateTime.Now.Date,
                                   ProfileVisibility = "Private",
                                   ZipCode = "0",
                               };
                               UserManager.Update(currentUser);
                           }
                           catch (Exception ex)
                           {
                               string x = ex.StackTrace.ToString();
                           }
                       }
                       return System.Threading.Tasks.Task.FromResult(0);
                   }
           };
            app.UseFacebookAuthentication(options);


            app.UseGooglePlusAuthentication(new GooglePlusAuthenticationOptions()
            {
                ClientId = "xxxxxxx",
                ClientSecret = "xxxxx",
                Provider = new GooglePlusAuthenticationProvider()
                {

                    OnAuthenticated = context =>
                    {
                        var userDetail = context.Person;
                        context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirstValue(ClaimTypes.Name)));
                        context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Identity.FindFirstValue(ClaimTypes.Email)));
                        string id = ((dynamic)context.Person).id;
                        string emmail = ((dynamic)context.Person).emails[0].value.Value;
                        var currentUser = UserManager.FindByName(emmail);
                        if (currentUser.UserProfile == null)
                        {
                            currentUser.EmailConfirmed = true;

                            currentUser.UserProfile = new UserProfile
                            {
                                UserProfileId = currentUser.ToString(),
                                Avatar = ConvertImageURLToBase64(((dynamic)context.Person).image.url.Value),
                                LastName = ((dynamic)context.Person).name.familyName.Value,
                                FirstName = ((dynamic)context.Person).name.givenName.Value,
                                MemberSince = DateTime.Now.Date,
                                ProfileVisibility = "Private",
                                ZipCode = "0"
                            };
                            UserManager.Update(currentUser);
                        }

                        return System.Threading.Tasks.Task.FromResult(0);
                    },
                },
            });
        }

This is the AccountController.cs - Google+ works, but Facebook does not.

[AllowAnonymous]
        public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
        {
            var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
            if (loginInfo == null)
            {
                return RedirectToAction("Login");
            }

            // Sign in the user with this external login provider if the user already has a login
            var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
            switch (result)
            {
                case SignInStatus.Success:
                    return RedirectToLocal(returnUrl);
                case SignInStatus.LockedOut:
                    return View("Lockout");
                case SignInStatus.RequiresVerification:
                    return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
                case SignInStatus.Failure:
                default:
                    // If the user does not have an account, then prompt the user to create an account
                    ViewBag.ReturnUrl = returnUrl;
                    ViewBag.L`enter code here`oginProvider = loginInfo.Login.LoginProvider;
                    return View("ExternalLoginConfirmation", new ExternalLogi![enter image description here][1]nConfirmationViewModel { Email = loginInfo.Email });
            }
        }

回答1:


As it turns out the code is working. I was thinking I could wire up and existing user as a Facebook user when the Facebook user email matched the user id (Which is email), but that is not the case and after thinking about it it makes sense. You have to associate the Facebook user with a new user.




回答2:


Add the following line to your Startup.cs class:

 app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

It will solve the issue.



来源:https://stackoverflow.com/questions/27550825/signinmanager-externalsigninasync-with-facebook-always-returns-failure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!