Facebook Login works in localhost but not in webhost

非 Y 不嫁゛ 提交于 2019-12-11 00:39:12

问题


I have a class listed below:

public class FacebookScopedClient : IAuthenticationClient
{
    private string appId;
    private string appSecret;
    private string scope;

    private const string baseUrl = "https://www.facebook.com/dialog/oauth?client_id=";
    public const string graphApiToken = "https://graph.facebook.com/oauth/access_token?";
    public const string graphApiMe = "https://graph.facebook.com/me?";

    private  string GetHTML(string URL)
    {
        string connectionString = URL;

        try
        {
            var myRequest = (HttpWebRequest)WebRequest.Create(connectionString);
            myRequest.Credentials = CredentialCache.DefaultCredentials;
            //// Get the response
            WebResponse webResponse = myRequest.GetResponse();
            Stream respStream = webResponse.GetResponseStream();
            ////
            var ioStream = new StreamReader(respStream);
            string pageContent = ioStream.ReadToEnd();
            //// Close streams
            ioStream.Close();
            respStream.Close();
            return pageContent;
        }
        catch (Exception)
        {
        }
        return null;
    }

    private IDictionary<string, string> GetUserData(string accessCode, string redirectURI)
    {
        string token = GetHTML(graphApiToken + "client_id=" + appId + "&redirect_uri=" + HttpUtility.UrlEncode(redirectURI) + "&client_secret=" + appSecret + "&code=" + accessCode);
        if (string.IsNullOrEmpty(token))
        {
            return null;
        }
        string access_token = token.Substring(token.IndexOf("access_token=", StringComparison.Ordinal), token.IndexOf("&", System.StringComparison.Ordinal));
        token = access_token.Replace("access_token=", string.Empty);
        string data = GetHTML(graphApiMe + "fields=id,name,email,username,gender,link&" + access_token);

        // this dictionary must contains
        var userData = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
        userData.Add("access_token", token);
        return userData;
    }

    public FacebookScopedClient(string appId, string appSecret, string scope)
    {
        this.appId = appId;
        this.appSecret = appSecret;
        this.scope = scope;
    }

    public string ProviderName
    {
        get { return "facebook"; }
    }

    public void RequestAuthentication(System.Web.HttpContextBase context, Uri returnUrl)
    {
        string url = baseUrl + appId + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString()) + "&scope=" + scope;
        context.Response.Redirect(url);
    }

    public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context)
    {
        string code = context.Request.QueryString["code"];

        string rawUrl = context.Request.Url.OriginalString;
        //From this we need to remove code portion
        rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");

        IDictionary<string, string> userData = GetUserData(code, rawUrl);

        if (userData == null)
            return new AuthenticationResult(false, ProviderName, null, null, null);

        string id = userData["id"];
        string username = userData["username"];
        userData.Remove("id");
        userData.Remove("username");

        var result = new AuthenticationResult(true, ProviderName, id, username, userData);
        return result;
    }
}

The above class is registered in AuthConfig.cs Like so

OAuthWebSecurity.RegisterClient(
    new FacebookScopedClient("blablabla", "blablabla", 
        "read_stream,status_update,publish_actions,offline_access,user_friends"), "Facebook", facebooksocialData);

And I get to use this During authentication like so

[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
    AuthenticationResult result =
        OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));


    if (!result.IsSuccessful)
    {
        return RedirectToAction("ExternalLoginFailure");
    }
    if (result.ExtraData.Keys.Contains("access_token"))
    {
        Session["token"] = result.ExtraData["access_token"];


    }


    if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
    {
        return RedirectToLocal(returnUrl);
    }

    if (User.Identity.IsAuthenticated)
    {
        // If the current user is logged in add the new account
        OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
        return RedirectToLocal(returnUrl);
    }
    // User is new, ask for their desired membership name
    string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
    ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
    ViewBag.ReturnUrl = returnUrl;
    var client = new ComputerBeacon.Facebook.Graph.User("me", Session["token"].ToString());
    var firstName = client.FirstName;
    var lastName = client.LastName;
    var userName = client.Email;
    return View("ExternalLoginConfirmation",
                new RegisterExternalLoginModel
                    {
                        UserName = result.UserName,
                        FirstName = firstName,
                        LastName = lastName,
                        ExternalLoginData = loginData
                    });
}

Now this works 100% as expected in Localhost, but when I upload to a remote server, it does not work for some strange reason.

AuthenticationResult result =
        OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));

is never successful. Please what am I doing wrong. I have updated the neccessary URL's @ developers.facebook.com

thanks


回答1:


well I saw the problem.

public AuthenticationResult VerifyAuthentication(System.Web.HttpContextBase context)
    {
        string code = context.Request.QueryString["code"];

        string rawUrl = context.Request.Url.OriginalString;
        if (rawUrl.Contains(":80/"))
            {
            rawUrl = rawUrl.Replace(":80/", "/");
            }
        if (rawUrl.Contains(":443/"))
        {
            rawUrl = rawUrl.Replace(":443/", "/");
        }
        //From this we need to remove code portion
        rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");

        IDictionary<string, string> userData = GetUserData(code, rawUrl);

        if (userData == null)
            return new AuthenticationResult(false, ProviderName, null, null, null);

        string id = userData["id"];
        string username = userData["username"];
        userData.Remove("id");
        userData.Remove("username");

        var result = new AuthenticationResult(true, ProviderName, id, username, userData);
        return result;
    }

Thanks to http://savvydev.com/authenticating-facebook-users-with-mvc-4-oauth-and-obtaining-scope-permissions/ which where all these came from anyway

Thanks everyone for contributing.




回答2:


Facebook uses a url that you supply that's necessary for its Open Authentication. I suspect that you have that url set up for your localhost, in which case Facebook won't allow authentication requests from any other domain.

If that is indeed your case, you'll need to set up another Facebook App profile (call it "AppName Production" or something), and set up the site url for that app to the domain of your web host:

You'll find this setting under your app settings tab:



来源:https://stackoverflow.com/questions/22605305/facebook-login-works-in-localhost-but-not-in-webhost

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