简体   繁体   中英

Facebook Login works in localhost but not in webhost

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

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.

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:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM