http://www.independent.co.uk/ and http://www.guardian.co.uk/ have an application where by if you read an article on their site, it writes to your profile/timeline that "X has read Y on Z".
Now I can write to the timeline with a button present. I can also do it automatically (but this happens each time they go to the article which I don't need). However what I need to add is some logic as shown below
If user logged in but app not authorised
Show a button to authorise application
If user logged in and app authorised and visiting article for first time
Automatically publish "X has read Y on Z" to their profile and FB
If user logged in and app authorised and visiting article again
Don't publish anything
Does this make sense? Any examples of this around? So basically pulishing to the timeline isn't an issue, it's just the various checks I need to put into place.
EDIT
Ok, for some reason this works (for checking of they are authorised or not) but if I take out the alert('test'); part, it doesn't work. Any ideas?
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1&appId=123456789";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
alert('test');
FB.init({
appId:'123456789', cookie:true,
status:true, xfbml:true, oauth:true
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
alert('Logged in and connected');
$(read);
} else if (response.status === 'not_authorized') {
alert('Logged into FB but not authorised');
} else {
alert('Not logged into FB');
}
});
</script>
Ok, got it partly working. There are some slight niggles but main issue now is to check whether they have posted a specific action to the timeline already. If they have then don't post another e.g. So when they go to an article first time, the status "Jon has read an article on the Site" gets added. However if they go to it again, it doesn't get added
This is against the Facebook Platform Policy. See section IV part 3:
If a user grants you a publishing permission, you must still obtain consent from the user before taking any action on the user's behalf, such as publishing content or creating an event.
You can not post to the user's timeline\wall without first asking them permission. The Independent and The Guardian have a unique arrangement with Facebook that exempts them from these restrictions.
This is the kind fo thing that will get you a strongly worded email warning, or more severely, a developer account suspension.
Its always good to have a look at the Platform Policies and Promotions Checklist before starting a new project.
Your code only works with the alert due to a race condition in your code.
You are loading the SDK asynchronously (which you should), but then try to use it synchronously by calling FB.init immediately.
You need to define a function fbAsyncInit, in which you call FB.init. This will ensure that you don't try to call FB.init before the SDK is loaded.
Other than that, this is all about getting the right permissions from the user, and following Facebooks policies. Technically it's all pretty basic stuff.
Related
I am trying to tweak the Parse Express tutorial:
https://www.anyimg.org/ and https://github.com/ParsePlatform/Anyimg
Basically, instead of starting with their default home page, I always show a login page if the user has not been logged in. I was able to do that by adding a simple check for Parse.User.Current() at the Homepage endpoint and redirecting to login if they are not looged in.
For my next step, I want to allow Facebook login. So I tweaked the login.ejs as follows:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
Parse.FacebookUtils.init({
appId : '254642391362596',
status : true,
xfbml : true
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
function fLogin() {
/*Parse.FacebookUtils.logIn(null, {
*//*success: function(user) {
alert("login success with user " + JSON.stringify(user));
if (!user.existed()) {
alert("User signed up and logged in through Facebook!");
} else {
alert("User logged in through Facebook!");
}
//FB.api('/me', function(response) {
// alert("got fb me api=" + JSON.stringify(response));
//});
},
error: function(user, error) {
alert("User cancelled the Facebook login or did not fully authorize.");
}*//*
});*/
// log in with Parse
Parse.FacebookUtils.logIn(authData, {
success: this._fbLoginSuccess,
error: this._fbLoginError
});
}
</script>
<button class="btn-facebook btn-large" onclick="fLogin();"><img src="./images/FB-f-Logo__blue_58.png"> <span class="btn-facebook-text">Login with Facebook</span></button>
The good news: When I try the commented block without the login block, I get a FaceBook login prompt, and I can go to the DataBrowser and see AuthData there.
However, if I use the //Login block, nothing seems to happen.
Also, if FB login is a success what do I change in app.js or user.js to allow the home page to render? I have been searching docs and SO for a day now, and I don't see any clear docs on this.
Thanks for your help!
Note: I am rather new to both Parse and Express, but I have been able to make progress mostly on my own (please see my other postings here).
I have made progress. The code above essentially works. Remove unwanted alerts from above and use window.location.href = '"home"/one-of-my-routes". However, I am still unable to send a post to my users.js page. Any help will be appreciated
What you are trying to do is definitely possible (I've done it), but can't be achieved with the method you are using right now. Basically you can't access the Parse.User.current() in Express on the server if you do a login with Facebook JS SDK on the browser. It doesn't work. (See this question in Parse forums.)
The only way you can achieve what you want, as far as I know, is using the undocumented parseFacebookUserSession middleware.
Edit: Add step-by-step detailed instructions
To log in the user with Facebook on Express (server) you simply need to follow the steps detailed on the middleware's github repo. Start by adding the file parse-facebook-user-session.js into the cloud folder. Then add the code shown on the readme to app.js, like this:
var parseExpressHttpsRedirect = require('parse-express-https-redirect');
var parseExpressCookieSession = require('parse-express-cookie-session');
var parseFacebookUserSession = require('cloud/parse-facebook-user-session');
app.use(parseExpressHttpsRedirect()); // Require user to be on HTTPS.
app.use(express.bodyParser()); // Middleware for reading request body
app.use(express.cookieParser('123456789')); // YOUR_SIGNING_SECRET
app.use(parseExpressCookieSession({ cookie: { maxAge: 3600000 } }));
var fbLogin = parseFacebookUserSession({
clientId: 'FB_APP_ID',
appSecret: 'FB_APP_SECRET',
verbose: true,
redirectUri: '/profile' // where the user will be redirected to after getting a token from Facebook
});
// This route will require FB login. If the user is not logged in, it will be redirected to FB
app.get('/events/new', fbLogin, events.new);
// A route to log out
app.get('/logout', function(req, res) {
Parse.User.logOut();
res.redirect('/');
});
Some notes:
You must use HTTPS
You must enable the 'Add Field' Class Level Permission for the _User class using the Data Browser
You must enable 'Allow client class creation' in the app Settings (see the readme)
A new class ParseFacebookTokenRequest will be created on the Data Browser. Disable all it's Class Level Permissions (again, see the readme)
Important: According to a Parse Engineer, it's possible to log in the user client side using the FB JS SDK. I haven't done this but it's somewhat explained in this issue.
I recently found this useful post. Albert, this has the become() that you suggested. And this helped me at least get one version working.
Parse Javascript SDK -- Save client-side `user` as server-side ` Parse.User.current()`
Code on my web page:
<body class="popup">
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
// init the FB JS SDK
FB.init({
appId : '476947702378530', // App ID from the app dashboard
channelUrl : '//www.majorforms.com/fb_channel.php?_lang_id=1',// Channel file for x-domain comms
status : true, // Check Facebook Login status
xfbml : true // Look for social plugins on the page
});
// Additional initialization code such as adding Event Listeners goes here
};
// Load the SDK asynchronously
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en/all.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
After loading that page with a browser, I get this error in firebug console:
Application Error: There was a problem getting data for the application you requested. The application may not be valid, or there may be a temporary glitch. Please try again later.
I don't really understand. I do not have a real app, I just used the identifier of a facebook (company) account. I do not want to create a new facebook app, I just want to use credentials of a specific facebook account. How do I do that?
I'm not hundred percent sure but you need to create an app to use the facebook sdk because in the FB.init method it obviously asks for the Facebook App Id.
Creating a Facebook App doesn't necessarily mean that you actually have an app on facebook, the app configuration screen on Facebook Developers page has a specific section for "Website With Facebook Login" , so I think thats the way you should go.
I found I was getting this error when testing my application because I was signed into Facebook as a test account user. When I tried to access the live environment it would generate that error as it was already authenticated to the developer user. The error message is kind of generic and doesn't really spell out the issue in black and white.
I'm trying to figure out how to do something, and I've tried searching Stack Overflow, but I'm honestly not 100% sure what I'm looking for, so I'm not coming up with anything great.
Here is what I need to do:
We have an app, and you're supposed to like the page to see the app. Great that works.
The client wants us to put a facebook share button on the site, so that when you're finished using the app, you can click the "Share" button and post something to your wall saying, "I just used XXX and you should too!" or whatever. The problem is that the Share button is deprecated. Everything on the facebook developer site says I need to use the like button, but, since you've already LIKED the page to get in, you're going to see that you've already liked the page and not be allowed to click it again to share content on your news feed.
It seems like I'm missing something here. Can you have a like button for a page AND a specific app inside that fan page? It doesn't seem like I can do that. Is what I'm asking even possible?
Yes, you can use the Javascript SDK to post to the wall... this uses jQuery to detect a click on an id which is the share button so make sure you add this before any facebook javascript:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
You will also need to load the FB Javascript SDK if you haven't already:
<script>
window.fbAsyncInit = function () {
FB.init({
appId: 'INSERT APP ID',
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
oauth: true // enable OAuth 2.0
});
};
// Load the SDK Asynchronously
(function (d) {
var js, id = 'facebook-jssdk',
ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
</script>
Then add the following code:
$("#shareclick").click(function () {
FB.ui({
method: 'feed',
name: 'The Post Title',
caption: 'skruffymedia testing caption post',
description: (
'Testing the description of the skruffymedia app post!'),
link: 'http://www.skruffymedia.com',
picture: 'http://www.skruffymedia.com/facebook.jpg'
}, function (response) {
if (response && response.post_id) {
alert('posted');
} else {
alert('not shared');
}
});
}); //End Share Click
I'll be including this answer on the next step of my blog
http://www.skruffymedia.com/blog/creating-a-facebook-like-gate-competition/
It is now against Facebook's policies to gate an app or content within an app based on if someone has liked your page.
See the announcement here: https://developers.facebook.com/blog/post/2014/08/07/Graph-API-v2.1/
I have made a Facebook registration form that works with custom fields and functions as I expect, EXCEPT when the user is not logged into facebook when they first visit the form.
In this situation the form does not render on screen and the following error appears:
Unable to load the registration form for this ID. You may have
previously blocked this app on Facebook. Go to your Facebook privacy
settings to unblock this app. (Error: Invalid 'client_id'.)
Now I know already that this has been discussed on the site but the solutions offered elsewhere don't work for me and I really want this to work based in the XFBML solution that facebook supports (a demo is here http://developers.facebook.com/docs/plugins/registration/)
If you logout of facebook you can visit a test of my code, taken directly from the facebook example and hardly modified here: https://www.askanutritionist.com/fb.html
By the way, yes sandbox is disabled in the facebook app settings as thats a common fix others on S.O. have suggested.
Thanks for your time.
Note; I would have commented on other existing questions with this topic but stackoverflow won't let me (yet).
Check that the app whose ID you're using isn't restricted demographically (e.g. by age or country) and that it isn't still in sandbox mode.
If it is restricted or in sandbox mode, users who aren't logged in and who meet the restrictions applied (or for sandbox mode, are admins of the app) can't see the existence of the app or its details until they log in.
Just to confirm; I never actually fixed this properly. Instead I made a work around and was able to do a javascript check via the facebook sdk to see if the user was logged in or not when they first hit the page that has the facebook registration form.
I do an http redirect if they aren't logged in (or aren't authorised) and if they are logged in later in the page I call to init the facebook form.
window.fbAsyncInit = function() {
FB.init({
appId : xxxx, // App ID
channelUrl : 'http:///xxxxx/fbchannel.php',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Additional initialization code here
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
// all ok!
//var uid = response.authResponse.userID;
//var accessToken = response.authResponse.accessToken;
} else if (response.status === 'not_authorized') {
window.location.href="create_account_with_facebook?authorizefirst";
} else {
window.location.href="create_account_with_facebook?loginfirst";
}
});
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
We have a facebook website app for use as a public event kiosk. Many people will be logging into facebook through our site on the same device (set up at a booth, like a ipad or similar).
We need to log the person out of facebook itself after they are done; not simply destroy the graph api session for our site.
Here is the problem:
User walks up to our ipad, which has a browser loaded to our website. He or she clicks "facbook login", and is redirected to facebook to log in.
They log in, grant our app permission, and facebook redirects them back to our site.
After they use our site (post comment, etc...) they click log out on our site.
Next user sits down, clicks "facebook login", and is redirected to facebook. Upon reaching facebook.com, the browser is still logged in for the previous user, granting this user access to the first user's facebook (just a small problem =)
My hope is that I can send the user to facebook, to a page with nothing but a logout button, and have facebook redirect the browser back to my site, ready for the next user. This is how the login works, and I need a logout equivalent.
Edit:
Thank you very much for the answer. We spent like 3 days trying to figure this out; I hope you will forgive us if we post generic code that anyone can plug in. Placing this on an HTML page, then visiting that page, logs the user out of Facebook and your site.
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'your APP ID', // App ID
channelUrl : '//WWW.YOURSITE.COM/channel.php or channel.html or whatever yours is', // Channel File
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Additional initialization code here
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
FB.logout();
alert('Thanks! You have been logged out of facebook.');
}
});
};
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
</script>
If you use the Facebook Javascript SDK, you can call FB.logout when they click your logout link as the documentation states:
FB.logout will log the user out of both your site and Facebook.