Facebook server side authentication with partial permission - facebook-graph-api

I'm using server side authentication for Facebook detailed on this page.
https://developers.facebook.com/docs/howtos/login/server-side-login/#step5
I'm asking for extended permissions like user_birthday and if the user accepts, I get the code
YOUR_REDIRECT_URI?
state=YOUR_STATE_VALUE
&code=CODE_GENERATED_BY_FACEBOOK
But if let's say the user declined to provide birthday, I still want to proceed when I get this url
YOUR_REDIRECT_URI?
error_reason=user_denied
&error=access_denied
&error_description=The+user+denied+your+request.
&state=YOUR_STATE_VALUE
Does anyone know how to get the code under that scenario or do I have to ask the user to signin again but this time not asking for additional permissions?
Cheers,
Steve

Does anyone know how to get the code under that scenario or do I have to ask the user to signin again but this time not asking for additional permissions?
There are two scenarios here:
You are asking the user to connect to your app for the first time. At this point, they can not decline giving you user_birthday permission solely (since it’s a basic and not an extended permission) – they either connect to your app, or they don’t.
The user has connected to your app before, and now you are asking for user_birthday permission. If the user declines that, that will lead to the error_reason=user_denied – and then you will not get a code parameter.
In the 2nd scenario, when using the server-side flow, asking the user again (maybe with a reduced set of permissions) is the only way to go – unless you have already gotten an access token before. That will not get invalidated – but it will obviously only contain permissions already given before.
(If the user connected to your app before, you can just call the Auth dialog with no scope parameter at all – in that case Facebook will redirect straight back to your app with a code parameter. Or you could get the token beforehand client-side, for example by calling FB.getLoginStatus.)

Related

Access Facebook page statuses with an app access token

Reading the API docs (https://developers.facebook.com/docs/reference/api/page/) I assumed that in order to read a public pages status updates, I would require "any valid access_token or user access_token" (quoting the docs here).
However, if I try to get the status updates for the public page, using my app access token, I receive the following response: "A user access token is required to request this resource"
GET 20531316728/statuses?access_token=myappaccesstoken
So, my question is if the docs are just plain wrong, I'm doing something wrong or whatever?
There is a clarification that needs to occur by Facebook [1]. The docs are either outdated or Facebook has changed their mind on handling these updates which is interesting seeing that
GET /PAGE_ID/feed?access_token=myappaccesstoken
Works (and holds all the statuses). I was told by someone in IRC #facebook that maybe the statuses call is more expensive (Not too bought on this idea).
My current stance is that either
any valid access_token or user access_token was supposed to imply those excluding app tokens
Facebook realizes that one can bypass the OAuth Flow by using an app token on pages when Facebook desired some form of authentication.
In the end, these are all assumptions.
I haven't been able to get a clear answer out of any Facebook employee as to whether this is indeed a bug or an intentional removal of this feature.
[1] - http://developers.facebook.com/bugs/480742545315442

Request a Page Access Token in C# SDK

As a proof of concept for a simple background application, I used the Graph API Explorer to create an access token for my app to post something to the wall of a page I maintain. It worked fine. Naturally, however, the token expires.
So now I'm trying to have the background application automatically request a new page access token each time it runs. And I'm having a lot of trouble finding a concrete definition of how to do that. There's no shortage of information regarding Facebook and Access Tokens, but nothing seems to demonstrate how to have a background application post to a page. (Not post to a user's wall, not display a login dialog to a user since it's a background application, etc.)
I can fetch an access token in code easily enough by reading the response from a web request to this URL:
https://graph.facebook.com/oauth/access_token?grant_type=client_credentials&client_id={MY_APP_ID}&client_secret={MY_APP_SECRET}
Of course, that "access token" doesn't work when trying to post to the page's wall. It says that the user hasn't authorized the application to perform this action. The action I'm performing is pretty simple:
var client = new FacebookClient(GetFacebookAccessToken());
dynamic parameters = new ExpandoObject();
parameters.message = "this is a test";
dynamic result = client.Post("{MY_PAGE_ID}/feed", parameters);
I've read in some places that I'll need to make a second request, using the first access token, to get the page access token. But I can't seem to find examples of how to do that.
Can someone shed some light on this for me?
I have a Facebook page.
I have a Facebook app which serves no other purpose than to provide a means for a local background application to access said page.
I just need that application to be able to authenticate so it can post something to the page.
(And if there's a step I need to perform in the Facebook UI to permanently give the application permission to do this, I think I've performed that step but it would be good to double check somehow.)
Edit: It's been described to me that I need to obtain a long-lived user access token and, using that, obtain a page access token. The theory is that said page access token won't expire. However, what's not clear to me is how one accomplishes this.
I've read the page describing the deprecation of offline_access, as well as the page describing server-side access. However, I'm clearly misunderstanding something. In the former, it references the latter for obtaining the proper token. The latter, however, includes steps for presenting a login to the user, having them accept permissions, and using the response from that login.
Being a background process that runs unattended, presenting any sort of question to a user (which would be me) isn't really an option. I've also been told that I can't do a one-time request from my browser to get an access token because that is, by definition, client-side interaction and not part of the necessary server-side flow. (It seems odd to me that the service would care if a RESTful request comes from a web browser vs. from an application, but I'm not familiar enough with OAuth or the Facebook API to really make that call.)
So, if I can perform some manual steps to get a permanent access token for the app to post to the Facebook page, what are those steps? Conversely, if I can perform some automated steps in the application to acquire access each time it runs, what are those steps?
(Making a few more API calls from the application adds a second or two of running time to an otherwise once-a-day process, so it makes no difference to me which approach to take.)
At first I just went into the Facebook Application settings and re-enabled the deprecated "offline access" permission. Said application settings can be found at a URL like this:
https://developers.facebook.com/apps/{APPLICATION_ID}/advanced
However, since everything keeps referring to that setting as being "deprecated" then I didn't want to use that as a long-term solution. It may get removed entirely, it may be unsafe in certain circumstances, etc. Better to use recommended functionality.
So here's what I was able to piece together from a scavenger hunt through updated documentation, outdated documentation, a sea of outdated internet posts, and PHP code which mostly made assumptions about functionality that aren't true in all cases...
Visit the Graph API Explorer and select your Facebook Application from the drop-down menu. Click "Get Access Token" and select the permissions you want. (For mine I went to the "Extended Permissions" tab and selected "Managed Pages" and "Publish Stream.") You will be prompted (in my browser it was in a new tab) with a familiar screen where the Facebook Application is asking you, the user, to grant it the permissions you just selected. (You've seen this before if you've ever agreed to use a Facebook Application before.)
The value it produces in the Graph API Explorer (a long string of random-ish characters) is your "Short Lived User Access Token."
As described here in "Scenario 4: Client-side OAuth and Extending Access_Token Expiration Time through New Endpoint" access this URL in your web browser:
https://graph.facebook.com/oauth/access_token?
client_id={APPLICATION_ID}
&client_secret={APPLICATION_SECRET}
&grant_type=fb_exchange_token
&fb_exchange_token={SHORT_LIVED_USER_ACCESS_TOKEN}
(You can obtain the {APPLICATION_SECRET} value on the basic settings page for your Facebook Application: https://developers.facebook.com/apps/{APPLICATION_ID}/summary)
This will return another Access Token as such:
access_token={LONG_LIVED_USER_ACCESS_TOKEN}&expires=5184000
This access_token value (another long string of random-ish characters) is your "Long Lived User Access Token." The expires value is in seconds, which translates into 60 days.
Now we hop over to the Page API reference and take a look at the section on Page Access Tokens. This, along with the basic structure of Graph API requests exemplified here (scroll down to the part where it shows a bulleted list of sample links which include access_token specifiers, which you'll need to specify here because you're requesting non-public information) leads you to request this in your browser:
https://graph.facebook.com/{FACEBOOK_USER_ID}/accounts?
access_token={LONG_LIVED_USER_ACCESS_TOKEN}
This will return a JavaScript object containing lots of useful information about the Facebook Pages and Facebook Applications your user account controls. In my case the Page and the Application had the same name, but it's easy to tell them apart from the category values or, if all else fails, the id values. Find the Page that the background application running on your machine will need to access and copy its access_token (the third and final long string of random-ish characters). The whole node looks something like this:
{
"name": "Some Facebook Application Name",
"access_token": "{LONG_LIVED_PAGE_ACCESS_TOKEN}",
"category": "Musician/band",
"id": "{APPLICATION_ID}",
"perms": [
"ADMINISTER",
"EDIT_PROFILE",
"CREATE_CONTENT",
"MODERATE_CONTENT",
"CREATE_ADS",
"BASIC_ADMIN"
]
}
This is your "Long Lived Page Access Token." This is the value you use to initialize the FacebookClient object in the code. Then, posting a simple status update is as easy as:
var client = new FacebookClient("{LONG_LIVED_PAGE_ACCESS_TOKEN}");
dynamic parameters = new ExpandoObject();
parameters.message = "This is a my status update.";
dynamic result = client.Post("{FACEBOOK_PAGE_ID}/feed", parameters);
Supposedly this "Long Lived Page Access Token" does not expire after 60 days like the "Long Lived User Access Token" does. I'll find out in 59 days, I guess.
NB: The curly braces in my examples are part of the placeholder for actual values. Do not use the curly braces in the actual requests. So something like this:
https://developers.facebook.com/apps/{APPLICATION_ID}/advanced
becomes something like this, for example:
https://developers.facebook.com/apps/123456/advanced
where 123456 is the actual Facebook Application ID.
Being a background process that runs unattended, presenting any sort of question to a user (which would be me) isn't really an option.
As I already said, you only have to do it once.
You get your non-expiring page access token, copy&paste that into your app – and from then on your app can do server-side whatever it wants to do happily everafter.
I've also been told that I can't do a one-time request from my browser to get an access token because that is, by definition, client-side interaction and not part of the necessary server-side flow.
The server-side auth flow for getting a user access token also needs to take part partly in the browser.
It does not matter, if you get a short-lived token via the client-side auth flow and extend it afterwards, or if you get a long-lived one using the server-side auth flow.
(It seems odd to me that the service would care if a RESTful request comes from a web browser vs. from an application […])
Facebook does not want users to give their login credentials to any third party. Therefor, the process of getting a user access token always has to take part in the browser, with the user login in to Facebook.
So, if I can perform some manual steps to get a permanent access token for the app to post to the Facebook page, what are those steps?
Get a long-lived user access token with manage_pages permission. (Or get a short-lived one, and extend it). And then, use that long-lived token to request a page access token for the target page, in the way that is described in the docs.

OAuth2 User Mapping and Loosing my Cookies

Wrapping my old-fashioned head around OAuth....
Aside from the request/response mechanics and the Authorize / Authenticate round trips (which I think I underdstand) I am struggling with mapping my MyUser object (whatever that may contain) to an OAuth token, if (actually when, not if) the user kills any cookies (encrypted or otherwise) I may have dropped on the browser.
I get MyUser info at the original Login (call it 'registration' for my site) but now MyUser comes back, all cookies are gone so he is just 'user'. Fair enough, user has to do an OAuth login again, but now I have no way of associating the new Token / Secret with MyUser data.
What am I missing?
--- edit Aug 2/2012 -----
Let me restate this (I am pretty sure I am being thick about this but guess thats what here is for):
As pointed out in Replies, each OAuth provider has their own mechanism. We can navigate those and get back an access Token for the user.
Lets say Hero registers on my site using Facebook. FB returns his FB UserID and Name along with the Access Token. We are clever enough to request and get his FB Email, and we ask him some other registration q's before letting him in. Then we save this in our datastore (linked to our own User record):
OurUserId : 1234
oAuthProviderName : Facebook
oAUthProviderUserId: xxxxx
oAuthProviderUserEmail: hero#mlb.com
oAuthProviderUserName: iBeHero
oAuthToken: entracingly-unique-string-of-goop
oAuthSecret: moredata
.... etc.
and set a cookie to identify him as our user# 1234.
Now Hero goes away, kills his cookies for some reason, and then comes back to us.
Now he decides to Log In with Twitter. I have no cookie so I don't know who he is, and we go through the process again.
To me he looks like a new user so once Twitter sends me a Token I start asking him Registration questions, clearly not right.
Turns out Twitter doesn't return an Email address so I can't match that, and even if they did (I think almost everyone else does) Hero likley has more than one Email.
It seems to me that the only tie I have between the two (or however many) logins is whatever cookies I set that have not been deleted.
Are we saying that the entire OAuth2.0 mechanism hangs on this? I can't belive that is right, but don't see another way, so I must be missing something , yes?
If you're using OAuth as a login mechanism as well, then make sure whichever provider you're talking to has some way of returning back a stable ID for a user. That ID is the key you'd use for looking up the user in your DB.
Different providers have different ways of doing this. For Google, details on how to do authentication with OAuth 2.0 are here. For Twitter, they use OAuth 1.0 and return the user ID when exchanging the code for an access token. Facebook has its own way of doing it as well.

Offline_access and Api-Key confusion

I've tried do develop automatic code that would fetch data from ads campaigns under account. My plan is to have server that would query every day to get data from impressions/clicks/costs of ads and save it for later use.
I use https://developers.facebook.com/tools/explorer to get access_token for getting data (insights) from those campaign pages but when I log out to try offline_access it tells access_token is old, cause of password change or access_token getting outdated.
Isn't the whole point of offline_access to grant acccess when user is not logged in?
And besides that.. what's with most of my calls ending having reply as follows:
"(#294) Managing advertisements requires the extended permission ads_management, and a participating API key"
I've given access_token that has ads_management, but I have no idea what this Participating Api key even means. Do I need to add this to url call or something? Where do I get this Api Key?
Edit: I want to be able to get data from add campaign pages, so I'm not talking about Apps in page
You will want to read up on the deprecation of the offline_access here: https://developers.facebook.com/docs/offline-access-deprecation/
But most importantly follow the guide here on how to handle invalid access tokens:
https://developers.facebook.com/blog/post/500/
You app is to monitor the error messages coming back from the API and handle it gracefully.
I have the same issue and I found this bug can be reason of our problem. It's already accepted and assigned, but still not solved. I hope it's really bug and not a secure hole, that was closed :)

Publish to friends wall doesn't work with specified access token

We have an application that allows to users publish content to their friends wall.
It uses the user's access_token given our application.
It works stable usually, but for some reason for one of our clients it doesn't work at all.
We've checked permissions several times, removed-added them again, but still no result.
There is no error message or something, everything looks fine, complete the action, but no posts published in fact. And it doesn't work only for one person.
What possibly can be a problem?
Updated: The problem is actually in this OAuthException:
Error validating access token: Session does not match current stored
session. This may be because the user changed the password since the
time the session was created or Facebook has changed the session for
security reasons.
We tried to get access token one more time, but that didn't help. Somebody familiar with this issue?
your user might forbid people/applications to post on his wall.
"There is no error message or something, everything looks fine, complete the action, but no posts published in fact."
Are you sure about this? You should be getting back a unique stream id of the feed item just posted.
Facebook frequently changes its policies that sucks!
Now, you need permission to access the wall.
You need to check if the user has permission to access your application / wall page. if user hasn't got permission then you need to ask for permission before message is streamed. Yes, that's true, it won't display any error message, unless you manually debug this to see where it is stopping.
My suggestion is:
1. use FB.login method to verify, if the user is not logged in then he should login
2. verify the user permission for the wall page
FB.api('/id', function(response){});
3. publish / stream the comments on wall
FB.api("/id/feed", 'post', { ... blah blah blah !
edits:
At FB.login method, you should ask for permisions
e.g. FB.login(function(response) {..} ... ,{scope: 'offline_access,publish_stream'});