how to nest access tokens in javascript safely? - javascript

FB.api({user-id},
{
"fields":"context",
"access_token": anAccessToken
}, function (response) {
console.log(response);
})
I am currently getting mutual friends via the context object. But in order for that to happen, I need to pass both the app_scoped_userid and my accesstoken from Oauth.
I feel uneasy putting these two strings in my client, since together anyone can use them to query any information the user has allowed my app permission to use.
Is there a better solution? (I have been contemplating moving the graph call onto the server, but that works against the light server-heavy client structure I am trying to achieve.)
Am I right to be worried?

I don't think that it's correct how you're using this functionality. According to https://developers.facebook.com/docs/graph-api/reference/v2.2/user.context/mutual_friends you should be able to run the following request:
/{friend_id}?fields=context{mutual_friends}
The Access Token (from the currently logged-in User) should be handled transparently by the JS SDK. I see no need to specify it for the request:
FB.api('/{friend_id}?fields=context{mutual_friends}', function(response) {
console.log(response);
});
To the the {friend_id}, you'll need to query /me/friends first for the current User, and select a specific friend.

Related

Fetch POST to send DELETE query to MySQL - is it safe?

Since many web hosting websites (such as infinityfree and 000webhost) block HTTP DELETE requests I found a way how to send DELETE query to MySQL by adding a password to HTTP POST body which triggers PHP to send DELETE query to MySQL.
But is this safe since the password is visible in Front End and so visible to any site visitor? Can someone do harm to my database by using this password like making SQL injection?
In React JS:
async function sendDeleteRequest(i) {
const bodyWithPassword = {
...props.updatedProducts[i],
password: "kfI2KiIMOibKn0X98ufe$#!G^z78FNbbvI!fng0p*vk",
};
await fetch(Links["products"], {
method: "POST",
body: JSON.stringify(bodyWithPassword),
headers: {
"Content-Type": "application/json",
},
});
await props.refreshProductListContent();
}
In PHP:
//If HTTP body has password send DELETE query.
if ($json["password"] = "kfI2KiIMOibKn0X98ufe$#!G^z78FNbbvI!fng0p*vk") {
$deleteProduct = new $json["productType"]($json);
$deleteProduct->deleteProduct($json);
return;
}
//If password isn't added in the body add product to database
$newProduct = new $json["productType"]($json);
$newProduct->addProduct($json, $newProduct);
The short answer is - This is not safe
Having a hard-coded password in ReactJS, which is a client-based Javascript code, means that it's accessible to anyone who visits and loads the Javascript file. Anyone can read it, use it and abuse it.
There is not enough code provided to see if there is a SQL injection vulnerability as such. You should review deleteProduct and addProduct functions and see if you have parameterized all the parameters passed to a SQL query.
In a scenario where your code was vulnerable to a SQL injection, anyone can grab the client-side encoded password and abuse the SQL injection vulnerability.
Regarding the request type, there is no actual difference between a POST and a DELETE request (technically speaking), apart from how your server side code processes it, which is what you write and decide. Obviously the development world has agreed to common sense on which each of the methods does here https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods, which you should oblige by when doing development.

How to use Facebook token obtained through Firebase authentication appropriately?

I am trying to get a person's first name and last name when the person would like to sign up through Facebook, but wondering if there can be some security issue.
Based on the document from Firebase, the answer from Stack Overflow, and the explanation about parameters from Facebook website, I wrote the following codes:
firebase.auth().getRedirectResult().then(function(result) {
var token = result.credential.accessToken;
FB.api('/me', {fields: 'last_name', access_token: token}, function(response) {
console.log(response);
})
})
My main concern is that according to Facebook, it says:
One parameter of note is access_token which you can use to make an API call with a Page access token. App access tokens should never be used in this SDK as it is client-side, and your app secret would be exposed."
It looks like I cannot use this approach to get a user's first and last name.
Starting with Firebase 4.0.0, additional IdP data will be directly returned in the result of type UserCredential. You shouldn't need to make an additional API call to Facebook to get data like first/last name:
firebase.auth().getRedirectResult().then(function(result) {
if (result.user) {
// Additional user info like first name, last name,
// Facebook account url, gender, etc.
console.log(result.additionalUserInfo.profile);
// Facebook access token returned in the process
// for the scopes requested.
console.log(result.credential.accessToken);
}
});

Parse Server Node.js SDK: Alternative to Parse.User.become?

I want to completely dissociate my client app from Parse server, to ease the switch to other Baas/custom backend in the future. As such, all client request will point to a node.js server who will make the request to Parse on behalf of the user.
Client <--> Node.js Server <--> Parse Server
As such, I need the node.js server to be able to switch between users so I can keep the context of their authentification.
I know how to authentificate, then keep the sessionToken of the user, and I ve seen during my research than the "accepted" solution to this problem was to call Parse.User.disableUnsafeCurrentUser, then using Parse.User.become() to switch the current user to the one making a request.
But that feels hackish, and I m pretty sure it will, sooner or later, lead to a race condition where the current user is switched before the request is made to Parse.
Another solution I found was to not care about Parse.User, and use the masterKey to save everything by the server, but that would make the server responsible of the ACL.
Is there a way to make request from different user other than thoses two?
Any request to the backend (query.find(), object.save(), etc) takes an optional options parameter as the final argument. This lets you specify extra permissions levels, such as forcing the master key or using a specific session token.
If you have the session token, your server code can make a request on behalf of that user, preserving ACL permissions.
Let's assume you have a table of Item objects, where we rely on ACLs to ensure that a user can only retrieve his own Items. The following code would use an explicit session token and only return the Items the user can see:
// fetch items visible to the user associate with `token`
fetchItems(token) {
new Parse.Query('Item')
.find({ sessionToken: token })
.then((results) => {
// do something with the items
});
}
become() was really designed for the Parse Cloud Code environment, where each request lives in a sandbox, and you can rely on a global current user for each request. It doesn't really make sense in a Node.js app, and we'll probably deprecate it.
I recently wrote a NodeJS application and had the same problem. I found that the combination of Parse.User.disableUnsafeCurrentUser and Parse.User.become() was not only hackish, but also caused several other problems I wasn't able to anticipate.
So here's what I did: I used
Parse.Cloud.useMasterKey(); and then loaded the current user by session ID as if it was a regular user object. It looked something like this:
module.exports = function(req, res, next) {
var Parse = req.app.locals.parse, query;
res.locals.parse = Parse;
if (req.session.userid === undefined) {
res.locals.user = undefined;
return next();
}
Parse.Cloud.useMasterKey();
query = new Parse.Query(Parse.User);
query.equalTo("objectId", req.session.userid);
query.first().then(function(result) {
res.locals.user = result;
return next();
}, function(err) {
res.locals.user = undefined;
console.error("error recovering user " + req.session.userid);
return next();
});
};
This code can obviously be optimized, but you can see the general idea. Upside: It works! Downside: No more use of Parse.User.current(), and the need to take special care in the backend that no conditions occur where someone overwrites data without permission.

How to request, store, and use an access token in Meteor while using the Instagram API

How does one request, store, and use an access token from an API in the Meteor framework? I am currently trying to make requests from the (Instagram API)[https://instagram.com/developer/authentication/], but I first need to request an access token and store it for later use.
What is the general structure for doing this? I have my Client Id and Client Secret stored in the settings.json and have the services configuration package loaded. I think I need to create some sort of Method using http.get, but if someone could give a brief walkthrough that would be greatly appreciated ! Not much on this in the Meteor Docs.
You can use Bozhao Package for this.
Just install it.
meteor add bozhao:accounts-instagram
And this will work exactly like tha core accounts - facebook || google || twitter
and you can do something like this on the accountsOnCreateUser Methods
if (user.services.instagram) {
console.log("-- REGISTED USER WITH INSTAGRAM ");
instagramProfile = {
socialProfileUrl: user.services.instagram.profile_picture,
socialName: user.services.instagram.full_name,
service: "Instagram",
profileUrl: "https://instagram.com/"+ user.services.instagram.username
};
user.profile = instagramProfile;
}
Now knowing this, you can see that we have the user data inside the user.services.instagram object, there should be a accessToken and id field that you make POST / GET http request to the https://instagram.com/api/v1/.
I have never done a HTTP request to the Instagram API but it should be similar to facebook (if not sorry the below code dosnt help you to much).
Simple http call using the params.
Meteor.http.get("https://instagram.com/api/v1/", {
headers: {
"User-Agent": "Meteor/1.0"
},
params: {
access_token: user.services.accessToken
}
},function(error,result){
if(!error){
console.log(result);
}
});

Parse.com: Authenticate user before updating object?

The scenario is similar to Evernote: a user can own multiple notes that can be viewed publicly but cannot be edited by anyone other than himself.
(I have implemented creating notes, but now get confused on updating notes. Have read docs of data & security, but it didn't help me much; though I've known ACL.)
I tried this in backend:
Parse.beforeSave("Notes", function (request, response) {
Parse.User.current();
});
But I got error saying null (or undefined? sorry for forgetting the exact error) is not a function. I think that meant there is no Parse.User or Parse.User.current available in Cloud Function.
Then according to a question in archive of Parse.com forum I found:
Parse.beforeSave("Notes", function (request, response) {
var userId = new Parse.User({id : request.params.userId});
});
But it doesn't seem to be like a method of authentication. I mean, by this, I just trust data form client without authenticating it.
request.user will contain the user object that is making the request. Do whatever check you have to do on that object and return an error if the user is not allowed to edit it.
Even better, set proper ACL on each note object, for example "Public Read" and only write access for the creator. That should make the beforeSave hook unnecessary.

Categories

Resources