I'm trying to build an app that gets public information from Facebook. In the past, this type of operation would require an App Token (A token that could be used on behalf of the application to query public data). I had no problem implementing this technique with Twitter and Youtube, but Facebook looks like you can only access their API by letting a user login with Facebook via OAuth, retrieve them a personal token, and give them permission to query their own information.
I see a lot of posts related to this question, but they seem outdated. I know Facebook has been under a lot of privacy pressure lately and I'm wondering if they changed it.
Here are my questions:
Is it possible to generate an App Token used to access Facebook's Graph API?
If so, where can I find the documentation for this? I can only find information on using a user token.
I prefer to use Node.js as my backend, so any direction on where to start there would also be appreciated.
User Profiles: They always require a User Token, there is no way to access User Data without explicit authorization of the User, no matter if data is public or not.
Pages: If you manage the Page, you can use a Page Token of that Page to access data. If you want to access other Pages, you need to apply for Page Public Content Access - after that, you can use an App Token for those Pages.
In other words: App Tokens for public Pages (with PPCA), Page Tokens for Pages you own, User Tokens for User Profiles.
Btw, App Tokens do not need to be "generated", they are just "App-ID|App-Secret" (with a pipe in the middle).
Related
I'm trying to create a simple script (node) that each day collects information from various APIs, including Facebook's Graph API.
The idea is simple, each day I want to collect the total friend count of my personal account, total page likes of my managed pages, total social interactions of my content (personal and from pages).
Now, if I was doing this in a web app, the normal route would be using facebook login to request the access tokens for my profile and pages, but since this is a script it does not have a public exposed url to return the authentication to.
Does anyone know of a way to manually get the tokens, to use in a scenario like this?
Thanks
Have you tried to use this node package?
If you get an accesstoken via some other Oauth module like everyauth ,
connect-auth or node-oauth you can just set the access token directly.
Most get calls, and pretty much all post calls will require an
access_token
There is also a decent article on Medium which works through this process.
So I noticed that apps like Tinder can show Instagram connect of lets say, User A on everyone else's phones even without requiring other users to actually sign into instagram.
For example: User-A connects instagram and gets access token. Users-B, C, D... can see A's public & private pictures without even logging into instagram.
Is there a way to view another user's instagram without requiring access token - even private pictures by just using CLIENT_ID?
Let's not make confusion. Tinder user can opt-in for sharing Instagram photos. Tinder has no worldwide access to Instagram photos. I will answer you from the security perspective, as I have never tried setting up a Tinder account with Instagram connection to test the scenario for you. Actually, from my understanding of Instagram APIs it could be impossible to get user's private pictures. But I could be wrong, so let me continue my discussion.
Access token is embedded in Tinder app code, you may find it or not if you decompile the code, according on the level of obfuscation, and almost certainly if you use software such as mitmproxy. I won't discuss such a practice here.
So Tinder client is granted a token to access user's pictures.
User opts in on Tinder/Instagram to access his private photos. A single access token is valid for pictures of all users that opted in to Instagram.If you steal Tinder's token you can access any Tinder-Instagram user's private photos. That is not bad. User has chosen to share private photos to the world. But if an Instagram user is not a Tinder user be sure that you won't get anything
Please mind that the token is valid for Tinder application, and is not user A's token. This is forbidden by security practices.
By associating your Tinder account with Instagram you grant Tinder's already-issued token to access your photos on behalf of you.
Summarizing:
Tinder client - Actor
Instagram - Resource server
User A's photos - Resource
User B (on Tinder, not on Instagram) - not an actor in the workflow
Token issued to Tinder: access to any (public or private??????) photos of users who have opted in to share Instagram photos on Tinder
Note: Tinder client may or may not use an Instagram-issued token. From a general security point-of-view, there are two implementation scenarios:
Tinder client contacts Instagram server with a token that is issued to Tinder application and encoded in all clients
PRO: bandwidth is charged to user only
CON: exposing the token may grant one to access any Tinder-Instagram user photos without passing by Tinder
Tinder app requests Tinder server to fetch photos from Instagram. Tinder client only authenticates with Tinder server
PRO: more secure design. Tinder-to-Instagram token never exposed. If a user leaves Tinder he can't access Instagram photos of other Tinder users
CON: Tinder server will be charged for the bandwidth needed to retrieve and distribute photos. This exposes Tinder to a potential violation of Instagram API ToS if they start caching the photos
The previous answer is way too confusing... so let's handle it in a easy way, according to your question.
Let's start from understanding, what is access_token, in their API, in API requests alike:
api.instagram.com/v1/users/self/media/recent/?access_token=%#
Working through API, receiving this access_token still requires granting of access, and Authentication (see the manual on Receiving an access_token). As you can read there, all the possible options still require authenticated access.
Even though our access tokens do not specify an expiration time, your app should handle the case that either the user revokes access, or Instagram expires the token after some period of time. If the token is no longer valid, API responses will contain an “error_type=OAuthAccessTokenError”. In this case you will need to re-authenticate the user to obtain a new valid token.
In other words: do not assume your access_token is valid forever.
This is standard authentication process in programming, with the access tokens, session identifiers, etc.
The world has been living with OAuth 2.0 Authorization Protocol for a long time, you are not the last guy who's concerned about it. If you are sleeping fine knowing about theoretical Session hijacking, then you shouldn't worry that much about potential security issues related to usage of APIs by access tokens.
It's secure enough. Aha, and another "small thing", I forgotten to mention: all requests to the Instagram API must be made over SSL (https:// not http://), which adds even more confidence.
To answer explicitly your question:
"is there a way to view another user's instagram without access token - even private pictures by just using CLIENT_ID?"
No, there's no possibility. Security token is the thing, which requires granting of access, and authentication. If it would allow this kind of access - this would be counted as security vulnerability. This is the basics of OAuth mechanism. If you need more understanding, you may read here, in a simple language, how OAuth is an authentication protocol works.
If you want a quick solution to the problem, I would avoid OAuth at all costs when dealing with public data. I would write a curl script to grab the public Instagram data from the user's profile URL, and parse the HTML server-side (or client-side).
Here's a quick mock-up example in PHP, using file_get_contents and DOMDocument:
//HTTP GET someone's profile (the easy way):
$html = file_get_contents('https://www.instagram.com/profile_xxxxxx/');
//Use PHP's built-in HTML parser
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->loadHTML($html);
$selector = new DOMXPath($doc);
//Instagram stores image URL's in meta tag "og:image"
foreach($selector->query('//attribute::*[contains(., \'og:image\')]') as $e) {
//Store profile photo from DOMNode $e
$photourl = $e->getAttribute('content');
//Grab profile photo
file_get_contents($photourl);
}
Let's consider that Instagram User Profiles pages like ISS page are available online without any authentication access:
https://www.instagram.com/iss/
Due to how Instagram works, only public images will be showed here (plus posts, followers, following).
So what you have to do is to get the page data. To do this you can use several solutions like PhantomJS that is as little as writing
var page = require('webpage').create();
page.open('https://www.instagram.com/iss/', function() {
var contents=page.contents; // here is the page contents
phantom.exit();
});
So, assumed you can execute this process on server-side you could provide those public profile images as a JSON object in a api response. Of course it's a little bit more complicated than this (i.e. you have to wait page resources to be loaded within PhantomJS, but at the end the web scraper can temporary save the page and turn it into a json structure, with <img/> source images, etc. ready to be showed in a app.
I am currently creating an API (who isn't) however when I look for a way to use oAuth in the ways Facebook and twitter do to authenticate users trying to get data all i find is a way to get users permissions which I do not need, the idea of my implementation of oAuth is to authenticate the developer so when they make an API call the server knows who they are and what to serve them. I haven't tried any oAuth code because I haven't found node module that will help so far, however I can give background. I am using:
Mongoose, to query MongoDB
Express, for the HTTP Server
I do not explicitly want to use oAuth, I simply thought it was a good idea, I am open to any other way of doing things.
I think you should read the OAuth specification and to decide if one of the grant flows suits for your requirements. When user(developer) logs in you grant Access Token to him/her. Now on when user makes request to API the Access Token must be on HTTP request header, extracting that Access Token on back-end service from the request you can identify the user.
It is up to you what kind of information you store to DB from the user when she/he registers to your service. But all that information can be mapped with the Access Token that user gets after succesful login or stored inside the Access Token also.
I have the following elements:
A PHP back-end providing a RESTful API secured with OAuth (FOSOAuthServerBundle with Symfony 2)
A Javascript front-end (AngularJS), i.e. an OAuth client.
My goal is to provide users with an authentification page in the front-end, allowing them to log in and access the API through the Javascript.
I do this the following way, according to this article: http://www.bubblecode.net/fr/2013/03/10/comprendre-oauth2/ (unfortunately in French, but if you scroll a bit, the diagrams explaining the standard grant flows are in English):
I provide a form asking the user credentials (login and password)
I use an OAuth Implicit Grant to exchange the user credentials for an access token.
Evertything should work (almost) well so far.
Now, the reason of this question is I want to add Facebook Login to my front-end. What this will give me is a Facebook access token each time a user registers with Facebook Login on my front-end. Ideally, my back-end should:
get this token
check it against Facebook PHP API in order to validate it
retrieve from Facebook PHP API the user Facebook UID
compare it to the ones of my app registered users
return an access token (this time for my own app, not Facebook) if and only if the Facebook UID matches with one of my registered app users.
My question is: which type of grant should I use to make the transaction between my front-end and my back-end in such a use case (given that it is of course not acceptable to give my Client Secret from a Javascript Client)?
Actually, I managed to found the solution. A custom grant should be designed to solve this problem, based on the Implicit Grant (in which the Client Secret is not asked).
However FOSOauthServerBundle does not yet implement grants based on public clients (see https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/issues/266 for more details).
When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.