2

I want to use "Require App Secret" (Require app secret for server API calls) on my facebook app, But if I do - I'm getting the following error:

(GraphMethodException - #100) No appsecret_proof parameter was specified

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: Facebook.FacebookApiException: (GraphMethodException - #100) No appsecret_proof parameter was specified

Source Error:

Line 801: var fb = new FacebookClient(accessToken); Line 802: Line 803: dynamic facebookInfo = fb.Get("/me?appsecret_proof=" + fb.AppSecret + "&fields=email,birthday,gender"); Line 804: signInInfo.Email = facebookInfo.email; Line 805:

I saw this post, so I'm trying to understand how to send it... do I need to switch to fb.Post ?

Also, I wonder if the SDK does not already have something like "GenereateFaceBookSecret()"

Thanks in advance.

Community
  • 1
  • 1
Yovav
  • 2,557
  • 2
  • 32
  • 53

1 Answers1

17

SOLVED! finally... and working with the new facebook APIs v2.4

So maybe I can save someone else 6 hours :-)

I created this little helper class:

namespace YouProjectNamespace.Helpers 
{
    using System.Security.Cryptography;
    using System.Text;

    /// <summary>
    /// Facebook Helper
    /// </summary>
    public static class FacebookHelper
    {
        /// <summary>
        /// Generate a facebook secret proof (works with facebook APIs v2.4)
        /// <seealso cref="http://stackoverflow.com/questions/20572523/c-sharp-help-required-to-create-facebook-appsecret-proof-hmacsha256"/>
        /// </summary>
        /// <param name="facebookAccessToken"></param>
        /// <param name="facebookAuthAppSecret"></param>
        /// <returns></returns>
        public static string GenerateFacebookSecretProof(string facebookAccessToken, string facebookAuthAppSecret)
        {
            byte[] keyBytes = Encoding.UTF8.GetBytes(facebookAuthAppSecret);
            byte[] messageBytes = Encoding.UTF8.GetBytes(facebookAccessToken);
            HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes);
            byte[] hash = hmacsha256.ComputeHash(messageBytes);
            StringBuilder sbHash = new StringBuilder();
            
            for (int i = 0; i < hash.Length; i++)
            {
                sbHash.Append(hash[i].ToString("x2"));
            }

            return sbHash.ToString();
        }
    }
}

And this is how to use it:

// Use Facebook SDK for .NET to get more specific data (https://github.com/facebook-csharp-sdk/facebook-csharp-sdk)

var identity = AuthenticationManager.GetExternalIdentity(DefaultAuthenticationTypes.ExternalCookie);
var facebookAccessToken = identity.FindFirstValue("FacebookAccessToken");
var fb = new FacebookClient(facebookAccessToken);

var facebookAuthAppSecret = "Use_Your_Own_Facebook_AppSecret_Here";
var facebookAppSecretProof = FacebookHelper.GenerateFacebookSecretProof(facebookAccessToken, facebookAuthAppSecret);

dynamic facebookInfo = fb.Get(string.Format("/me?appsecret_proof={0}&fields=email,birthday,gender", facebookAppSecretProof));
signInInfo.Email = facebookInfo.email;

I should add that a claim should be added in order to use facebook SDK, This is what I have in Startup.Auth.cs

            #region Facebook

            // https://developers.facebook.com/apps
            // https://developers.facebook.com/docs/facebook-login/permissions/v2.4
            // https://developers.facebook.com/docs/graph-api/reference/v2.4/post
            // https://developers.facebook.com/docs/apps/changelog#v2_4
            // https://developers.facebook.com/docs/graph-api/reference/user

            var facebookAuthOptions = new FacebookAuthenticationOptions();

            facebookAuthOptions.AppId = facebookAuthAppId;
            facebookAuthOptions.AppSecret = facebookAuthAppSecret;
            facebookAuthOptions.SendAppSecretProof = true;

            // public_profile (Default) includes: id,name,first_name,last_name,age_range,link,gender,locale,timezone,updated_time,verified
            facebookAuthOptions.Scope.Add("public_profile");
            facebookAuthOptions.Scope.Add("email");
            facebookAuthOptions.Scope.Add("user_birthday");
            facebookAuthOptions.Scope.Add("user_location"); // current city through the location field on the User object

            facebookAuthOptions.Provider = new FacebookAuthenticationProvider()
            {
                OnAuthenticated = (context) =>
                {
                    // http://stackoverflow.com/questions/7999934/facebook-c-sharp-sdk-problems-getting-user-email/8013211#8013211
                    // http://blogs.msdn.com/b/webdev/archive/2013/10/16/get-more-information-from-social-providers-used-in-the-vs-2013-project-templates.aspx
                    // Get the access token from FB and store it in the database and use FacebookC# SDK to get more information about the user
                    context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));

                    var expiryDuration = context.ExpiresIn ?? new TimeSpan();
                    context.Identity.AddClaim(new Claim("facebook:expires_in", DateTime.UtcNow.Add(expiryDuration).ToString(CultureInfo.InvariantCulture)));

                    // Add all other available claims
                    foreach (var claim in context.User)
                    {
                        var claimType = string.Format("facebook:{0}", claim.Key);
                        var claimValue = claim.Value.ToString();
                        if (!context.Identity.HasClaim(claimType, claimValue))
                            context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, "XmlSchemaString", "Facebook"));
                    }

                    return Task.FromResult(0);
                }
            };
            app.UseFacebookAuthentication(facebookAuthOptions);

            #endregion Facebook
Yovav
  • 2,557
  • 2
  • 32
  • 53
  • 1
    You are the first person I've seen who can correctly explain the data format of the Access Token, App Secret and App Secret Proof. It has taken 6 hours, but I'm sure you saved me many more! – Hand-E-Food Jun 13 '16 at 12:16
  • 1
    You are the chosen one! – Hudson Jan 26 '18 at 21:04
  • If i could give you a hundred up-votes i would, this sort of thing should be part of of the FB API documentation. – jv_ Apr 15 '18 at 10:05