I'm using the new'ish People API to track a users contacts. I request a syncToken when listing a users contacts using people.connections.list and pass this along on subsequent requests to only get changes.
If there is a change I get only the changed Person as expected. However, nextSyncToken is always the same as the syncToken I passed in. I was expecting a new sync token after a change. The documentation isn't really clear on whats supposed to happen. Anyone have any insights?
This happens with both the Golang bindings (which aren't documented on the site but work great otherwise) and when using the API explorer on - https://developers.google.com/people/api/rest/v1/people.connections/list
Related
The site of the company I work at is using a Consent Management Platform which was functioning ok. Lately, we had to make some modifications in it and had to reimplement it. The implementation went ok, even the engineers who offer support for the CMP I'm using confirmed that everything I did was fine.
And now the problem: some users are still having the old cookie on their devices. So now when they are entering the site they receive a 400 error and can not access the site anymore. The fix would be so that every user manually deletes the cookie on their device but this is impossible to do as our visitors are not very technical and we can't reach all of them.
So, is there anyway to somehow make any kind of change/implementation, from our side, from the server-side, in order to refresh the users session and make their 400 error disappear without them having to do it manually?
I'm really in a pinch right now and am in need of real advice.
Currently I set up a RESTful API backend using Django and I can list a set of articles by the following GET:
api/articles/
Also, I can get a single article by:
api/article/1/
Each article is owned by a certain user, and one user could have multiple articles of course.
On the frond end side, I present all the articles at loading of the page, and I hope the user who is logged in currently could see the articles that they own in a different style, e.g, outlined by a box, and has a associated "delete" or "edit" button.
This requires me to tell, after the retrieval of the articles, which ones are owned by the current user programmatically. One way of doing this is to check the current user id with the owner id. However I feel this is not a good choice as the user id is the check is done fully on the client side and may be not consistent with the actual server judgement.
Therefore, is there a way, to tell by looking at the response of the GET, (say, let the server return a property "editable=true/false") to get whether the current user could edit(PUT) the resource?
I understand that this could be done at the server side, by attaching such a property manually. However, I am just asking whether there is better/common practice.
I just started learning web development and I am sorry if the question sounds trivial. Thank you!
You can attach propriety manually as you suggested. The advance of this approach is that you dont need any other http request.
Second possibility might be, that your client intentionally request information about endpoint permissions. In this case I would suggest to use OPTIONS HTTP method. You send OPTIONS HTTP request to api/articles/1 and backend returns wanted info. This might be exactly what OPTIONS method and DRF metadata were made for.
http://www.django-rest-framework.org/api-guide/metadata/
I think that this is a very interesting question.
Several options that come to me:
You can add to the GET api/article/1 response a HTTP header with this information i.e. HTTP_METHODS_ALLOWED=PUT,PATH,DELETE. Doing this way helps the API client because it does not need to know anything else. I think that this is not a good approach when more than one entity is returned.
call to OPTIONS api/article/1. Allowed methods for that user on that resource can be returned but notice that, in my opinion, this approach is not very good in terms of performance, because it duplicates the number of requests to the server.
But what if the entity returned also contains information on the owner or it? can, in this case the client know which policy apply and try to figure out it by itself? notice that the policy can be obtained from another endpoint (just one call would be needed) or even with the login response. If your entities do not contain that kind of information, it could be also returned as a HTTP header (like first option above)
Before you start yelling at me, I know many users already asked for something like this, but I read all of them and couldn't find any reply related to my specific case: I eventually managed to get something working but it's not what I think I (and other developers) are looking for. I want to share my experience about this with all of you, so I'll try and describe my scenario and the steps I followed to look into how to take care of this, so please indulge me for this long post: I'm sure it will help some developers in the same situation as I am to clear their minds too, just as I hope it will give others the right information to help me (and others) with it.
I wrote a native Android application that makes use of the Facebook API. I DO NOT make use of the Facebook SDK, because I don't want to rely on the official app being installed on the device (as a matter of fact, my app is in part an alternative to that app so it would be silly to need it installed anyway in the first place), but I rather issue Graph API calls directly via HTTP and handle the responses myself. So if that is the answer you're thinking of giving me, please don't because I won't take that road.
As such, I made use of the Client-side authentication to authorize my app, displaying the URL in a WebView and getting the access_token at the end. I requested offline_access among the other permissions.
Since offline_access is going to be deprecated in May, I started investigating how to get long lived tokens anyway, and so read almost everything I could find related to that, including of course the official guidelines. Long story short, nothing worked for me, and I'm still stuck with very short-lived access_tokens that I can do nothing about.
This is what I did to begin:
Deprecated the offline_access for my app (well not THE app since it's being used by many users right now, but another one which is basically the same and I use for testing purposes only so that's the same thing) in the settings.
Authorized a user using Client-side authentication: https://www.facebook.com/dialog/oauth?client_id=MY_APP_ID&redirect_uri=http://my.domain.com/yeah.htmlscope=publish_stream,read_stream,user_photos,friends_photos,offline_access&response_type=token&display=wap
I got my access_token, but I immediately noticed how it was not long-lived at all, quite the opposite: expires_in was set to something like 6800 seconds (less than two hours). So the first assumption I had made (access_tokens will be longer lived by default) was already wrong.
I looked into how this access_token lifetime could be extended then, and tried almost every alternative out there. Needless to say, every attempt failed. That's what I tried, to be precise:
First of all, I of course tried the "official" approach, that is extending the token through the new endpoint. Skipping for now the rant about how stupid it is to request the client secret for such an operation (as many folks already pointed out, such secret would need to be embedded in the Android app, which is a security nightmare as far as we developers are concerned, and moving this bit server-side to extend the token life on behalf of the user is a nightmare for what concerns them instead, since they'd need to trust me with messing with their access_token), I tried issuing a GET request to that address using the correct parameters: https://graph.facebook.com/oauth/access_token?client_id=APP_ID&client_secret=APP_SECRET&grant_type=fb_exchange_token&fb_exchange_token=EXISTING_ACCESS_TOKEN ...The request was apparently successful, but it did NOT extend the lifetime of anything. The request just returned the same access_token as before, with an expires_in parameter that just reflected the sand of time flowing away (the same as before minus the seconds passed since I authorized). Basically, that method only told me how much the already available access_token would live, without refreshing or changing anything, so, despite the obvious security concerns it raises, it is pretty useless too.
I then tried what someone else suggested, that is using the old REST API to do the job, issuing a GET request to the following address: https://api.facebook.com/method/auth.extendSSOAccessToken?access_token=EXISTING_ACCESS_TOKEN which obviously failed too with the infamous "The access token was not obtained using single sign-on" error.
After those failed attempte, I started thinking about what may be the cause of all of them failing. As I anticipated, my app runs on Android devices but makes triggers HTTP requests to the API directly, which I guess may be the root of the problem.
In the advanced section of my developer apps page, my app was configured as "Web" rather than "Native/Desktop". That said, changing it to "Native/Desktop" did nothing but give me a longer-lived access_token at the first logout (about 24 hours rather than 1-2), while the already described attempts at extending its life failed just as before.
The official guideline has an interesting and quite creepy paragraph: "Desktop applications will not be able to extend the life of an existing access_token and the user must login to facebook once the token has expired". While this seems to have been overlooked by many, I started to think this may be the cause of my problems, so I tried an alternative approach, that is, I tried the server-side authentication rather than the client side one: again, this requires client_secret so would be a dumb solution for an Android app but I wanted to try that anyway. So, I got the code first, and then the access_token after that (as described in http://developers.facebook.com/docs/authentication/server-side/). This resulted in a much longer lived access_token (5183882 seconds, that is about 59 days), but then again, both the known means for extending it (even if not really needed in this case) resulted in the same thing: the former not refreshing anything, the latter complaining about the fact it was not obtained via SSO.
So, very long story short (I know, too late), the deadline for deprecating offline_access is so close you can feel it breathing on your neck, and nothing seems to work. What is your experience with all of this and, if you're on the same boat as I am and you managed to get it working, how did you do it?
Thanks for your patience.
BUMP: This is not a dead request. I'm still hoping to get a solid answer from someone at Facebook or anyone else. Thanks.
Revised Inquiry: I don't know if I'm not asking the right question, or if I'm asking a valid question that no one can answer.
New Questions:
Can we use FQL or another means to get all of the requests seen at reqs.php? I'm essentially looking for something like this:
SELECT request_id, app_id FROM apprequest WHERE recipient_uid = me()
Notifications return that data but app requests are often batched into a single record with a link identifying some but not all requests. I want individual records for all app requests currently open. The data to do this must be available, as this is the data used to build notifications! It just seems that this is not being made available to us. :(
Thanks!
Original Inquiry Follows:
I have an app that aggregates various sources of Facebook information for a user. One of the sets of data I'm working on is the collection of apprequests which have been sent to this user by friends. For example, I open GreatApp and click to send a request to you. You may or may not use GreatApp but let's assume you haven't blocked requests from it. You now open my AggregatorApp that shows my request to you, and the included link back to GreatApp. The data you see is the same as at reqs.php but formatted differently, with much more data, and of course simply much better. ;)
I thought that is what we got in apprequests. From this question I'm understanding that apprequests is a collection of requests sent out by the current application.
When using path/me/apprequests, we don't need to specify an app ID. But I believe here we do need to provide an app token rather than a user token. Is that correct? If that's correct then this confirms that the requests are those that this app sent out, not requests generated by other apps.
When using FQL, we need to identify the uid of the app as well as the id of the request in order to query the apprequests table. I get that, but even with a valid request id and app id (and valid permissions) FQL doesn't return request data. (I haven't checked with an app id, maybe that's the key.)
I am hoping people will provide some concrete examples for any of the above, specifically getting inbound requests from other apps, and confirmation about what token or other detail is expected for /apprequests and the apprequests table to return data.
Thanks!
Other threads asking the same question without a good (or any) response:
thread1 thread2
You need to make a graph api request to get the apprequests connection for a user. See the current documentation here: http://developers.facebook.com/docs/reference/api/user/.
In the Connections table, the documentation correctly notes that you need an application access token to retrive the requests to that user. There's a bug in the documentation under (http://developers.facebook.com/docs/reference/api/user/#apprequests) that claims you need a user access token. This is incorrect, and (as you've seen) will return an empty list of requests.
Requests sent by an application are only visible to the application. The user can't see or delete these requests (though they are able to hide the request). The reason for this is that the applications can put data into the requests (255 characters) that's never exposed to the user or other applications.
I don't think there's a way you'll be able to aggregate a user's requests from apps that you don't have an access token for.
What I have found out (before my question was deleted) was that you can't access requests with a user token, and app tokens can only access requests that app has sent (and I found that out myself in the documentation and playing with the graph explorer). Since I know there are iPhone apps and browser plugins for processing requests, I assume they are accessing the page itself and parsing the data (like scraping a site). The downfall to that approach is that on the request page only around 100 requests from each app are shown at one time.
(Unless some people have found a way that they aren't sharing...)
You are right, you need the app_access_token and not the user_access_token.
I think the FB documentation has an error.
The definitive answer was provided by a Facebook developer here in response to my bug report. The resolution is that this is By Design. This relates to the note by #noah-callaway that there's probably some app-specific data in requests that should not be available to other apps.
This is a shame, in my opinion, because as Facebook is all about sharing data among friends, I think it adds a dimension to the ecosystem when apps can share (limited and reasonable) information among one another.
Thanks for the responses!
I've got a webservice which is executed through javascript (jquery) to retrieve data from the database. I would like to make sure that only my web pages can execute those web methods (ie I don't want people to execute those web methods directly - they could find out the url by looking at the source code of the javascript for example).
What I'm planning to do is add a 'Key' parameter to all the webmethods. The key will be stored in the web pages in a hidden field and the value will be set dynamically by the web server when the web page is requested. The key value will only be valid for, say, 5 minutes. This way, when a webmethod needs to be executed, javascript will pass the key to the webmethod and the webmethod will check that the key is valid before doing whatever it needs to do.
If someone wants to execute the webmethods directly, they won't have the key which will make them unable to execute them.
What's your views on this? Is there a better solution? Do you forsee any problems with my solution?
MORE INFO: for what I'm doing, the visitors are not logged in so I can't use a session. I understand that if someone really wants to break this, they can parse the html code and get the value of the hidden field but they would have to do this regularly as the key will change every x minutes... which is of course possible but hopefully will be a pain for them.
EDIT: what I'm doing is a web application (as opposed to a web site). The data is retrieved through web methods (+jquery). I would like to prevent anyone from building their own web application using my data (which they could if they can execute the web methods). Obviously it would be a risk for them as I could change the web methods at any time.
I will probably just go for the referrer option. It's not perfect but it's easy to implement. I don't want to spend too much time on this as some of you said if someone really wants to break it, they'll find a solution anyway.
Thanks.
Well, there's nothing technical wrong with it, but your assumption that "they won't have the key which will make them unable to execute them" is incorrect, and thus the security of the whole thing is flawed.
It's very trivial to retrieve the value of a hidden field and use it to execute the method.
I'll save you a lot of time and frustration: If the user's browser can execute the method, a determined user can. You're not going to be able to stop that.
With that said, any more information on why you're attempting to do this? What's the context? Perhaps there's something else that would accomplish your goal here that we could suggest if we knew more :)
EDIT: Not a whole lot more info there, but I'll run with it. Your solution isn't really going to increase the security at all and is going to create a headache for you in maintenance and bugs. It will also create a headache for your users in that they would then have an 'invisible' time limit in which to perform actions on pages. With what you've told us so far, I'd say you're better off just doing nothing.
What kind of methods are you trying to protect here? Why are you trying to protect them?
ND
MORE INFO: for what I'm doing, the visitors are not logged in so I can't use a session.
If you are sending a client a key that they will send back every time they want to use a service, you are in effect creating a session. The key you are passing back and forth is functionally no different than a cookie (expect that it will be passed back only on certain requests.) Might as well just save the trouble and set a temporary cookie that will expire in 5 minutes. Add a little server side check for expired cookies and you'll have probably the best you can get.
You may already have such a key, if you're using a language or framework that sets a session id. Send that with the Ajax call. (Note that such a session lasts a bit longer than five minutes, but note also it's what you're using to keep state for the users regular HTPP gets and posts.)
What's to stop someone requesting a webpage, parsing the results to pull out the key and then calling the webservice with that?
You could check the referrer header to check the call is coming from one of your pages, but that is also easy to spoof.
The only way I can see to solve this is to require authentication. If your webpages that call the webservice require the user to be logged in then you can check the that they're logged in when they call the webservice. This doesn't stop other pages from using your webservice, but it does let you track usage more and with some rate limiting you should be able to prevent abuse of your service.
If you really don't want to risk your webservice being abused then don't make it public. That's the only failsafe solution.
Let's say that you generate a key valid from 12.00 to 12.05. At 12.04 i open the page, read it with calm, and at 12.06 i trigger action which use your web service. I'll be blocked from doing so even i'm a legit visitor.
I would suggest to restrain access to web services by http referrer (allow only those from your domain and null referrers) and/or require user authentication for calling methods.