10

Closed

"Invalid signed request" exception when parsing fbsr cookie

description

I start saying that my webapp worked fine until yesterday, so something must have changed Facebook side.

I'm using Facebook C# SDK version 5.4.1.0.
My website is accessible at, say, http://my.website.com.
When a user visits the homepage, I use the FB Javascript library to login the user and authorize the application:

window.fbAsyncInit = function() {
FB.init({
appId: 'my-app-id',
channelUrl: '...',
status: true,
cookie: 'my.website.com',
xfbml: true,
oauth: true
});
};

(function(d) {
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) { return; }
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/it_IT/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
} (document));

...
at some point, after init has been executed:

FB.login(function(response) {
// reload page
}, { scope: 'user_birthday,email,publish_stream,publish_actions,offline_access' });

After FB.init is called, a first fbsr_my-app-id cookie is created for domain my.website.com, containing the oauth 2.0 signed request.
After FB.login is called, and user has authorized the app, another fbsr_my-app-id is created for domain .my.website.com (notice the dot at the beginning), containing another signed request. Another cookie is created too at this point, named fbm_my-app-id, for domain .my.website.com (notice the dot again), whose value is:

base_domain=my.website.com

When the page is reloaded after login, i call FacebookWebContext.IsAuthorized to check if my app has been authorized. That method parses the fbsr cookie in order to read and decode the signed request.
The problem is that the browser (i tried this with chrome 16 and firefox 9) sends both the fbsr cookies, without domain information. When i call IsAuthorized, and the method reads the fbsr cookie, .net returns the values of the two cookies concatenated with a comma, like "FIRSTFBSRCOOKIEVALUE,SECONDFBSRCOOKIEVALUE". So now the concatenated value contains two dots (one from each cookie value). The parsing method doesn't expect that, and throws an exception because the cookie value is malformed. The stack trace of the exception is as follows:

Type : System.InvalidOperationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Invalid signed request.
Source : Facebook.Web
TryParse(System.String, System.String, Int32, Double, Boolean)
Stack Trace : at Facebook.FacebookSignedRequest.TryParse(String secret, String signedRequestValue, Int32 maxAge, Double currentTime, Boolean throws) in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookSignedRequest.cs:line 486
at Facebook.FacebookSignedRequest.Parse(String secret, String signedRequestValue) in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookSignedRequest.cs:line 253
at Facebook.FacebookSignedRequest.GetSignedRequest(String appId, String appSecret, HttpContextBase httpContext) in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookSignedRequest.cs:line 349
at Facebook.FacebookSession.GetSession(IFacebookApplication settings, HttpContextBase httpContext, FacebookSignedRequest signedRequest) in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookSession.cs:line 367
at Facebook.FacebookSession.GetSession(IFacebookApplication settings, HttpContextBase httpContext) in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookSession.cs:line 326
at Facebook.Web.FacebookWebContext.get_Session() in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookWebContext.cs:line 136
at Facebook.Web.FacebookWebContext.IsAuthenticated() in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookWebContext.cs:line 218
at Facebook.Web.FacebookWebContext.IsAuthorized(String[] permissions) in d:\prabir\Documents\Projects\facebooksdk\v5.4.1\Source\Facebook.Web\FacebookWebContext.cs:line 238
... my method calls

The exception is thrown inside Facebook.FacebookSignedRequest.TryParse, line 412:

string[] split = signedRequestValue.Split('.');
if (split.Length != 2)
{
// need to have exactly 2 parts
throw new InvalidOperationException(Properties.Resources.InvalidSignedRequest);
}

My facebook configuration in web.config is:

<facebookSettings appId = "my-app-id" appSecret = "my-app-secret" canvasPage="http://apps.facebook.com/my-app" canvasUrl="http://my.website.com:8091/" secureCanvasUrl="https://my.website.com:8091/" />

I use port 8091 for security reasons, maybe that can be the cause of FB creating two cookies.

I've read some blog posts saying that browsers, in case of multiple cookies with the same name, should always send just one of the cookies, although it's not specified how they should choose the cookie. Anyway i can confirm that the latest versions of both chrome and firefox send all the cookies even if they have the same name.

Maybe the key is in the fbm cookie, which tells which is domain of the right fbsr cookie; however, this information cannot be used server-side, because domain information of cookies is lost.

Please help me or share a possible solution if you've had this problem; I must ship a big fb application by the end of the month and suddenly its core part stopped working :(
Feel free to ask for additional details, bye
lorenzo

No files are attached

Closed Feb 6 at 6:35 PM by ntotten
Migrated to github: https://github.com/facebook-csharp-sdk/facebook-csharp-sdk/issues/62

comments

tlianza wrote Jan 19 at 4:59 PM

Seems the root cause is a facebook bug, however in handling this error in our applications, I think it would be preferable if the SDK threw an Exception that derives from FacebookApiException instead of an InvalidOperationException in this case. Currently, callers need to rescue a list of different Exception types if they want to handle this gracefully.

jcargilo wrote Jan 18 at 8:46 PM

The double cookie issue for me happened when a user logged into my site (using FB.Login) with their FB account, switched to viewing facebook as a fan page, and then attempted to go back to my site and navigate around using the previous login. Changing the cookie setting from true to 'mydomain.com' appears to have resolved it.

nirnoy wrote Jan 16 at 9:10 AM

i'm guessing that what facebook had changed was the FB.login() method, it sets a fbsr_appid cookie with domain ".yourdomain.com".
now when the FB.init is called with cookie:true it sets a cookie with domain 'www.yourdomain.com'
then you have a duplicate cookie and you the Invalid signed request error.
the way i resolved it for now is to set the cookie in the init method to my base domain ("yourdomain.com") and on my login page load removed any "fbsr" of "fbm" cookie that has domain set to "www.yourdomain.com".

lorenzocarrara wrote Jan 13 at 1:15 PM

I followed your advice (putting the domain in the cookie config) but I'm still having the problem.
In FB.init i use cookie: 'my.domain.com'
The application is configured with domain 'my.domain.com'.
After deleting the cookies, the application works for a while, but at some point the double cookie is created again. In my case, i have two couples of fbsr/fbm cookies, one for domain '.my.domain.com' and one for '.domain.com'.
At first I thought it was a problem on the Facebook C# SDK side, which created additional cookies with wrong domains, but I've checked the source code of the current stable version (5.4.1.0) and no cookie is created whatsoever, so it must be facebook.
Follow the discussion on https://developers.facebook.com/bugs/359391590741517 too for updates.

okinsey wrote Jan 12 at 5:53 PM

@lorenzocarrara You can resolve this by setting cookie: 'yourbasedomain' instead of cookie: true in init. This should make the domain used consistent.
Let me know if this helps.

actstudio wrote Jan 12 at 3:59 PM

have the same issue. It was working fine until today. I have the app created in sitecore, so I am using the code for multiple domains / fb apps.

ERROR: Invalid signed request.
Line 329: if (!fbContext.IsAuthorized(extendedPermissions))
Line 330: {

npiaseck wrote Jan 12 at 12:54 PM

I'm seeing the same issue ... vote for this bug https://developers.facebook.com/bugs/359391590741517