iOS 12设备上的Facebook身份验证问题

时间:2018-10-05 16:31:50

标签: .net facebook asp.net-core facebook-authentication ios12

开始遇到版本12的iphone设备出现问题,facebook身份验证停止工作,我找不到发生这种情况的任何原因,当您单击按钮facebook auth时,Safari只是重定向到Facebook并立即返回应用程序。

从代码中,它触发了HttpPost方法 ExternalLogin ,然后使用HttpGet Login返回页面。它可以与其他设备一起使用,但不适用于iPhone 12版本。有人遇到此问题吗?另外,请注意,facebook api版本是2.7

这是我的代码:

<div class="form-group">
@{
    if (ViewBag.Shemas != null)
    {
        <form asp-controller="Account" asp-action="ExternalLogin" method="post" class="form-horizontal">
            <input id="ExtReturnUrl" data-val="true" name="ExtReturnUrl" asp-for="ExtReturnUrl" type="hidden" value="@Context.Request.Query["ReturnUrl"].ToString()">
            <div>
                <p>
                    @foreach (var provider in ViewBag.Shemas)
                    {
                        if (provider.DisplayName.Equals("Google"))
                        {
                            <button type="submit" class="btn btn-block text-uppercase btn-login-social  btn-login-google" id="Google" name="provider"
                                    value="Google" title="Log in using your Google account">
                                <i class="fa fa-google-plus-square"></i>Sign in via Google
                            </button>
                        }
                        else
                        {
                            <button type="submit" class="btn btn-block text-uppercase btn-login-social  btn-login-facebook" id="Facebook" name="provider"
                                    value="Facebook" title="Log in using your Facebook account">
                                <i class="fa fa-facebook-square"></i>Sign in via Facebook
                            </button>
                        }
                    }
                </p>
            </div>
        </form>
    }
}
@if (ViewData["Error"] != null)
{
    <span class="field-validation-error">@ViewData["Error"]</span>
}

并且来自控制器:

    [HttpGet("/account/login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login(string error = "", string returnUrl = "", string errorStateKey = null, string errorStateMessage = null)
    {
        if (!string.IsNullOrEmpty(returnUrl))
        {
            Request.QueryString.Add("ReturnUrl", returnUrl);
        }
        if (HttpContext.User.Identity.IsAuthenticated)
        {
            if (string.IsNullOrEmpty(returnUrl)) return RedirectToAction("Index", "Home");

            // Check if ReturnUrl is Wp Support Site Url>>
            var isAbsoluteReturnUrl = IsAbsoluteValidUrl(returnUrl);
            if (!isAbsoluteReturnUrl) return RedirectToAction("Index", "Home");

            var uriWpReturn = new Uri(returnUrl);
            var hostWpReturn = uriWpReturn.Host;

            var uriWp = new Uri(_wpOptions.Value.Host);
            var hostWp = uriWp.Host;
            if (hostWpReturn == hostWp)
            {
                returnUrl = string.Format(_wpOptions.Value.AutologinUrl, CurrentSalesPeople.Var1, returnUrl);
                return Redirect(returnUrl);
            }
            // << check if ReturnUrl is Wp Support Site


            return RedirectToAction("Index", "Home");
        }

        if (!string.IsNullOrEmpty(error))
        {
            ViewData["Error"] = error;
        }
        if (errorStateKey != null && errorStateMessage != null)
        {
            ModelState.AddModelError(errorStateKey, errorStateMessage);
        }
        return await ShowLoginViewAsync(null);
    }

    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> Login(LoginModel model)
    {
        if (!ModelState.IsValid) return await ShowLoginViewAsync(model);

        var validatePeople = await _authService.ValidateSalespeople(model.Login, model.Password);
        if (!validatePeople.Success)
        {
            var errorStateKey = "Password";
            var errorStateMessage = validatePeople.Message;
            if (!string.IsNullOrEmpty(model.ReturnUrl))
            {
                return RedirectToAction("Login", new { returnUrl = model.ReturnUrl, errorStateKey = errorStateKey, errorStateMessage = errorStateMessage });
            }
            ModelState.AddModelError(errorStateKey, errorStateMessage);
            return await ShowLoginViewAsync(model);
        }
        var salespeopleRole = await _roleService.GetRoleNameBySalespeopleId(validatePeople.Model.SId);
        if (!salespeopleRole.Success)
        {
            var errorStateKey = "";
            var errorStateMessage = validatePeople.Message;
            if (!string.IsNullOrEmpty(model.ReturnUrl))
            {
                return RedirectToAction("Login", new { returnUrl = model.ReturnUrl, errorStateKey = errorStateKey, errorStateMessage = errorStateMessage });
            }
            ModelState.AddModelError(errorStateKey, errorStateMessage);
            return await ShowLoginViewAsync(model);
        }
        var requestForDealerToolkit = await _dealerService.GetToolkitTypeBySalespeopleIddAsync(validatePeople.Model.SId);
        if (!requestForDealerToolkit.Success)
        {
            var errorStateKey = "";
            var errorStateMessage = "Problem with your toolkit subscription. Please tell a support about this error";
            if (!string.IsNullOrEmpty(model.ReturnUrl))
            {
                return RedirectToAction("Login", new { returnUrl = model.ReturnUrl, errorStateKey = errorStateKey, errorStateMessage = errorStateMessage });
            }
            ModelState.AddModelError(errorStateKey, errorStateMessage);
            return await ShowLoginViewAsync(model);
        }
        var getToolkit = GetToolkitTypeForSalespeople(validatePeople.Model.SubscriptionTypeId, requestForDealerToolkit.Model);

        var roleName = new RoleHelper(getToolkit, salespeopleRole.Model == "Manager").RoleName;
        if (roleName == "None")
        {
            var errorStateKey = "Password";
            var errorStateMessage = "You don't have permissions";
            if (!string.IsNullOrEmpty(model.ReturnUrl))
            {
                return RedirectToAction("Login", new { returnUrl = model.ReturnUrl, errorStateKey = errorStateKey, errorStateMessage = errorStateMessage });
            }
            ModelState.AddModelError(errorStateKey, errorStateMessage);
            return await ShowLoginViewAsync(model);
        }

        //We clear session before each login to prevent caching changes in new app vesrions 
        //HttpContext.Session.Clear();

        await Authenticate(validatePeople.Model, roleName, getToolkit);


        return Redirect(model.ReturnUrl);
    }

    private async Task<IActionResult> ShowLoginViewAsync(object model)
    {
        var schemeProvider = HttpContext.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
        var shemas = await schemeProvider.GetAllSchemesAsync().FromAsyncResult(z => z.Where(x => x.Name.Equals("Facebook") || x.Name.Equals("Google")).ToList());
        ViewBag.Shemas = shemas;
        return View(model);
    }


    [HttpPost]
    [AllowAnonymous]
    public IActionResult ExternalLogin(string provider, string extReturnUrl = null)
    {
        if (User.Identity.IsAuthenticated)
        {
            return RedirectToAction("Index", "Home");
        }
        // Request a redirect to the external login provider.
        var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = extReturnUrl });
        var properties = new AuthenticationProperties { RedirectUri = redirectUrl };
        return Challenge(properties, provider);
    }


    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
    {
        await HttpContext.SignOutAsync("Cookies");
        var externalModel = ExternalLoginModel.FromIdentity(HttpContext);

        if (externalModel != null)
        {
            var user = default(Salespeople);
            if (externalModel.Provider.Equals("Google"))
            {
                var request = await _salespeopleGetService.GetSalespeopleByPredicateAsNoTrackingAsync(p => p.GoogleKey.Equals(externalModel.Id));
                if (!request.Success)
                    return RedirectToAction("Login", new { error = "You do not have a connected google account", returnUrl = returnUrl });
                user = request.Model;
            }
            else if (externalModel.Provider.Equals("Facebook"))
            {
                var request = await _salespeopleGetService.GetSalespeopleByPredicateAsNoTrackingAsync(p => p.FacebookKey.Equals(externalModel.Id));
                if (!request.Success)
                    return RedirectToAction("Login", new { error = "You do not have a connected facebook account", returnUrl = returnUrl });
                user = request.Model;
            }
            return await Login(new LoginModel() { Login = user?.Email, Password = user?.Pass, ReturnUrl = returnUrl });
        }
        return RedirectToAction(nameof(Login));
    }



    private async Task Authenticate(Salespeople user, string role, int toolkitType)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, user.SId.ToString(), ClaimValueTypes.String),
            new Claim(ClaimsIdentity.DefaultNameClaimType, user.Email),
            new Claim(ClaimsIdentity.DefaultRoleClaimType, role),
            new Claim(ClaimTypes.UserData,toolkitType.ToString()),
            new Claim(ClaimTypes.Expiration, "")
        };
        ClaimsIdentity id = new ClaimsIdentity(claims, "ApplicationCookie", ClaimsIdentity.DefaultNameClaimType,
            ClaimsIdentity.DefaultRoleClaimType);
        _cpl = new ClaimsPrincipal(id);

        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, _cpl, (await _authService.GetAuthenticationPropertiesWithPermissions(user)).Model);
    }

1 个答案:

答案 0 :(得分:2)

在iOS 12中,Apple以其无限的智慧选择了使Safari的行为不同于其他所有浏览器。因此,如果您遵循ASP.NET Core中的最佳安全做法,则会破坏野生动物园中的社交身份验证。

here上有一条公告,其解决方法如下所示:

services.ConfigureExternalCookie(options =>
{
    // Other options
    options.Cookie.SameSite = SameSiteMode.None;
});
services.ConfigureApplicationCookie(options =>
{
    // Other options
    options.Cookie.SameSite = SameSiteMode.None;
});