Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getLoginStatus returns status unknown when trying to logout from Facebook using Facebook JS SDK

I have a localhost website, where I've implemented login via Facebook using Facebook C# SDK.

Startup configuration class:

    public class ExternalLoginConfig
    {
        public void ConfigureAuth(IAppBuilder app)
        {
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
            {
                AppId = ConfigSettings.FacebookAppId,
                AppSecret = ConfigSettings.FacebookAppSecret,
                Scope = { "email" },
                Provider = new FacebookAuthenticationProvider()
                {
                    OnAuthenticated = context =>
                    {
                        var accessToken = context.AccessToken;
                        var facebookClient = new FacebookClient(accessToken);

                        var result = facebookClient.Get("me", new { fields = "email,first_name,last_name" }) as JsonObject;

                        string email = null;
                        string firstName = null;
                        string lastName = null;

                        if (result != null)
                        {
                            email = result.ContainsKey("email") ? (string) result["email"] : null;
                            firstName = result.ContainsKey("first_name") ? (string) result["first_name"] : null;
                            lastName = result.ContainsKey("last_name") ? (string) result["last_name"] : null;
                        }

                        if (firstName != null)
                        {
                            context.Identity.AddClaim(new Claim(ClaimTypes.GivenName, firstName));
                        }
                        if (lastName != null)
                        {
                            context.Identity.AddClaim(new Claim(ClaimTypes.Surname, lastName));
                        }
                        if (email != null)
                        {
                            context.Identity.AddClaim(new Claim(ClaimTypes.Email, email));
                        }

                        return Task.FromResult(0);
                    },
                    OnApplyRedirect = context =>
                    {
                        context.Response.Redirect(context.RedirectUri + "&auth_type=reauthenticate");
                    }
                }
            };
            app.UseFacebookAuthentication(facebookAuthenticationOptions);
        }
    }

Actions form Authentication controller:

    [HttpPost]
    [AllowAnonymous]
    public virtual ActionResult Login(string provider, string returnUrl)
    {
        ControllerContext.HttpContext.Session.RemoveAll();

        return new ExternalLoginResult(provider,
            Url.Action("LoginCallback", "Oauth", new { ReturnUrl = returnUrl }));
    }

    [AllowAnonymous]
    public async Task<ActionResult> LoginCallback(string returnUrl, string error)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

        if (loginInfo == null)
        {
            return Redirect(returnUrl);
        }

        User user = null;
        string userName = Guid.NewGuid().ToString();
        string firstName = loginInfo.ExternalIdentity.FindFirstValue(ClaimTypes.GivenName);
        string lastName = loginInfo.ExternalIdentity.FindFirstValue(ClaimTypes.Surname);
        string email = loginInfo.ExternalIdentity.FindFirstValue(ClaimTypes.Email);
        string externalProviderName = loginInfo.Login.LoginProvider;
        string externalProviderKey = loginInfo.Login.ProviderKey;

        var externalAuthenticationInfo = new ExternalAuthenticationInfo()
        {
            Username = userName,
            Email = email,
            FirstName = firstName,
            LastName = lastName,
            ExternalProviderName = externalProviderName,
            ExternalProviderKey = externalProviderKey
        };

        var loginResult = userProvider.ExternalLogin(externalProviderKey, email, out user);

        switch (loginResult)
        {
            case LoginResult.Success:
            {
                AuthenticationHelper.SetAuthenticatedUserId(user.ID);
                break;
            }
            case LoginResult.NotRegistered:
            {
                var registerResult = userProvider.Register(userName, email, null, externalAuthenticationInfo);

                if (registerResult.IsValid)
                {
                    AuthenticationHelper.SetAuthenticatedUserId(registerResult.Result.ID);
                }

                break;
            }
        }

        return Redirect(returnUrl);
    }

Facebook JS SDK initialization:

    window.fbAsyncInit = function () {
        FB.init({
            appId: '@ConfigSettings.FacebookAppId',
            xfbml: true,
            version: 'v2.4'
        });
    };

    (function (d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) { return; }
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));

I'm attempting to log a user out of facebook with the Facebook JS SDK, however calling:

    FB.getLoginStatus(function facebookLogoutCallback(facebookResponse) {
        if (facebookResponse.status !== 'connected') {
            return;
        }

        FB.logout(facebookLogoutCallback);
    });

leads to status unknown instead of connected, which is returned in facebookResponse object. I've also tried to call FB.logout() without if statement, but it didn't work.

Maybe you can say, that this behavior is caused by unauthorized user status, but after server side login the user is actually logged in: on my website and Facebook too.

like image 774
iOne Avatar asked Jan 11 '16 15:01

iOne


1 Answers

It seems that there's a bug currently in the FB.logout function. After calling it the user can not be logged into this App again using the JS SDK because the FB.login function returns
Object { status="unknown", authResponse=null}

EDIT:
Found that there's a cookie called "fblo_*" created after FB.logout() which seems to be the reason for this. I can't say exactly why it's there and what it does, but deleting it makes the login work again.

Therefor I created a small script that looks for this cookie and deletes it just before I call FB.login() which you probably want to call in a click event (https://developers.facebook.com/docs/reference/javascript/FB.login/v2.5).

function delete_cookie(name) 
{
    document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';
}


var cookies = document.cookie.split(";");
for (var i = 0; i < cookies.length; i++)
{
    if(cookies[i].split("=")[0].indexOf("fblo_") != -1)
        delete_cookie(cookies[i].split("=")[0]);
}
like image 189
Milan O Avatar answered Nov 01 '22 03:11

Milan O