Authentication and OpenGraph - authentication

this is my first attempt playing around with facebook apps and OpenGraph. I've followed the example at developers.facebook.com. So far, so good.
What I am trying to do though is:
When clicking a certain image, check so that the user is logged and have authenticated your app. I want the user to be able to use the page without going through authentication. Only one specific action (clicking that image) requires that the user authenticate.
If the user is logged in and have authenticated your app then publish a message on the user's stream.
If the user is not logged in and/or have not authenticated your app show the authentication dialog if the user clicks on the image. Once accepted, post a message on the user's stream.
<a onclick="fb_login();" href="#" class="productlink1"><img id="product1" onclick="postCook()" alt="" src="img/fressko_heart_black.png"/></a> <a class="productlink2"><img id="product2" alt="" src="img/fressko_checked_black.png"/></a>
I know this is not the ultimate piece of code, especially as it has two onclick="" that will trigger at the same time. So, I need a different solution to that.
The JavaScript function to post on the user's feed looks like this:
function postCook()
{
FB.api(
'/me/xxxxxx:cook',
'post',
{ recipe: 'http://www.zzzzzzz.com/test/' },
function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Cook was successful! Action ID: ' + response.id);
}
});
}
The JavaScript to authenticate the user looks like this:
window.fbAsyncInit = function() {
FB.init({
appId : 'xxxxxx',
oauth : true,
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});};
function fb_login(){
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
//console.log(response); // dump complete info
access_token = response.authResponse.accessToken; //get access token
user_id = response.authResponse.userID; //get FB UID
FB.api('/me', function(response) {
user_email = response.email; //get user email
// you can store this data into your database
});
} else {
//user hit cancel button
console.log('User cancelled login or did not fully authorize.');
}
}, {
scope: 'publish_stream'
});
}(function() {
var e = document.createElement('script');
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);}());
Does anyone have any good solution to my problem? Or a kick in the right direction. I prefer using PHP usually, but for this mission JavaScript seems to be the weapon of choise.
Regards,

Related

jwt - Where to store token in Vue.js?

I read in some security blog that storing a token in localstorage is unsafe so what i want to do is to store the token in the vuex storage, and all the api call will include that token in all following request.
But I am not able to access the token in the first place during successful login, what I want to do is to store the token in the vuex storage for the first time, I thought of sending the token to the body of the response but it will be a vulnerable method so I am sending it in the header["authorization"].
below are my user.js and login.vue file respectively.
router.post('/login', function (req, res, next) {
const {
UserName,
Password
} = req.body;
if (UserName.length == 0 || Password.length == 0) {
res.status(400).json({
message: 'Email or Password is empty',
});
} else {
login_pool.query(
'SELECT * FROM authentication WHERE user_name = ($1) and password = crypt(($2), password)',
[UserName, Password],
(err, results) => {
if (err) {
throw err;
} else if (results.rows.length == 1) {
// On Successful Login
const token = jwt.sign(
{
user_name: results.rows[0].user_name,
full_name: results.rows[0].full_name,
phone_number: results.rows[0].phone_number,
},
btoa(process.env.TOKEN_SECRET), // converting token_secret to base 64
{ expiresIn: '1800s' },
{ algorithm: 'HS256' },
(err) => {
if (err) {
res.status(400).json({
message: 'Not able to create a token',
});
console.log(err);
}
}
);
res.header('Authorization', `Bearer ${token}`);
res.status(201).json({
message: results.rows[0].full_name + 'logged in.',
});
console.log(results.rows[0].full_name + 'Just Logged In. ');
} else {
login_pool.query(
'SELECT * FROM authentication WHERE user_name = ($1)',
[UserName],
(errUser, resultUser) => {
if (resultUser.rows.length != 1) {
res.status(400).json({
message: 'User with this email does not exist',
});
} else {
res.status(400).json({
message: 'Password is not correct',
});
}
}
);
}
}
);
}
});
LoginSubmit() {
this.axios
.post(
"http://127.0.0.1:3000/users/login",
{
UserName: this.UserName,
Password: this.Password,
},
{
headers: {
"Content-Type": "application/json;charset=UTF-8",
"Access-Control-Allow-Origin": "*",
Accept: "application/vnd.api+json",
},
}
)
.then(
(res) => {
// successful login
console.log(res.headers); // authentication header not present here
this.Error = "";
console.log(this.axios.defaults.headers.common); // authentication header not present here
},
(err) => {
console.log(err.response.data.message);
this.Error = err.response.data.message.replace(/"/g, "");
}
);
},
I've never seen it done like this. A JWT can just be sent as part of the body of the response to some POST /auth endpoint. You then save that token using some sort of storage.
Whether that is localStorage or a cookie is debatable; I personally just use localStorage so that the API can be as stateless as possible. However when using a cookie, you can set some sort of expiry to your cookie which makes sure its deleted after the expiry date.
Vuex store is in essence a global state object that loses all its contents once you refresh your browser window. That is unless you couple it with some sort of localStorage/sessionStorage that loads/saves to your Vuex store.
So I suggest you remove the Access-Control-Expose-Headers: Authorization header and just send the JWT token as a POST body response during authentication. The safety of such auth request depends on whether you use http or https. You obviously always want to use https because everything that is not can easily be read plain-text by some malicious owner of a (wifi-)network.
res.header({
Authorization: "Bearer" + token,
"Access-Control-Expose-Headers": "Authorization",
});
Using Access-Control-Expose-Headers solved my problem now I can access the Authorization Header at the frontend part by using res.headers["authorization"]
Our vue app is storing the token in the sessionStorage and running into an strange issue because of it.
The normal behavior we see and expect is each time a user goes to our app on a new tab, they have to authenticate. This works fine in all browser, all the time. There is one path only on Windows Chrome where the user does not have to authenticate.
Make sure there is at least one other tab or instance of Chrome open, whether or not there is a website loaded is not relevant.
Log into our site
Close the tab.
Open either a new tab or new instance of Chrome.
Go to the browser History and restore the tab that was just closed.
In this scenario the sessionStorage is restored and the user is logged in. I have been able to duplicate this in a simple HTML Page.
Is there some other way to save the JWT token other then the sessionStorage?
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Session Persists Test</title>
<style>
div { margin: .75em; }
input { margin-left: 2em;}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script>
$(document).ready(function () {
const formatDateTime = function (date_ob) {
let date = ("0" + date_ob.getDate()).slice(-2);
let month = ("0" + (date_ob.getMonth() + 1)).slice(-2);
let year = date_ob.getFullYear();
let hours = ("0" + date_ob.getHours()).slice(-2);
let minutes = ("0" + date_ob.getMinutes()).slice(-2);
let seconds = ("0" + date_ob.getSeconds()).slice(-2);
return `${month}-${date}-${year} ${hours}:${minutes}:${seconds}`;
};
const updateTimes = () => {
let now_token = formatDateTime(new Date());
let session_now_token = sessionStorage.getItem('now_token');
if (session_now_token == null) {
session_now_token = now_token;
sessionStorage.setItem('now_token', session_now_token);
}
$("#sessionTime").text(`Session Time: ${session_now_token}`);
$("#lastCall").text(`Current Time: ${now_token}`);
}
$("#updateSession").click(function () {
sessionStorage.clear();
location.reload();
});
$('#updateTime').click(updateTimes);
updateTimes();
});
</script>
</head>
<body>
<h1>Session Persists Test</h1>
<div><span id="sessionTime">Session Time: (please enable Javascript not running>)</span><input id="updateSession" type="button" value="Update Session Time"></div>
<div><span id="lastCall">Current Time: (please enable Javascript not running>)</span><input id="updateTime" type="button" value="Update Current Time (or press F5)"></div>
<H3>Testing of how long a browser session persists.</H3>
<div>
<p>Google Chrome Version 97.0.4692.99 on Windows is not clearing the session when restoring a tab from the history. This site
has been created to test and demo that issue.</p>
<ul>
<li>When this page is first loaded (or the Update Session time button is pressed) the session variable with the
time is updated from the server.
</li>
<li>Each time the browser is refreshed (F5) the current time is updated.</li>
<li>When a new tab opened to this site, the there will be a new session storage and a new session time.</li>
</ul>
<h3>The Problem:</h3>
<p>A new session is NOT create when restoring a tab from history. To reproduce, using Google Chrome on Windows do the following:</p>
<ol>
<li>Make sure there is at least one other tab or instance of Chrome open, whether or not there is a website
loaded is not relevant.
</li>
<li>Load this site and record the session time.</li>
<li>Close the tab that is displaying this site.</li>
<li>Open either a new tab or new instance of Chrome.</li>
<li>Go to the browser History and restore the tab that was just closed.</li>
</ol>
<p>The session time is the same time recorded in step 2. As long as there is at least one instance of Chrome
running, when restoring from history, the session will also be restored.</p>
<p>This is not the way eitehr Edge or Firefox is currently working. Both created a new session. Which browser is
working correctly?</p>
</div>
</body>
</html>

facebook login/logout issue in website

I’ve taken below code from Facebook developer, while login to FB it's showing only logout button not showing user name and profile with logout button. Is it possible to add our own button instead of Facebook login button?
<html>
<head><title>facelogin<title></head>
<body>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '478566162309261',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Here we subscribe to the auth.authResponseChange JavaScript event. This event is fired
// for any authentication related change, such as login, logout or session refresh. This means that
// whenever someone who was previously logged out tries to log in again, the correct case below
// will be handled.
FB.Event.subscribe('auth.authResponseChange', function(response) {
// Here we specify what we do with the response anytime this event occurs.
if (response.status === 'connected') {
// The response object is returned with a status field that lets the app know the current
// login status of the person. In this case, we're handling the situation where they
// have logged in to the app.
testAPI();
} else if (response.status === 'not_authorized') {
// In this case, the person is logged into Facebook, but not into the app, so we call
// FB.login() to prompt them to do so.
// In real-life usage, you wouldn't want to immediately prompt someone to login
// like this, for two reasons:
// (1) JavaScript created popup windows are blocked by most browsers unless they
// result from direct interaction from people using the app (such as a mouse click)
// (2) it is a bad experience to be continually prompted to login upon page load.
FB.login();
} else {
// In this case, the person is not logged into Facebook, so we call the login()
// function to prompt them to do so. Note that at this stage there is no indication
// of whether they are logged into the app. If they aren't then they'll see the Login
// dialog right after they log in to Facebook.
// The same caveats as above apply to the FB.login() call here.
FB.login();
}
});
};
// 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));
// Here we run a very simple test of the Graph API after login is successful.
// This testAPI() function is only called in those cases.
function testAPI() {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
}
FB.logout(function(response) {
// Person is now logged out
});
</script>
<!--
Below we include the Login Button social plugin. This button uses the JavaScript SDK to
present a graphical Login button that triggers the FB.login() function when clicked. -->
<div class="fb-login-button" data-max-rows="1" data-size="medium" data-show-faces="false" data-auto-logout-link="true">
</div>
</body>
</html>
You can use your own button and call FB.login on click:
document.getElementById('loginBtn').addEventListener('click', function() {
//do the login
FB.login(function(response) {
if (response.authResponse) {
//user just authorized your app
document.getElementById('loginBtn').style.display = 'none';
getUserData();
}
}, {scope: 'email,public_profile', return_scopes: true});
}, false);
Source: http://www.devils-heaven.com/facebook-javascript-sdk-login/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</script>
<script>
window.fbAsyncInit = function () {
// FB JavaScript SDK configuration and setup
FB.init({
appId: // FB App ID
cookie: true, // enable cookies to allow the server to access the session
xfbml: true, // parse social plugins on this page
version: 'v2.8' // use graph api version 2.8
});
// Check whether the user already logged in
FB.getLoginStatus(function (response) {
if (response.status === 'connected') {
//display user data
getFbUserData();
}
});
};
// Load the JavaScript 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_GB/sdk.js#xfbml=1&version=v2.8&appId=FB APP ID";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
// Facebook login with JavaScript SDK
function fbLogin() {
FB.login(function (response) {
if (response.authResponse) {
// Get and display the user profile data
getFbUserData();
} else {
document.getElementById('status').innerHTML = 'User cancelled login or did not fully authorize.';
}
}, {scope: 'email'});
}
// Fetch the user profile data from facebook
function getFbUserData() {
FB.api('/me', {locale: 'en_US', fields: 'id,first_name,last_name,email,link,gender,locale,picture'},
function (response) {
document.getElementById('fbLink').setAttribute("onclick", "fbLogout()");
document.getElementById('fbLink').innerHTML = 'Logout from Facebook';
document.getElementById('status').innerHTML = 'Thanks for logging in, ' + response.first_name + '!';
document.getElementById('userData').innerHTML = '<p><b>FB ID:</b> ' + response.id + '</p><p><b>Name:</b> ' + response.first_name + ' ' + response.last_name + '</p><p><b>Email:</b> ' + response.email + '</p><p><b>Gender:</b> ' + response.gender + '</p><p><b>Locale:</b> ' + response.locale + '</p><p><b>Picture:</b> <img src="' + response.picture.data.url + '"/></p><p><b>FB Profile:</b> <a target="_blank" href="' + response.link + '">click to view profile</a></p>';
});
}
// Logout from facebook
function fbLogout() {
FB.logout(function () {
document.getElementById('fbLink').setAttribute("onclick", "fbLogin()");
document.getElementById('fbLink').innerHTML = '<i class="fa fa-facebook-official" aria-hidden="true"></i>';
// document.getElementById('fbLink').innerHTML = '<div class="fb-login-button" data-max-rows="1" data-size="large" data-button-type="login_with" data-show-faces="false" data-auto-logout-link="false" data-use-continue-as="false"></div>';
document.getElementById('userData').innerHTML = '';
document.getElementById('status').innerHTML = 'You have successfully logout from Facebook.';
});
}
</script>

Disable auto login - facebook javascript SDK

I want to disable auto login in my website when there is a facebook session user. I want the user to click on the facebook login button
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId: '<?php echo $facebook->getAppID() ?>',
cookie: true,
xfbml: true,
oauth: true
});
FB.Event.subscribe('auth.login', function(response) {
window.location.reload();
});
FB.Event.subscribe('auth.logout', function(response) {
window.location.reload();
});
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
</script>
Just do this.
FB.init({
appId : 'key',
status : false,
cookie : true, // enable cookies to allow the server to access
// the session
xfbml : true, // parse social plugins on this page
version : 'v2.8' // use graph api version 2.8
});
and auto login will be disabled.
just put status on the top.
Instead of facebook events, simply use FB.Login.
Call the userLogin(), when the user click your Login button (not the facebook login button, but a simple button)
function userLogin()
{
FB.login(function(response)
{
if (response.authResponse)
{
console.log('Welcome! Fetching your information.... ');
var access_token = response.authResponse.accessToken;
location.href = "REDIRECT_TO.php";
}
else
{
console.log('User cancelled login or did not fully authorize.');
}
});
}
So now, the user have to click on the facebook login button every time he visits your site.
Add "status: false" inside your FB.init.
This will prevent an existing Facebook session from logging users in automatically.
https://developers.facebook.com/docs/unity/reference/current/FB.Init

The permissions in the settings don't match the ones in the login-dialogue

For my App, I need a users birthdate and email-address. So I set up the permissions to that!
In the preview it works just fine:
but in the actual login dialogue it does not!
Therefore, I don't have the permission. What do I do now?
Code: It's basically right out of facebook's getting started...
window.fbAsyncInit = function() {
FB.init({ // init the FB JS SDK
appId : 'XXXXXXXX', // App ID from the App Dashboard
channelUrl : 'http://nerdjokes.funpic.de/channel.html', // Channel File for x-domain communication
status : true, // check the login status upon init?
cookie : true, // set sessions cookies to allow your server to access the session?
xfbml : true // parse XFBML tags on this page?
});
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
loggedIn();
} else if (response.status === 'not_authorized') {
login(); //user hast not authorized the app. Display the dialogue
} else {
login();
}
});
};
function login() {
FB.login(function(response) {
if (response.authResponse) {
// connected
} else {
// cancelled
}
});

FB.Event.subscribe('auth.login', function(response) { }) issue

FB.Event.subscribe('auth.login', function(response) {
FB.api('/me', function(response){
//Some operation
});});
Above piece of JavaScript code runs when user logs-in through Facebook
or
when user is already logged-in the browser and you open the page containing the above JavaScript.
Is there any way to execute the operation only when user logs-in for first time and escape the operation when user is already logged-in in the browser?
Run FB.getLoginStatus to see if the user is already connected to your app and logged in.
https://developers.facebook.com/docs/reference/javascript/FB.getLoginStatus/
FB.getLoginStatus(function(response) {
if (response.session) {
// logged in and connected user, someone you know
} else {
// no user session available, someone you dont know
}
});
Try subscribing to the event if and only if the user is not connected.
function listen_for_authorization (cb) {
FB.getLoginStatus(function (res) {
if (!res || res.status !== "connected") {
FB.Event.subscribe('auth.login', cb);
}
}
}
We reproduced this in Safari/Mac, Firefox/Windows, Internet Explorer.
See http://developers.facebook.com/bugs/255767001140894