How to set up profiles and sessions in Firebase and Ionic using Facebook Auth - facebook

I am very new to Firebase and struggling to set up a system where a user logs in via Facebook, and his/her profile picture is saved in a database.
I have a users and also a uids array in Firebase. What I want the flow to be is:
Login via Facebook
Store some memory of the user so they don't have to login again on the app, or perhaps store into the uids and users array
Get the existing name, location to fill into a profile section of the app
Update any of these to then fill into the Firebase users database, as well as add new fields e.g. location
Here is my current setup:
Login Controller:
.controller('LoginCtrl', ['Auth', '$state', '$location', '$scope', '$rootScope', '$firebaseAuth', '$window',
function (Auth, $state, $location, $scope, $rootScope, $firebaseAuth, $window) {
// check session
//$rootScope.checkSession;
// Create a callback to handle the result of the authentication
$scope.user = {
email: this.email,
password: this.password
};
$scope.validateUser = function (user) {
$rootScope.show('Please wait.. Authenticating');
console.log('Please wait.. Authenticating');
var email = this.user.email;
var password = this.user.password;
/* Check user fields*/
if (!email || !password) {
$rootScope.hide();
$rootScope.notify('Error', 'Email or Password is incorrect!');
return;
}
/* All good, let's authentify */
Auth.$authWithPassword({
email: email,
password: password
}).then(function (authData) {
console.log(authData);
//$rootScope.userEmail = user.email;
$window.location.href = ('#/app/meals');
$rootScope.hide();
}).catch(function (error) {
console.log("Login Failed!", error);
if (error.code == 'INVALID_EMAIL') {
$rootScope.notify('Invalid Email Address');
}
else if (error.code == 'INVALID_PASSWORD') {
$rootScope.notify('Invalid Password');
}
else if (error.code == 'INVALID_USER') {
$rootScope.notify('Invalid User');
}
else {
$rootScope.notify('Oops something went wrong. Please try again later');
}
$rootScope.hide();
//$rootScope.notify('Error', 'Email or Password is incorrect!');
});
};
$scope.loginWithGoogle = function () {
Auth.$authWithOAuthPopup('google')
.then(function (authData) {
$state.go($location.path('app/meals'));
});
};
$scope.loginWithFacebook = function () {
Auth.$authWithOAuthPopup('facebook')
.then(function (authData) {
console.log(authData);
$state.go($location.path('app/meals'));
})
.catch(function(error){
if (error.code === "TRANSPORT_UNAVAILABLE") {
Auth.$authWithOAuthRedirect("facebook").then(function (authData) {
// User successfully logged in. We can log to the console
// since we’re using a popup here
console.log(authData);
$state.go($location.path('app/meals'));
});
} else {
// Another error occurred
console.log(error);
}
});
};
}
])
Key functions like get session I want in $rootScope:
.run(function ($ionicPlatform, $rootScope, $firebaseAuth, $firebase, $window, $ionicLoading) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
$rootScope.userEmail = null;
$rootScope.baseUrl = 'https://[myappurl.firebaseio.com/';
var authRef = new Firebase($rootScope.baseUrl);
$rootScope.auth = $firebaseAuth(authRef);
$rootScope.authData = authRef.getAuth();
$rootScope.show = function(text) {
$rootScope.loading = $ionicLoading.show({
content: text ? text : 'Loading..',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
};
$rootScope.hide = function() {
$ionicLoading.hide();
};
$rootScope.notify = function(text) {
$rootScope.show(text);
$window.setTimeout(function() {
$rootScope.hide();
}, 1999);
};
$rootScope.logout = function() {
authRef.unauth();
$rootScope.authDataCallBack;
};
$rootScope.checkSession = function() {
if ($rootScope.authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider);
$rootScope.userEmail = user.email;
$window.location.href = ('#/app/meals');
} else {
console.log("No session so logout");
$rootScope.userEmail = null;
$window.location.href = '#/auth/signin';
}
}
$rootScope.authDataCallBack = function(authData) {
if ($rootScope.authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider);
} else {
console.log("User is logged out");
$window.location.href = '#/auth/signin';
}
};
});
})
The profile page:
<ion-view view-title="Profile">
<ion-content class="has-header">
<div class="list card">
<div class="item">
<h2>{{user.name}}</h2>
<p>{{user.city}}</p>
</div>
<!--https://github.com/israelidanny/ion-profile-picture-->
<!--<div class="item item-body">-->
<!--<img src="http://graph.facebook.com/{{user.id}}/picture?width=270&height=270"/>-->
<!--</div>-->
</div>
</ion-content>
</ion-view>
Auth factory:
app.factory('Auth', ['rootRef', '$firebaseAuth', function (rootRef, $firebaseAuth) {
return $firebaseAuth(rootRef);
}]);
If it helps, here is my SignUpCtrl which pushes items into the users array and also stores an array of uids of users already set up in the app.
.controller('SignUpCtrl', [
'$scope', '$rootScope', '$firebaseAuth', '$window', 'Auth',
function ($scope, $rootScope, $firebaseAuth, $window, Auth) {
$scope.user = {
firstname: this.firstname,
lastname: this.lastname,
email: "",
password: ""
};
$scope.createUser = function () {
var firstname = this.user.firstname;
var lastname = this.user.lastname;
var email = this.user.email;
var password = this.user.password;
if (!email || !password) {
$rootScope.notify("Please enter valid credentials");
return false;
}
$rootScope.show('Please wait.. Registering');
$rootScope.auth.$createUser(
{email: email, password: password})
.then(function (user) {
console.log('user is created');
$rootScope.hide();
$rootScope.userEmail = user.email;
var usersRef = new Firebase('https://foodsharingapp.firebaseio.com/users');
var keyRef = usersRef.push({
'uid': user.uid,
'email': email,
'firstname': firstname,
'lastname': lastname
});
var uidRef = new Firebase('https://[myapp].firebaseio.com/uids/' + user.uid + '/' + keyRef.key());
uidRef.set({'registered': true});
$window.location.href = ('#/app/meals');
}, function (error) {
console.log('error unfortunately');
$rootScope.hide();
if (error.code == 'INVALID_EMAIL') {
console.log('invalid email');
$rootScope.notify('Invalid Email Address');
}
else if (error.code == 'EMAIL_TAKEN') {
console.log('email taken');
$rootScope.notify('Email Address already taken');
}
else {
console.log('not sure what happened');
$rootScope.notify('Oops something went wrong. Please try again later');
}
});
}
Questions:
I want to call $rootScope.authDataCallBack(authData) on any controller to get the name and any details of the user_id logged in, however this is not working. Am I thinking about this right? How can I use my $rootScope functions as ways to obtain global information?
When I log in I see the Facebook object appearing fine, should I use the Facebook ID as a uid to store in my array?
On any view, how can I use the session uid or authData to then match against my list of users in the user array and pull out more detailed user info? Is there some pseudocode I can use and would this be in every function in my controller, or would it be split between factory and controller?

Related

Problem with facebook login from the facebook application

I also encounter a problem with a project, login with facebook works on absolutely any browser, even those on mobile, but in the integrated browser in the facebook application it doesn't work, it just doesn't connect me, it sends me back to login ... can you help me with a piece of advice please? Thank you.
I used this script:
<script>
(function(){
var body = $('body');
var socialLoginErrorElm = $('#loginError');
var loginModal = $('#loginModal');
body.on('social-login:error', function(e, error) {
socialLoginErrorElm.removeClass('hide').html('<div class="alert alert-danger">' + error + '</div>');
loginModal.removeClass("logging-in");
});
window.loginWithFb = function(){
FB.login(function(response) {
if (response.authResponse) {
if(response.authResponse.grantedScopes.split(',').indexOf('email') < 0) {
//If email permission not granted
body.trigger('social-login:error', (__('fbNoEmailError')));
return;
}
FB.api('/me', {fields: 'id,name,email'}, function(response) {
console.log('Logged in as ' + response.name + '.');
//Dual check email - needed to if check if the user has a verified email ID
if(!response.email) {
body.trigger('social-login:error', (__('fbNoEmailError')));
return;
}
body.trigger('loggedIn:fb');
});
} else {
body.trigger('social-login:error', (__('fbPermissionError')));
}
}, {
scope: 'email',
auth_type: 'rerequest',
'return_scopes': true
});
}
var body = $('body');
body.on('click', '[data-action="loginWithFB"]', function(e){
loginWithFb();
e.preventDefault();
});
body.on('loggedIn', function(){
loginModal.modal('hide');
});
body.on('loggedIn:fb', function(){
if(!User.isLoggedIn()) {
$.get(BASE_PATH + '/login/fb').success(function(response){
User.setData(response.user);
}).fail(function(jqXHR, textStatus, errorThrown){
body.trigger('social-login:error', jqXHR.responseText);
}).always(function(){
loginModal.removeClass("logging-in");
});
}
});
body.on('prompt-login', function(e, message){
loginModal.find('.login-prompt-message').html(message);
loginModal.modal('show');
});
})();
function showNewPointsAlert(addedPoints) {
var alertOptions = {
title: "+"+ addedPoints +" " + __('points'),
text: __('earnedNewPointsMessage'),
imageUrl: "{{LeaderboardHelpers::getPointsIcon()}}",
confirmButtonText: __('earnedNewPointsOkayBtnText'),
allowEscapeKey: true,
allowOutsideClick: true,
customClass: 'new-points-alert'
}
#if(!empty($mainBtnColor))
alertOptions.confirmButtonColor = '{{{$mainBtnColor}}}';
#endif
swal(alertOptions);
}
$('body').on('user-activity-recorded', function() {
$.get('{{route('getMyPoints')}}').success(function(response) {
if(response && response.points) {
var oldPoints = parseInt(User.data.points);
var newPoints = parseInt(response.points);
User.data.points = newPoints;
User.setData(User.data);
if(oldPoints != newPoints) {
var animateClass = 'animated bounceIn';
$('#headerUserMenu').removeClass(animateClass).addClass(animateClass);
var addedPoints = parseInt(newPoints) - parseInt(oldPoints);
#if(MyConfig::isTrue('leaderboard.showNewPointsAlert'))
showNewPointsAlert(addedPoints);
#endif
}
}
}).fail(function() {
});
});
</script>

Auth0 - get provider user id

at the moment I am relying on a junky method to get the provider user id (the string/number used in in user page urls of the social) based on splitting the profile "sub" field given from the /profile endpoint.
I saw that the old API had a field named "identities" where seems to be stored the provider user id, is there an equivalent for the new API?
Basically it should return:
facebook: the user number or url nickname http://www.facebook.com/mattiamanzati or http://www.facebook.com/100011120071734 if a nickname was'nt set
twitter: the twitter handle http://www.twitter.com/mattiamanzati
instagram: the instagram handle http://www.instagram.com/cenaacorte
This is the code I've been using now, and you can see how junky is the provider and provider_uid setting is.
var webAuth = new auth0.WebAuth({
domain: "himy.eu.auth0.com",
clientID: "0gz79WpxVxXNH5qeYRXXTxTQiWZZEV9S",
redirectUri: window.location.href,
audience: "https://himy.eu.auth0.com/userinfo",
responseType: "token id_token",
scope: "openid profile"
});
function handleAuthentication() {
webAuth.parseHash(function(err, authResult) {
if (authResult && authResult.accessToken && authResult.idToken) {
window.location.hash = "";
webAuth.client.userInfo(authResult.accessToken, function(err, profile) {
if (profile) {
if (window.postMessage) {
if (profile.sub.indexOf("facebook") === 0) {
profile.provider_uid = profile.sub.split("|")[1];
profile.provider = "facebook";
} else if (profile.sub.indexOf("instagram") === 0) {
profile.provider_uid = profile.nickname;
profile.provider = "instagram";
}
window.postMessage(JSON.stringify(profile));
}
console.log(profile);
}
});
} else if (err) {
console.log(err);
}
});
}
window.addEventListener("load", function(e) {
if (!window.location.hash) {
webAuth.authorize();
} else {
handleAuthentication();
}
});

What does this `checkSession` function do?

I have included the firebase and angularfire libraries to my ionic framework project.
I am following the below link for my sample project.
https://www.sitepoint.com/creating-firebase-powered-end-end-ionic-application/
I am not able to understand how the 'checkSession' function in the below 'app.js' works. Could someone please explain?
How can we call the 'auth' function which is inside 'checkSession' function?
app.js
angular.module('bucketList', ['ionic', 'firebase', 'bucketList.controllers'])
.run(function($ionicPlatform, $rootScope, $firebaseAuth, $firebase, $window, $ionicLoading) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
$rootScope.userEmail = null;
$rootScope.baseUrl = 'https://bucketlist-app.firebaseio.com/';
var authRef = new Firebase($rootScope.baseUrl);
$rootScope.auth = $firebaseAuth(authRef);
$rootScope.show = function(text) {
$rootScope.loading = $ionicLoading.show({
content: text ? text : 'Loading..',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
};
$rootScope.hide = function() {
$ionicLoading.hide();
};
$rootScope.notify = function(text) {
$rootScope.show(text);
$window.setTimeout(function() {
$rootScope.hide();
}, 1999);
};
$rootScope.logout = function() {
$rootScope.auth.$logout();
$rootScope.checkSession();
};
$rootScope.checkSession = function() {
var auth = new FirebaseSimpleLogin(authRef, function(error, user) {
if (error) {
// no action yet.. redirect to default route
$rootScope.userEmail = null;
$window.location.href = '#/auth/signin';
} else if (user) {
// user authenticated with Firebase
$rootScope.userEmail = user.email;
$window.location.href = ('#/bucket/list');
} else {
// user is logged out
$rootScope.userEmail = null;
$window.location.href = '#/auth/signin';
}
});
}
});
})

PhoneGap Facebook plugin, how to get firstname, lastname, image?

how to get firstname, lastname and image from facebook user after login ?
Here is the my code
function onDeviceReady()
{
var fbLoginSuccess = function (userData) {
document.getElementById('status').innerHTML = 'success';
}
facebookConnectPlugin.login(["public_profile"],
fbLoginSuccess,
function (error) { document.getElementById('status').innerHTML = 'error'; }
);
}
function loginFb() {
openFB.loginFb(
function(response) {
if(response.status === 'connected') {
openFB.api({
path: '/me',
success: function(data) {
console.log(JSON.stringify(data));
fbUserName = data.name;
fbUserId = data.id;
fbUserPic = document.getElementById("fbuserPic").src = 'http://graph.facebook.com/' + data.id + '/picture?type=small';
}
});
}
});
}
Hello, if you have any facing problem then tell me OK.

react-native-fbsdk - how to get user profile?

onLoginFinished's result just tells me the granted permissions. From the repo, not clear how to get the user profile. Seems like react-native-fbsdkcore should wrap FBSDKProfile.h but don't see where it does.
var FBSDKLogin = require('react-native-fbsdklogin');
var {
FBSDKLoginButton,
} = FBSDKLogin;
var Login = React.createClass({
render: function() {
return (
<View>
<FBSDKLoginButton
onLoginFinished={(error, result) => {
if (error) {
alert('Error logging in.');
} else {
if (result.isCanceled) {
alert('Login cancelled.');
} else {
alert('Logged in.');
}
}
}}
onLogoutFinished={() => alert('Logged out.')}
readPermissions={[]}
publishPermissions={['publish_actions']}/>
</View>
);
}
});
Found out you can get logged in user's profile with Graph API.
// Create a graph request asking for user's profile
var fetchProfileRequest = new FBSDKGraphRequest((error, result) => {
if (error) {
alert('Error making request.');
} else {
// Data from request is in result
}
}, '/me');
// Start the graph request.
fetchProfileRequest.start();
There is an easier way to do it. Rather than manually making the graph request yourself, 'react-native-fbsdkcore' package to get the data associated with the logged in user (if there is one)
var
FBSDKCore = require('react-native-fbsdkcore');
var {
FBSDKAccessToken,
} = FBSDKCore;
FBSDKAccessToken.getCurrentAccessToken((token) => {
// token will be null if no user is logged in,
// or will contain the data associated with the logged in user
});
cphackm address is that in this issue #2
Using #flow, here is a full example:
FbLogin.js
// #flow
import * as React from 'react';
import { View } from 'react-native';
import { LoginButton, AccessToken } from 'react-native-fbsdk';
import { FbService } from '#services';
import { toast } from '#libs/helpers';
type LoginResult = {
isCancelled: boolean,
grantedPermissions?: Array<string>,
declinedPermissions?: Array<string>
};
type Props = {
store: {
Account: Object
}
};
type State = {
token?: string
};
export default class Login extends React.Component<Props, State> {
componentDidMount() {
AccessToken.getCurrentAccessToken().then(tokenData => {
if (tokenData) {
console.log('[-- tokenData --]', tokenData);
const { accessToken, userID } = tokenData;
if (accessToken) {
console.log('[-- accessToken, userID --]', accessToken, userID);
this.setState({ token: accessToken });
// this._getUserInformation();
}
}
});
}
_getUserInformation = () => {
const { token } = this.state;
const { Account } = this.props.store;
if (token) {
FbService.getFbUserData(token, (error, result) => {
if (error) {
console.log('[-- error --]', error);
} else {
Account.provider = 'facebook';
Account.authorized = true;
Account.current = { password: '', token, ...result };
console.log('[-- responseFbUserData --]', result);
}
});
}
};
render() {
return (
<View>
<LoginButton
readPermissions={['public_profile']}
onLoginFinished={(error: Object, result: LoginResult) => {
if (error) {
alert('Login failed with error: ' + error.toString());
} else if (result.isCancelled) {
alert('Login was cancelled');
} else {
if (result) {
this._getUserInformation();
}
}
}}
onLogoutFinished={() => toast('User logged out', 'info')}
/>
</View>
);
}
}
/* AccessToken
accessToken: string,
applicationID: string,
userID: string,
permissions: Array<string>,
declinedPermissions: Array<string>,
accessTokenSource?: string,
expirationTime: number,
lastRefreshTime: number,
*/
FbService.js
// #flow
import * as React from 'react';
import { GraphRequestManager, GraphRequest, AccessToken } from 'react-native-fbsdk';
export function getFbUserData(token: string, callBack: Function) {
const profileRequestConfig = {
httpMethod: 'GET',
version: 'v2.12',
parameters: {
fields: {
string: 'id, name, email'
}
},
accessToken: token
};
const profileRequest = new GraphRequest('/me', profileRequestConfig, callBack);
new GraphRequestManager().addRequest(profileRequest).start();
}