I´ve seen a lot of weird coding happening around Login with the Facebook JavaScript SDK, so here is one good solution with explanation.
HTML (just a login button and a div for the response)
<button id="loginBtn">Facebook Login</button> <div id="response"></div>
JavaScript
function getUserData() { FB.api('/me', {fields: 'name,email'}, (response) => { document.getElementById('response').innerHTML = 'Hello ' + response.name; }); } window.fbAsyncInit = () => { //SDK loaded, initialize it FB.init({ appId : 'your-app-id', xfbml : true, version : 'v2.2' }); //check user session and refresh it FB.getLoginStatus((response) => { if (response.status === 'connected') { //user is authorized document.getElementById('loginBtn').style.display = 'none'; getUserData(); } else { //user is not authorized } }); }; //load the JavaScript SDK ((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.com/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); //add event listener to login button document.getElementById('loginBtn').addEventListener('click', () => { //do the login FB.login((response) => { if (response.authResponse) { //user just authorized your app document.getElementById('loginBtn').style.display = 'none'; getUserData(); } }, {scope: 'email,public_profile', return_scopes: true}); }, false);
Of course there is room for improvement (there always is), but i am just trying to explain when (and how) you should use FB.login and FB.getLoginStatus. For example, you should hide the login button with CSS, right now it shows up for a short time and disappears if the user is authorized already – because it takes some time until the callback function of FB.getLoginStatus gets called. You could also use the Social Plugin for the Login Button, but i guess you want to use your own design so that´s not an option in most cases.
FB.login: FB.login opens the authorization window where users can authorize your App. It must get called directly on user interaction (mouse click), you can´t call it right after FB.init and you can´t call it in the asynchronous callback function of FB.getLoginStatus either. Make sure you understand what asynchronous means, it´s very important to know for a web developer. If you don´t call it on user interaction, it may get blocked by popup blockers. The benefit of using FB.login for authorization is that you don´t need to redirect the user to a login screen – the PHP SDK does not offer that kind of usability.
FB.getLoginStatus: This function should get used on page load, right after FB.init. The major advantage of using this instead of a server side login process (with the PHP SDK, for example) is that it will refresh the User Token without page refresh. That is another benefit of using the JavaScript SDK, and it´s a pretty important one.
FB.api: This is actually not about the login process anymore, it´s just a basic API call to get the basic user data in the example. FB.api can only be used after FB.init. Should be obvious though, you can´t use the API before initializing the SDK.
return_scopes: Asking for permissions in the authorization process is not a sure thing. The user can just deselect the email permission in the authorization popup, for example. It´s quite easy to check for the authorized permissions by setting return_scopes in FB.login, as you can see in the code. If you add that parameter, you will get a list of all granted permissions in the grantedScopes field of response.authResponse.
That´s it, if you got any improvement tips or find any errors, feel free to comment 🙂 – here are some links to the Facebook docs, if you need more information:
I try to use like what you did in your article.
But i get this error, “Given URL is not permitted by the application configuration.: One or more of the given URLs is not allowed by the App’s settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App’s domains.”
Do you know why it gave such error?
Thanks for your explanation.
you need to add one of the platforms in the app settings, with your url.
Hello, all this website was actually extremely useful. Still there’s a couple of things I’d like to know.
1. Can you suggest a way I can redirect the users to an “HTML2” page after he logged in on “HTML1” page?
2. Besides, I’m still wondering.. If I take short-lived access token with Javascript (requesting extended permissions) how can I pass this token to a php page in order to get a long-lived token and make API request from the back-end?
Sorry for bothering and thanks for all your help, you’ve already helped a lot a newbie to understand all this stuff 🙂
redirection is easy, you can do that with javascript (location.href….).
another blogpost of mine may help you with the second question, just make sure to activate appsecret_proof: http://www.devils-heaven.com/facebook-php-sdk-4-0-tutorial/
This is preety neat. I have a slight issue I’m using this mostly like it is here, however, it’s not working on firefox/safari on mobile. Any idea why? (note: the site is a mobile oriented/responsive site I’m making and it works wonderfully on chrome and android chrome however Firefox/safari are not as friendly)
i am afraid there is not enough information to help you in a serious way, to be honest. i suggest posting your question on stackoverflow (feel free to post a link to the thread in here), with all the neccessary details (your login code, a test link, …)
Hi,
How we can retrieve user email and photo using api with your code ?
I tried retrieving user info but , I am not getting any user data expect user id and user name …
Thanks
check out the official changelog for v2.4 of the graph api, search for “declarative fields”. that will answer your question.
How would you go about solving this for isomorphic applications?
My understanding is that the async loading of the FB code means that the server code is different from the client one, therefore breaking the isomorphism.
isomorphic apps don´t just run the exact same code on server and client, they share parts of the codes. for example, you can use the same components if you work with react. of course the javascript sdk only works client side, so that´s not really isomorphic.
Indeed, I didn’t mean that the code should be identical, only the HTML code that was produced should be the same, to benefit from the react rendering.
Perhaps a good idea would be to use the javascript code in the server (nodejs bit)?
I used your code with very little changes and it worked beautifully for what I needed. Thank you! Only thing is where I put the code is down a bit on the page and when I open the page it jumps down to that section – like a hyperlink is re-positioning it. Do you have any idea why that would happen? Thanks again for the code.
i´d need to see a test link, but in general it should not be related to the javascript sdk.
nice
This facebook developer page gives a complete example of logging in: https://developers.facebook.com/docs/facebook-login/web
i know, they improved the docs a lot since i wrote this article. although, i prefer my example, it works since many years and is easy to understand 🙂
Sorry to bother, how to extend the user access token in Javascript?
what for? if you mean client side javascript, then why not just use a default user token? generating an extended one would be pointless if the user is online anyway. if you want to store it, just use your server language to generate the extended one. would be safer anyway.
>> FB.login:
– you can´t call it right after FB.init
– you can´t call it in the asynchronous callback function of FB.getLoginStatus
Could you please explain why is this happening?
Since I want to load the JS SDK only after user clicks login button (I need this only once to get user id and token for server verification) I’m interested how it works.
that´s a basic browser feature, to block popups/ad-iframes. you can only call FB.login on user interaction, as it opens a popup.
loading the js sdk after a user clicks on a login button does not make any sense, you need the js sdk to make the login work.
2017 and still helping people.
Awesome explanation.
😀