SignInManager.ExternalSignInAsync在注册后始终返回SignInStatus.Failure

sam*_*n96 7 c# asp.net-mvc asp.net-mvc-4 asp.net-identity asp.net-web-api2

在我的混合MVC和WebAPI应用程序中,用于通过Google和Facebook进行身份验证的ExternalLoginCallback包含

var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
Run Code Online (Sandbox Code Playgroud)

即使在注册Google和Facebook之后,它总是SignInStatus.Failure

这是我的ExternalLoginCallback(默认值)

[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:
            if (returnUrl == null)
            {
                using (var context = ApplicationDbContext.Create())
                {
                    var user = context.Users.FirstOrDefault(x => x.Email.Equals(loginInfo.Email));
                    return RedirectToAction("Dashboard", "Provider");
                }
            }
            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.LoginProvider = loginInfo.Login.LoginProvider;

            return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的ExternalLoginConfirmation

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
{
    if (User.Identity.IsAuthenticated)
    {
        return RedirectToAction("Dashboard", "Provider");
    }

    if (ModelState.IsValid)
    {
        // Get the information about the user from the external login provider
        var info = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return View("ExternalLoginFailure");
        }
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        user.IsProvider = true;
        var result = await UserManager.CreateAsync(user);
        if (result.Succeeded)
        {
            result = await UserManager.AddLoginAsync(user.Id, info.Login);
            var provider = new Provider
            {
                UserId = user.Id,
                Id = Guid.NewGuid(),
                CompanyName = model.CompanyName,
                TierType = model.TierType
            };
            using (var context = ApplicationDbContext.Create())
            {
                context.Providers.Add(provider);
                await context.SaveChangesAsync();
            }
            if (result.Succeeded)
            {
                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                if (returnUrl != null)
                    return RedirectToLocal(returnUrl);
                else
                    return RedirectToAction("Dashboard", "Provider");
            }
        }
        AddErrors(result);
    }

    ViewBag.ReturnUrl = returnUrl;
    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

这是我的StartupConfigureAuth

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

    ///////////////////////////////////////
    PublicClientId = "self";
    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),
        Provider = new ApplicationOAuthProvider(PublicClientId),
        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
        AccessTokenFormat = new TicketDataFormat(app.CreateDataProtector(
           typeof(OAuthAuthorizationServerMiddleware).Namespace,
           "Access_Token", "v1")),
        AccessTokenProvider = new AuthenticationTokenProvider(),
        AllowInsecureHttp = true
        //TODO ^ change
    };

    // Enable the application to use bearer tokens to authenticate users
    //app.UseOAuthBearerTokens(OAuthOptions);
    //app.UseOAuthAuthorizationServer(OAuthOptions);

    //TODO ^ with v

    OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
    //OAuthBearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
    //OAuthBearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
    //OAuthBearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
    //OAuthBearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
    //OAuthBearerOptions.Description = OAuthOptions.Description;

    //OAuthBearerOptions.Provider = new ApplicationOAuthProvider();

    //OAuthBearerOptions.SystemClock = OAuthOptions.SystemClock;

    //This will used the HTTP header: "Authorization"      Value: "Bearer 1234123412341234asdfasdfasdfasdf"
    app.UseOAuthBearerAuthentication(OAuthBearerOptions);

    ///////////////////////////////////////////

    // Enable the application to use a cookie to store information for the signed in user
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login")
    });
    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: "");

    app.UseFacebookAuthentication(
        appId: "XXXX",
        appSecret: "XXXX");

    app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
    {
        ClientId = "XXXX",
        ClientSecret = "XXXX"
    });
}
Run Code Online (Sandbox Code Playgroud)