How can i update a parse user account with different user account - javascript

Hi i am trying do a very simple backend where admin can modify other users account but its not working. I understand this is happening because parse has some default security settings that does not allow this. Below is the code snippet from the update route of the web app:
//UPDATE ROUTE
router.put("/:id", function(req, res){
var Users = Parse.Object.extend("User");
var query = new Parse.Query(Users);
// find and update the correct user
query.get(req.params.id).then(function(user) {
user.set("name", req.body.name);
user.save().then(function(doctor) {
console.log("user has been updated");
res.redirect("/doctors/"+ req.params.id);
}, function(error) {
console.log(error.message);
});
}, function(error) {
console.log("user could not be retrieved!");
});
});
The Error Message is : Cannot modify user HeFxUOj7q9. HeFxUOj7q9 is the Objectid for the user which i am trying to update from another account(admin account)
I have an admin account already created on the parse server User class but I can't figure out how to update other accounts using the admin account. I am using parse server on nodeJs. I would really appreciate any help offered. Thanks in advance.

When you're initializing parse, you should include the masterKey and call useMasterKey like so:
Parse.initialize("YOUR_APP_ID", "YOUR_JAVASCRIPT_KEY", "YOUR_MASTERKEY");
Parse.serverURL = 'http://YOUR_PARSE_SERVER:1337/parse';
Parse.Cloud.useMasterKey();
However, be wary of doing this for endpoints that are publicly accessible, and never include your master key on a client-side application.

Related

Firebase: How do I get the ID Token for a signed-in user on the client side if I am using server-side session cookies?

I am using Firebase Cloud Functions with Express and Firebase Hosting to serve my multi-page site. I have successfully implemented server-side cookies as explained here and as implemented below:
function verifyLogin(request, response, next) {
const sessionCookie = request.cookies.__session || '';
firebase.auth().verifySessionCookie(sessionCookie, true /** checkRevoked */ )
.then((decodedClaims) => {
//serve content for user
return next();
}).catch(error => {
// Session cookie is unavailable or invalid. Force user to log in.
console.log(error);
response.redirect('/login');
return;
});
}
app.get('/', verifyLogin, (request, response) => {
var page_title = "Home";
response.render('index', {
page_title,
});
});
I am using the Firebase Web SDK (JavaScript) to access the Firebase Cloud Firestore. In order to do this, I need to get the idToken on the client side for the currently-logged-in user, like so:
firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
firebase.auth().currentUser.getIdTokenResult()
.then((idTokenResult) => {
// Access the Firebase Cloud Firestore here
});
}
});
This seems redundant to me, since I already know which user is signed in via my server cookie, but how else can I get the idToken without another call to Firebase Auth?
Is there a way to extrapolate it from my session cookie somehow and pass it to my client from my cloud function as a variable?
Or is there another way to look at this philosophically that I am overlooking?
In the same way you can listen to user sign-in state changes using onAuthStateChanged(), you can also listen to user ID token changes using onIdTokenChanged(). You will only need to use a new token when the observer you attach shows that a new one appears (for example, when it's refreshed every hour by the SDK).

How to create Microsoft Account Sign-in to my website, similar to Google?

I'm working on a web project (HTML, CSS, JavaScript, with back-end in PHP). I've successfully got a Google Sign-in working, using their simple API, but can't get the Microsoft equivalent to function. The official online solutions to this seem to rely on .NET or PHP Composer. I'll try composer if that's the only way but a pure JS/PHP method would be easiest.
I've tried to use the following:
https://github.com/microsoftgraph/msgraph-sdk-javascript
https://github.com/AzureAD/microsoft-authentication-library-for-js
The code below is the closest I've come to a working solution. I can get some kind of user ID (which appears to be unique and constant for each user). This might be enough to set up the login system I want, but it would be ideal if I could also fetch their name and profile picture.
<script class="pre">
var userAgentApplication = new Msal.UserAgentApplication("MY CLIENT ID", null, function (errorDes, token, error, tokenType) {
// this callback is called after loginRedirect OR acquireTokenRedirect (not used for loginPopup/aquireTokenPopup)
})
userAgentApplication.loginPopup(["user.read"]).then(function (token) {
var user = userAgentApplication.getUser(); //this is good
//user.userIdentifier seems to be a unique ID
//I will store this and use it for future verification
console.log(user);
//START
// get an access token
userAgentApplication.acquireTokenSilent(["user.read"]).then(function (token) {
console.log("ATS promise resolved");
}, function (error) {
console.log(error);
// interaction required
if (error.indexOf("interaction_required") != -1) {
userAgentApplication.acquireTokenPopup(["user.read"]).then(function (token) {
// success
console.log("s2");
}, function (error) {
console.log("e2");
// error
});
}
});
//END
// signin successful
}, function (error) {
console.log(error);
// handle error
});
</script>
(this code won't run as I've pasted it because it relies on the MSAL script from the second github link, and needs an application client ID)
After getting the access token with scope user.read , you could call microsoft graph api to get sign-in user's profile information such as displayName , businessPhones :
https://graph.microsoft.com/v1.0/me
Content-Type:application/json
Authorization:Bearer {token}
To get user's profile photo :
GET https://graph.microsoft.com/v1.0/me/photo/$value
In addition , if you are using Microsoft Graph JavaScript Client Library in first link , you could get user's displayName and profile photo by :
client
.api('/me')
.select("displayName")
.get((err, res) => {
if (err) {
console.log(err);
return;
}
console.log(res);
});
// Example of downloading the user's profile photo and displaying it in an img tag
client
.api('/me/photo/$value')
.responseType('blob')
.get((err, res, rawResponse) => {
if (err) throw err;
const url = window.URL;
const blobUrl = url.createObjectURL(rawResponse.xhr.response);
document.getElementById("profileImg").setAttribute("src", blobUrl);
});
Please refer to code sample here .

How to send Facebook authentication details to Firebase using a Cordova plugin & Firebase template

Sorry this question is kind of long, it's because I've been trying to solve this problem for a while and want to make sure I don't leave any info out. I'm building a Cordova app and using Firebase for the authentication/database back end. I've been trying to authenticate users into Firebase using a Log in with Facebook button for almost a week now, but I haven't been able to get it to work.
Originally I tried following Firebase's example here: https://firebase.google.com/docs/auth/web/facebook-login (I need to use the "Advanced: Handle the sign in flow manually" as it is a Cordova Android & iOS app), this example didn't work for me as the link to Facebook's SDK script (//connect.facebook.net/en_US/sdk.js) kept throwing the error:
file://connect.facebook.net/en_US/sdk.js Failed to load resource: net::ERR_FILE_NOT_FOUND
I tried to fix this error in several ways, such as:
Changing it to https://connect.facebook.net/en_US/sdk.js (this resulted in the error: Can't Load URL: The domain of this URL isn't included in the app's domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings. )
Added the links in question to the list of "Valid OAuth redirect URIs" and domains in the Facebook app settings
Storing the file in my local file system (and locally inside the app on my phone)
Including the entire SDK inside the head of my index.html file
None of these attempts worked. So instead I decided to use the plugin cordova-plugin-facebook from here: https://github.com/bisrael/cordova-plugin-facebook
This is the code I'm using to get the user's information from Facebook with the plugin:
function logInWithFacebook(){
CordovaFacebook.login({
onSuccess: function(result) {
console.log(result);
console.log(result.authToken);
// Store or send the user auth/access key here?
// Get user's name
retrieveUserDetails();
if(result.declined.length > 0) {
alert("The User declined something!");
}
},
onFailure: function(result) {
if(result.cancelled) {
alert("The user doesn't like my app");
} else if(result.error) {
alert("There was an error:" + result.errorLocalized);
}
}
});
}
function retrieveUserDetails(){
// Now that the user has authroised the app, make request to CordovaFacebook plugin to get user's name
CordovaFacebook.graphRequest({
path: '/me',
params: { fields: 'name' },
onSuccess: function (userData) {
console.log(userData);
console.log(userData.name);
// Here somehow send the retrieved username and send it to the Firebase function so that it's linked with the auth key.
},
onFailure: function (result) {
if (result.error) {
Error.log('error', 'There was an error in graph request:' + result.errorLocalized);
}
}
});
}
I'm now able to click on a log in button and log in successfully through Facebook. That process is returning a user auth/access key and the user's name from Facebook.
As I understand it, the manual log in flow example in Firebase's docs (https://firebase.google.com/docs/auth/web/facebook-login) takes the key returned from Facebook, converts it into a Firebase key, and then enters the user's newly created Firebase key and their username into Firebase's servers.
This seems pretty straight forward in the following sample code:
function checkLoginState(event) {
if (event.authResponse) {
// User is signed-in Facebook.
var unsubscribe = firebase.auth().onAuthStateChanged(function(firebaseUser) {
unsubscribe();
// Check if we are already signed-in Firebase with the correct user.
if (!isUserEqual(event.authResponse, firebaseUser)) {
// Build Firebase credential with the Facebook auth token.
var credential = firebase.auth.FacebookAuthProvider.credential(
event.authResponse.accessToken);
// Sign in with the credential from the Facebook user.
firebase.auth().signInWithCredential(credential).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
} else {
// User is already signed-in Firebase with the correct user.
}
});
} else {
// User is signed-out of Facebook.
firebase.auth().signOut();
}
}
function isUserEqual(facebookAuthResponse, firebaseUser) {
if (firebaseUser) {
var providerData = firebaseUser.providerData;
for (var i = 0; i < providerData.length; i++) {
if (providerData[i].providerId === firebase.auth.FacebookAuthProvider.PROVIDER_ID &&
providerData[i].uid === facebookAuthResponse.userID) {
// We don't need to re-auth the Firebase connection.
return true;
}
}
}
return false;
}
FB.Event.subscribe('auth.authResponseChange', checkLoginState);
My question is, how can I send the auth key and username returned from the Cordova plugin code, to Firebase's example code so that it works smoothly?
Firebase's example code includes this listener which listens for any change in the Facebook authorization status: FB.Event.subscribe('auth.authResponseChange', checkLoginState); but as this uses Facebook's SDK it won't work with my current set up.
I'm using the following Firebase chat app as a template to work from: https://gist.github.com/puf/8f67d3376d80ed2d02670d20bfc4ec7d as you can see it has a Login with Facebook button, but no code for handling the process, I'm trying to apply parts of the manual log in flow example in Firebase's docs (https://firebase.google.com/docs/auth/web/facebook-login) with data returned from the cordova-plugin-facebook queries, and integrate both with Firebase's chat app template.
I'm really at a loss as to what to do next, I've tried everything I can think of. Any help in solving this problem would be really, really appreciated.
Thank you in advance!
UPDATE
Questions and answers:
How does it work at the moment?
Right now I have a "Facebook Login" button - when this is clicked it runs logInWithFacebook(). This function uses the CordovaFacebook plugin, it also runs the function retrieveUserDetails() after the user signs in with Facebook. retrieveUserDetails() gets some user info from Facebook which I hope to then insert into my Firebase database.
logInWithFacebook() works correctly (it opens up a Facebook login page, and when the user logs in, I'm able to console.log the user's Facebook ID, and the Facebook access Token.
retrieveUserDetails() also works correctly (I'm able to console.log the user's name taken from Facebook).
How do you want it to work?
I'm happy with how the first half of the process is working (the logging in with Facebook and retrieving user details is working correctly). However I want this log in to trigger Firebase's auth state change listener, so that Firebase detects and confirms that the user has logged in:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log("User is signed in.");
} else {
console.log("User is not signed in.");
}
});
What is not working the way you want?
The first half of the process is working correctly, but I'm lost when it comes to what to do with the accessToken returned from Facebook. From reading the docs I think that Firebase is supposed to convert this token into a Firebase access token, and then that is used to log the user into Firebase (this would also trigger the above AuthStateChanged function). From there I want to be able to insert any data I've retrieved from Facebook (the user's name etc) into my Firebase database. But the main problem is getting the Facebook accessToken converted into a Firebase login (the second block of code in my original question is where I'm trying to perform the conversion/sign into Firebase).
Because I'm using Cordova, this method (logging into Facebook with a plugin and then handling the conversion of the accessToken) seems to be the only way to log in with Facebook. But I'm totally lost on how to complete the second half.
UPDATE 2
I've trimmed parts from the sample convert-Facebook-token-to-Firebase-token code from the docs so that the Facebook SDK isn't required. And it appears to be working. This is the code after cutting away the SDK related parts:
// First, define the Facebook accessToken:
var FBaccessToken = result.accessToken;
// Build Firebase credential with the Facebook auth token.
var credential = firebase.auth.FacebookAuthProvider.credential(
FBaccessToken);
// Sign in with the credential from the Facebook user.
firebase.auth().signInWithCredential(credential).then(function(user){
console.log("It looks like we signed into Firebase with the Facebook token correctly.");
}, function(error) {
console.log("Something went wrong, user isn't signed into Firebase with the FB token.");
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
I still need to add the user's email from Facebook and try to send that while logging into Firebase too - so that I'll have some identifier for the user in the Firebase console, but this is a good start.
2nd UPDATE
The below code successfully gets user data from Facebook after the user authorizes the app:
CordovaFacebook.graphRequest({
path: '/me',
params: { fields: 'first_name,last_name,email,locale,gender,age_range,picture.width(200).height(200)' },
onSuccess: function (userData) {
console.log(userData)
var first_name = userData.first_name;
var last_name = userData.last_name;
var email = userData.email;
var locale = userData.locale;
var gender = userData.gender;
var min_age = userData.age_range.min;
var profile_picture = userData.picture.data.url;
// Enter user details into the Firebase database:
firebase.database().ref('users/' + uid).set({
first_name: first_name,
last_name: last_name,
email: email,
locale: locale,
gender: gender,
min_age: min_age,
profile_picture : profile_picture
});
console.log("Facebook user data should now be in the database!");
},
onFailure: function (result) {
if (result.error) {
Error.log('error', 'There was an error in graph request:' + result.errorLocalized);
}
}
});
(Just an answer to the last update, as you figured out the rest :))
How to get user email from CordovaFacebook.login()
Looking at the CordovaFacebook documentation you can add a permissions property on the object passed to the login method.
According to the Facebook API documentation the permission name for email is just "email".
I haven't tested, but I think this should work:
CordovaFacebook.login({
permissions: [ 'email' ],
onSuccess: function(result) {
console.log('email:', result.email);
...
},
onFailure: function(result) {
...
}
});

Ongoing Access to Google Calendar API

How do I request access to a user's calendar once, then query events without having to request access again? Is there an access key that can grant continuous access as long as it isn't revoked?
I am currently using the google-calendar module in a nodejs app running express + mongodb.
The example below shows partial code for making the OAuth request and redirecting back to the app. This works great. What I want though is once I have access, to be able to query the user's events any time I want. This will be used in a booking app which, once a user registers their public Google Calendar, allows others to see their availability.
I have looked at the Google Calendar API documentation, but I can't figure out what is needed for the ongoing access I need.
Configuration:
var GoogleCalendar = require('google-calendar');
var google_calendar = new GoogleCalendar.GoogleCalendar(config.google.clientId, config.google.clientSecret, 'http://localhost:3000/authentication');
Display route:
app.get('/display', function(req, res) {
// redirect user to Google Authentication
var access_token = req.session.access_token;
if(!access_token) {
req.session.authReturn = req.url;
return res.redirect('/authentication');
}
google_calendar.listCalendarList(access_token, function(err, calendarList) {
// do something with the calendar events...
}
...
Authenticate route:
app.all('/authentication', function(req, res){
// Redirect the user to Google's authentication form
if(!req.query.code){
google_calendar.getGoogleAuthorizeTokenURL(function(err, redirectUrl) {
if(err) return res.send(500,err);
return res.redirect(redirectUrl);
});
}
// Get access_token from the code
else {
google_calendar.getGoogleAccessToken(req.query, function(err, access_token, refresh_token) {
if(err) return res.send(500,err);
req.session.access_token = access_token;
req.session.refresh_token = refresh_token;
return res.redirect(req.session.authReturn);
});
}
});
Use the Oauth 2.0 offline access parameter. See details at:
https://developers.google.com/accounts/docs/OAuth2WebServer#offline

Problems with OAuth on node.js

I am trying to get OAuth to work on node.js. I found this in the documentation of node-oauth:
var OAuth= require('oauth').OAuth;
var oa = new OAuth(requestUrl,accessUrl,consumerKey,consumerSecret,"1.0A",responseUrl,"HMAC-SHA1");
The next step in the official tutorial says:
"Then get hold of a valid access token + access token secret as per the normal channels"
What are these "normal channels"?
I know that the user has to authenticate somehow on the "vendor" site and that by some way a response url is called, but I can't find a description how to implement this. Can someone enlighten me?
I'm not sure what OAuth service you are trying to connect to so I'll just use twitter as an example. After you create your OAuth object you need to first request an oauth token. When you get that token, then you need to redirect to, for twitter, their authenticate page which either prompts them to login, then asks if it's ok for the app to login.
oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){
if (error) new Error(error.data)
else {
req.session.oauth.token = oauth_token
req.session.oauth.token_secret = oauth_token_secret
res.redirect('https://twitter.com/oauth/authenticate?oauth_token='+oauth_token)
}
});
When you first created the OAuth object, you set a responseURL, or the callback url. It can be anything, for my app its just /oauth/callback. In that callback you receive the oauth verifier token. You then use both the oauth request token and oauth verifier token to request the access tokens. When you receive the access tokens you will also receive anything else they pass, like their username.
app.get('/oauth/callback', function(req, res, next){
if (req.session.oauth) {
req.session.oauth.verifier = req.query.oauth_verifier
var oauth = req.session.oauth
oa.getOAuthAccessToken(oauth.token,oauth.token_secret,oauth.verifier,
function(error, oauth_access_token, oauth_access_token_secret, results){
if (error) new Error(error)
console.log(results.screen_name)
}
);
} else
next(new Error('No OAuth information stored in the session. How did you get here?'))
});
Hope this helps! I had the same problems when I started on this.
The access token is issued to your application after walking the user through the "OAuth dance" (as its affectionately known). This means obtaining a request token and redirecting the user to the provider (Twitter, in this case) for authorization. If the user grants authorization, Twitter redirects the user back to your application with a code that can be exchanged for an access token.
node-oauth can be used to manage this process, but a higher-level library will make it much easier. Passport (which I'm the author of), is one such library. In this case, check out the guide to Twitter authentication, which simplifies the OAuth dance down to a few lines of code.
After that, you can save the access token in your database, and use it to access protected resources in the usual manner using node-oauth.
An update to post tweet to user timeline:
#mattmcmanus, Extending #mattmcmanus nice answer, I would like to post a tweet to timeline. For this, I am using the same code as mattcmanus given above.
Step 1:
oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){
if (error) new Error(error.data)
else {
req.session.oauth.token = oauth_token
req.session.oauth.token_secret = oauth_token_secret
res.redirect('https://twitter.com/oauth/authenticate?oauth_token='+oauth_token)
}
});
Step 2:
app.get('/oauth/callback', function(req, res, next){
if (req.session.oauth) {
req.session.oauth.verifier = req.query.oauth_verifier
var oauth = req.session.oauth
oa.getOAuthAccessToken(oauth.token,oauth.token_secret,oauth.verifier,
function(error, oauth_access_token, oauth_access_token_secret, results){
if (error) new Error(error){
console.log(results.screen_name)
}else{
// NEW CODE TO POST TWEET TO TWITTER
oa.post(
"https://api.twitter.com/1.1/statuses/update.json",
oauth_access_token, oauth_access_token_secret,
{"status":"Need somebody to love me! I love OSIpage, http://www.osipage.com"},
function(error, data) {
if(error) console.log(error)
else console.log(data)
}
);
// POST TWEET CODE ENDS HERE
}
}
);
} else
next(new Error('No OAuth information stored in the session. How did you get here?'))
});
I have added oauth_access_token & oauth_access_token_secret in commented code. This will post a tweet update to user's timeline. Happy tweeting!!!

Categories