MVC5 和 OWIN facebook 身份验证提供程序在 IE11 和 Firefox 中不工作(但在 Chrome 中工作)

MVC5 and OWIN facebook authentication provider not working in IE11 and Firefox (but works in Chrome)

我正在使用 Asp.Net MVC 5 并利用 Microsoft 的身份 (v2) 实现进行身份验证和外部 (facebook) 登录。

我的外部登录代码是这样的:

在 Startup.Auth.cs 我声明提供者:

var facebookAuthenticationOptions = new FacebookAuthenticationOptions();
        facebookAuthenticationOptions.Scope.Add("email");
        (...)
        facebookAuthenticationOptions.AppId = "<my fb app id>";
        facebookAuthenticationOptions.AppSecret = "<my fb app secret>";
        facebookAuthenticationOptions.Provider = new FacebookAuthenticationProvider()
        {
            OnAuthenticated = async context =>
            {
                //Get the access token from FB and store it in the database
                context.Identity.AddClaim(
                new System.Security.Claims.Claim("FacebookAccessToken",
                                                     context.AccessToken));
            }
        };
        app.UseFacebookAuthentication(facebookAuthenticationOptions);

在我 post facebook 登录表单的控制器函数中,

[HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {

        returnUrl = !String.IsNullOrEmpty(returnUrl) ? returnUrl : "/";

        // Request a redirect to the external login provider
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
        return null;
    }

在我的基本控制器中使用这个(我从中派生出所有控制器),我使用 owin OAuth:

internal class ChallengeResult : HttpUnauthorizedResult
    {
        public ChallengeResult(string provider, string redirectUri)
            : this(provider, redirectUri, null)
        {
        }

        public ChallengeResult(string provider, string redirectUri, string userId)
        {
            LoginProvider = provider;
            RedirectUri = redirectUri;
            UserId = userId;
        }

        public string LoginProvider { get; set; }
        public string RedirectUri { get; set; }
        public string UserId { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
            if (UserId != null)
            {
                properties.Dictionary[XsrfKey] = UserId;
            }
            context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
        }

    }

然后我通过外部回调函数获得回调(正如我在上面的 ChallangeResult 对象中声明的那样):

[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)
        {

        // login logic code here.    
        // and return some View(""); or RedirerctToAction("somewhere");
        }

    }

另外值得注意的是,我正在使用 StructureMap 3.0 进行依赖注入,并且根据以下代码,它将任何控制器代码的生命周期限制为请求的生命周期。

public void Init(HttpApplication context) {
        context.BeginRequest += (sender, e) => StructuremapMvc.StructureMapDependencyScope.CreateNestedContainer();
        context.EndRequest += (sender, e) => {
            HttpContextLifecycle.DisposeAndClearAll();
            StructuremapMvc.StructureMapDependencyScope.DisposeNestedContainer();
        };
    }

现在,这一切都很好,当我 运行 来自 chrome 的应用程序时,它确实为我处理了 facebook 登录。但是当我使用 Internet Explorer(尝试过 11)或 Firefox 时,它在 /{controller}/ExternalLogin 处挂在黑屏中并且不进行任何重定向。

如果这是 IOC 包含结构图的问题,我相信它也不应该在 chrome 上顺利地 运行。所以我一直在网上搜索,但找不到解决方案 - 或任何关于正在发生的事情的迹象。而且由于我没有得到任何异常之类的信息,所以我无法弄清楚我做错了什么。

总结一下:

谢谢。

好吧,我想的有点太复杂了。问题出在我正在 posting 的输入标签中。

如果您的 post 操作采用 public ActionResult ExternalLogin(string provider, string returnUrl) 之类的表单数据(即无模型),并且您使用输入图像的名称和值来提供该表单操作,例如:

<input type="image" id="@facebookLogin.AuthenticationType" name="provider" value="@facebookLogin.AuthenticationType"...>

然后,出于某种原因 Chrome 发送正确的 post 数据,而 Internet Explorer 和 Firefox 不能。

所以没有依赖注入、中间件或 OAuth 问题,只是普通的旧 html 这个问题。