I am using login with facebook utility of parse in my android application. Login with facebook utility works fine. it inserts only "userName" and "authData" column of "User" table.
I am getting name and email of facebook user using graph API of facebook.
Question -
How do we store "fullName" and "email" of facebook user into parse?
Thanks in advance!
I was able to write user Facebook details in CloudCode by doing the following:
Parse.Cloud.beforeSave(Parse.User, function (request, response) {
// Use Master Key
Parse.Cloud.useMasterKey();
// Pull User Object
var User = request.object;
// User Check
if (!User) {
// Not allowed
response.error();
return;
}
// For some reason, pulling authData fails. A try catch helps the TypeError that may happen
try {
var authData = User.get('authData');
var access_token = authData.facebook.access_token;
} catch(e) {
var access_token = null;
}
Parse.Cloud.httpRequest({
url:'https://graph.facebook.com/v2.1/me?fields=picture.height(50).width(50),email,first_name,last_name,friends.limit(5000),name,gender&access_token='+access_token,
success:function (httpResponse) {
// Success
var facebookIds = [];
try {
var facebookFriends = httpResponse.data.friends.data;
} catch (e) {
var facebookFriends = [];
}
var promise = _.each(facebookFriends, function(facebookFriend) {
facebookIds.push(facebookFriend.id);
});
Parse.Promise.when([promise]).then(function () {
if (request.object.existed() == false) {
User.set("displayName", httpResponse.data.name);
}
// Updating user object
User.set("facebookFriends", facebookIds);
User.set("fbEmail", httpResponse.data.email);
User.set("profileThumb", httpResponse.data.picture.data.url);
User.set("facebookId", httpResponse.data.id);
User.set("gender", httpResponse.data.gender);
response.success();
});
},
error:function (error){
// Error
response.error('Server error.')
}
});
});
Related
I'm completely new to flutter development and I am making a login for admins in my flutter mobile app.
The email address used in the login already exists in Firebase Authentication, but before I have it proceed to logging in the app, I first need to check if the inputted email address is stored in Realtime Database. How do I go about this in terms of code?
The flow is like this: user inputted "abc#gmail.com" as email address for login. App checks rtdb if there is a value of "abc#gmail.com", if true, proceed with login.
I understand I have to use
var rtdbref =
FirebaseDatabase.instance.reference().child("Admins").child("adminEmail");
but after that I have no idea how to have Flutter read the values. Any help is very much appreciated! Thank you :)
Image for rtdb reference:
screenshot of rtdb
Code I have so far:
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
var rtdbref =
FirebaseDatabase.instance.reference().child("Admins").child("adminEmail");
void loginAdmin(BuildContext context) async {
try {
final User? firebaseUser =
(await _firebaseAuth.signInWithEmailAndPassword(
email: emailTextEditingController.text,
password: passwordTextEditingController.text))
.user;
if (firebaseUser != null) {
var isAdmin = await rtdbref.child("Admins").once();
if (isAdmin.value["adminEmail"] == emailTextEditingController.text) {
//check if admin here
if (firebaseUser.emailVerified) {
//if (firebaseUser.emailVerified) {
usersRef.child(firebaseUser.uid).once().then((DataSnapshot snap) {
if (snap.value != null) {
Navigator.pushNamedAndRemoveUntil(
context, Navbar.idScreen, (route) => false);
//displayToastMessage("Homepage", context);
}
});
} else {
displayToastMessage("Please verify your account", context);
await firebaseUser.sendEmailVerification();
}
} else {
_firebaseAuth.signOut();
displayToastMessage("Account does not exist", context);
}
}
} on FirebaseAuthException catch (e) {
if (e.code == 'wrong-password') {
displayToastMessage("Wrong password", context);
}
if (e.code == 'too-many-requests') {
displayToastMessage("Please try again after 2 minutes", context);
}
if (e.code == 'user-not-found') {
displayToastMessage("User not found", context);
}
}
//displayToastMessage("Admin login test", context);
}
Update: I've attempted the following but still cannot seem to get it to read the adminEmail values of node Admins. What am I missing here? I feel like im so close
DatabaseReference adminsRef =
FirebaseDatabase.instance.reference().child("Admins");
var isAdmin = adminsRef
.orderByChild("adminEmail")
.equalTo(emailTextEditingController.text);
I can not create a server session in the mobile requests.
I am developing a mobile application. Sign in with LinkedIn to application made only from mobile.
I wrote the rest api with nodejs. I used the passport for linkedin login.Then I tested it from browser.It worked smoothly on browser.
When i make a request to my endpoint(/auth/linkedin) it redirect to linkedin and typing my account information and allow the app .It is redirect again to callback endpoint (auth/linkedin/callback). I am returning information of the logged-in user if success login. I am making process this session information on next requests.
But when I login from mobile, user information is printed webview and I cannot create session.How can i solve this problem. What am I doing wrong?
I am junior. if you see my code wrong please specify for improve my skill.
app.js
const AuthController = require("./router/Auth");
app.use(express.json());
app.use(session({
secret:'secretkey',
saveUninitialized: false,
resave: true,
cookie: {maxAge: 365*24*60*60*1000}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use('/auth',AuthController);
passport.use(new LinkedInStrategy({
clientID: config.linkedin.clientID,
clientSecret: config.linkedin.clientSecret,
callbackURL: config.baseUrl[env] + "/auth/linkedin/callback",
scope: config.linkedin.scope
},
function(accessToken, refreshToken, profile, done) {
User.findOne({'linkedin.id' : profile.id}, function(err, user) {
if (err) return done(err);
if (user) return done(null, user);
else {
// if there is no user found with that linkedin id, create them
var newUser = new User();
// set all of the linkedin information in our user model
newUser.linkedin.id = profile.id;
newUser.linkedin.token = accessToken;
newUser.name = profile.displayName;
if (typeof profile.emails != 'undefined' && profile.emails.length > 0)
newUser.email = profile.emails[0].value;
if(typeof profile.photos != 'undefined' && profile.photos.length> 0)
newUser.photo = profile.photos[0]
// save our user to the database
newUser.save()
.then(createWallet)
.then(updateWallet)
.then(user => {
return done(null,user)
})
.catch(err =>{
throw err;
});
}
});
}
));
passport.serializeUser(function(user, done){
done(null, user.id)
})
passport.deserializeUser(function(id, done) {
User.getUserById(id, function(err, user) {
done(err, user);
});
});
app.listen(PORT,()=>{
console.log("Listening...",PORT);
});
function createWallet (user){
const userId = user.id;
return new Promise((resolve,reject) => {
request(config.blockChain['url']+'/?type=register&userID='+userId,{json:true} ,(err,res,body)=>{
if(err) reject(err);
user.wallet = {
"secret":body.secret,
"publicKey":body.publicKey
}
resolve(user);
})
}
)
}
function updateWallet(user){
return user.save();
}
Auth.js
router.get('/linkedin', passport.authenticate('linkedin'));
router.get('/linkedin/callback',
passport.authenticate('linkedin',{ failureRedirect: '/'}),(req,res)=>{
const user = req.user;
response = {
status:true,
msg:"Login is successfull",
data: user
}
res.status(200).json(response);
});
I have a web app currently running with NodeJS and Express, where I authenticate the users using Passport sessions, and it works perfectly. Here is the overview of what I do:
app.use(session({
secret : 'hidden of course :)',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
/****** Passport functions ******/
passport.serializeUser(function (user, done) {
done(null, user.idUser);
});
passport.deserializeUser(function (id, done) {
db.user.findOne( { where : { idUser : id } }).then(function (user, err) {
done(null, user);
});
});
//Facebook
passport.use(new FacebookStrategy({
//Information stored on config/auth.js
clientID: *******,
clientSecret: ******,
callbackURL: *******,
profileFields: ['id', 'emails', 'displayName', 'name', 'gender', 'picture.type(large)']
}, function (accessToken, refreshToken, profile, done) {
//Using next tick to take advantage of async properties
process.nextTick(function () {
db.user.findOne( { where : { idUser : profile.id } }).then(function (user, err) {
if(err) {
return done(err);
}
if(user) {
return done(null, user);
} else {
// Check whether the email is undefined or valid
var emailTemp = '';
if(profile.emails && profile.emails[0] && profile.emails[0].value) {
emailTemp = profile.emails[0].value;
} else {
emailTemp = '';
}
var picture = '';
if(profile.photos && profile.photos[0] && profile.photos[0].value) {
picture = profile.photos[0].value;
} else {
picture = '/img/profile.png';
}
var sexFb = '';
if(profile.gender) {
sexFb = profile.gender;
} else {
sexFb = '';
}
// Create the user
db.user.create({
idUser : profile.id,
token : accessToken,
picture : picture,
nameUser : profile.displayName,
email : emailTemp,
sex : sexFb
}).then(function () {
db.user.findOne( { where : { idUser : profile.id } }).then(function (user, err) {
if(user) {
return done(null, user);
} else {
return done(err);
}
});
});
}
});
});
}));
app.use(express.static(__dirname + '/public/'));
/* FACEBOOK STRATEGY */
// Redirect the user to Facebook for authentication. When complete,
// Facebook will redirect the user back to the application at
// /auth/facebook/callback//
app.get('/auth/facebook', passport.authenticate('facebook', { scope : ['email']}));
/* FACEBOOK STRATEGY */
// Facebook will redirect the user to this URL after approval. Finish the
// authentication process by attempting to obtain an access token. If
// access was granted, the user will be logged in. Otherwise,
// authentication has failed.
app.get('/auth/facebook/callback',
passport.authenticate('facebook', { failureRedirect: '/' }),
function (req, res) {
// Successful authentication, redirect home.
res.redirect('../../app.html');
});
Now, I'm building our Android App and I need to authenticate our users, preferably using the backend I already built for the web version. I was checking some questions on SO like this one and I understood a lot of what I would have to do.
Currently my clients stay logged in through the cookie that Express-session handles, saving the user's id on the req.user, so that I can run queries like on this example:
app.put('/profile', function (req, res) {
//Updates the profile information of the user
db.user.update({
nameUser : req.body.nameUser
}, {
where : {
idUser : req.user.idUser
}
}).then(function (user) {
res.json({ yes : "yes" });
});
});
So my questions:
Can I authenticate my users using the same strategy as the one I currently have? If not, what would I have to change to be able to authenticate my users on Android?
Once they are authenticated, how can I set the req.user from Android (through HTTP request or whatever mean) to correctly perform the tasks on the backend (since all my requests are based on req.user)? I assume Android doesn't keep cookies like browsers do, so how would Passport Sessions know which user is calling the API?
I currently use Retrofit2 on my Android app to interact with the API, is it able to perform the actions necessary for this task?
Sorry for the long post, added a good chunk of code just to be on the safe side, if you guys have any questions or need any explanation please let me know!
so this is the main.js file in my cloud:
Parse.Cloud.define("addChannelToUser",function(request,response)){
var userId = request.params.userId;
var listId = request.params.listId;
var User = Parse.Object.extend("User"),
user = new User({ objectId: userId });
user.add("channels",listId);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
and this is where I call it from my app:
ParseCloud.callFunctionInBackground("addChannelToUser",params,
new FunctionCallback<Object>() {
#Override
public void done(Object o, ParseException e) {
if(e != null){
Log.d("cloud error", e.toString());
}else{
Log.d("cloud", "success");
}
}
});
my goal is to add the lisId to the "channel" field of a user with userId.
of course this user is not the user logged in the device so I obviously need to use the master key...
anyway, I keep getting the error "function not found", please help me :)
I just copy your code to my main.js file and try to deploy the code to Parse Cloud. However, Parse generates me a syntax error where I correct as follows;
Parse.Cloud.define("addChannelToUser",function(request,response)
{
var userId = request.params.userId;
var listId = request.params.listId;
var User = Parse.Object.extend("User"),
user = new User({ objectId: userId });
user.add("channels",listId);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
You can extract where you make mistake. The cloud function is tested in Parse environment. It is working. Hope this helps.
Regards.
I managed to log into Facebook with childBrowser plugin without any problems:
function deviceStart() {
FB.init({ appId: "xxxxxxxxxxxxxx", nativeInterface: PG.FB });
};
function onPubFacebookBtn(){ // I call this from a button
var my_client_id = "xxxxxxxxxxxxx",
my_redirect_uri = "http://www.facebook.com/connect/login_success.html",
my_type = "user_agent",
my_display = "touch"
var authorize_url = "https://graph.facebook.com/oauth/authorize?";
authorize_url += "client_id="+my_client_id;
authorize_url += "&redirect_uri="+my_redirect_uri;
authorize_url += "&display="+my_display;
authorize_url += "&scope=publish_stream,user_photos,email,user_online_presence,offline_access"
window.plugins.childBrowser.onLocationChange = facebookLocChanged;
window.plugins.childBrowser.onClose = closed;
window.plugins.childBrowser.showWebPage(authorize_url);
}
function facebookLocChanged(loc){
if (/login_success/.test(loc)) {
var fbCode = loc.match(/code=(.*)$/)[1]
localStorage.setItem('pg_fb_session', JSON.stringify(fbCode));
FB.Auth.setSession(fbCode, 'connected');
window.plugins.childBrowser.close();
}}
When I test if the app is logged in with
function getLoginStatus() {
FB.getLoginStatus(function(response) {
if (response.session) {
alert('logged in');
} else {
alert('not logged in');
}
});
}
it returns "loged in", but when I try to get user ID i get an error saying I need an active access token:
function me() {
FB.api('/me', function(response) {
if (response.error) {
alert(JSON.stringify(response.error));
} else {
var data = document.getElementById('data');
response.data.forEach(function(item) {
var d = document.createElement('div');
d.innerHTML = item.name;
data.appendChild(d);
});
}
});
}
This is a mixture of 2 solutions for loging into facebook of which none works.
Help!?
I have used the following code to get the Facebook user's name, please try once.
params='access_token='+accessToken;
$.get("https://graph.facebook.com/me",params,
function(response){
fbUesrName=response.name;
},"json");
You need to have an application on Facebook to generate access token, then you can get the ID, but it would be in the encrypted form.