Ionic AngularFire Firebase Facebook Login - firebase

I meat a problem with Ionic. I will explain that.
I use Ionic 2 and AngularFire 2 to use Firebase. So I can have access to my database and login with Facebook. I use a button to call this function:
this.af.auth.login({
provider: AuthProviders.Facebook,
method: AuthMethods.Popup
}).then(function(response){
console.log('facebook login ', response);
});
Everything works great on the ionic lab. However, when I test my app in my device, the button does nothing, neither the Popup nor the Redirect work. So can you help me with that ?

You need to fix some things, I used Cordova for facebook login:
You didn't share your log error, but I think you will need to do this:
In you Facebook app:
Add a new Platform, Android or IOS (You didn't say what you are using).
Add a cordova plugin:
ionic plugin add cordova-plugin-facebook4 --save --variable APP_ID="999999999" --variable APP_NAME="myApplication"
Use your facebook app id and name.
Install ionic-native in your app:
npm install ionic-native --save
Add a Facebook import in your code:
import { Facebook } from 'ionic-native';
and change your method for using a Cordova login:
loginWithFacebook() {
return Observable.create(observer => {
if (this.platform.is('cordova')) {
Facebook.login(['public_profile', 'email']).then(facebookData => {
let provider = firebase.auth.FacebookAuthProvider.credential(facebookData.authResponse.accessToken);
console.log('facebook accessToken: '+facebookData.authResponse.accessToken);
firebase.auth().signInWithCredential(provider).then(firebaseData => {
console.log('facebook login ', firebaseData);
observer.next();
}).catch(function(error) {
// Handle Errors here.
console.log("error");
console.log(error);
// ...
});
}, error => {
observer.error(error);
});
} else {
this.af.auth.login({
provider: AuthProviders.Facebook,
method: AuthMethods.Popup
}).then((response) => {
console.log('facebook login ', response);
observer.next();
}).catch((error) => {
console.info("login", error);
observer.error(error);
});
}
});
}
Note: If your app is in development only developers can login.

The code above can be made simpler for use inside an AuthProvider like the axample given here just by doing this:
signInWithFacebook(): firebase.Promise<any> {
if (this.platform.is('cordova')) {
return Facebook.login(['public_profile', 'email']).then(facebookData => {
let provider = firebase.auth.FacebookAuthProvider.credential(facebookData.authResponse.accessToken);
console.log('facebook accessToken: ' + facebookData.authResponse.accessToken);
return firebase.auth().signInWithCredential(provider);
});
} else {
return this.auth$.login({
provider: AuthProviders.Facebook,
method: AuthMethods.Popup
});
}
}

Related

How do I fix firebase auth/netwok-request-failed when opened by social media browsers?

I recently had a bug to solve for a customer on my webapp. It is givng a
Firebase: Error(auth/network-request-failed)
However I also realize upon selecting 'Ok' on the alert, the browser redirects the user to login with their account, however has a my FIREBASE_AUTH_DOMAIN - {projectID}.firbaseapp.com .
This only occurs when user visit the login/signUp link via social media browser.
So I changed the signInWithPopUp -> signInWithRedirect.
And now I still get the error if I am redirected to the login/signUp page. How I do fix this?
const loginGoogle = async () => {
closeSnackbar();
const provider = new GoogleAuthProvider();
signInWithRedirect(auth, provider)
.then(() => {
createUserDoc(); //creates a userProfile document
enqueueSnackbar(
`Welcome ${
!auth.currentUser.displayName ? "" : auth.currentUser.displayName
}`,
{ variant: "success" }
);
})
.catch((error) => {
alert(error.message);
});
router.push(redirect || "/shop");
};

This operation is not supported in the environment this application is runnung on [duplicate]

I develop a react-native (expo) mobile app and try to sign in with a google account to firebase, but I get an error:
"auth/operation-not-supported-in-this-enviroment. This operation is not supported in the enviroment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled"
Code:
loginGoogle() {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('profile');
provider.addScope('email');
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
return true;
}).catch(function(error) {
alert(error.code + '\n' +
error.message + '\n' +
error.email + '\n' +
error.credential);
return false;
});
}
signInWithPopup is not supported in react-native. You will need to use a third party OAuth library to get the OAuth ID token or access token and then sign in with Firebase:
const cred = firebase.auth.GoogleAuthProvider.credential(googleIdToken, googleAccessToken);
firebase.auth().signInWithCredential(cred)
.then((result) => {
// User signed in.
})
.catch((error) => {
// Error occurred.
});
Firebase does not support signInWithPopup in a React Native environment.
You can view a full list of supported environments on this page.
You can also submit a feature request for extended Firebase support for React Native here.
If you are using expo bare workflow or simple React native cli (or in simple words which contain android and ios folder) then simply use "React Native Firebase" library.
Here is the link https://rnfirebase.io/
But if you are using expo managed workflow(which donot contain android and ios folder ) then you have to follow below steps .
1.setup google developer account
use this guide to setup : https://docs.expo.dev/versions/latest/sdk/google/
Note that: use host.exp.exponent as the package name.
Another problem you may face in this step is generation of hash,which I also faced,the reason for that error is java dev kit(JDK) is not install ,so do install it before proceeding to this step.
2.Setup Firebase account
Simply setup firebase project as you set before, enable google sign in service
but this time the only change is you have to add client ID of your google developer account in (safest client id field) which will popup once you click on edit Google signin in firebase
look like this
3.Coding Part
import * as Google from 'expo-google-app-auth'; //imported from expo package
import {
GoogleAuthProvider,getAuth
} from 'firebase/auth';
import { initializeApp } from "firebase/app";
import { firebaseconfig } from '[your firebase credentials]';
const app=intitializeApp(firebaseconfig)
const auth=getAuth(app);
async function signInWithGoogleAsync() {
try {
const result = await Google.logInAsync({
androidClientId: 'cliend id from google dev console',
iosClientId: 'client id from google dev console for ios app(if you setup)',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
console.log(result)
const credential = GoogleAuthProvider.credential(result.idToken, result.accessToken);
// Sign in with credential from the Facebook user.
signInWithCredential(auth, credential)
.then(async result => {
console.log(result)
})
.catch(error => { console.log(error) });
return result.accessToken;
} else {
console.log("cancelled by user")
return { cancelled: true };
}
} catch (e) {
console.log(e);
return { error: true };
}//
}

How to implement Firebase phone authentication with Ionic 4?

Is it possible to use phone authentication with Firebase and Ionic 4 in mobile apps?
I have seen some old tutorials implementing phone authorization with Ionic 3, but these seem to be outdated.
The firebaseui-web project does not support phone authentication for cordova apps, but I am unsure if that implies that Firebase phone authentication is impossible with ionic apps.
If you cannot use Firebase's phone authentication with Ionic 4, is there an alternative phone authentication service that does work with Ionic 4?
Yes. You can do it with Firebase's Javascript SDK, it will need the user to pass a CAPTCHA and then send the phone number a verification code which you can login and auth with, the process is explained here:
https://firebase.google.com/docs/auth/web/phone-auth#send-a-verification-code-to-the-users-phone
The problem is that the firebase auth sms service will only send messages when the app is in production mode (uploaded to the store). But to be able to test the methods from test mode, it is adding a test number in the white list of firebase.
In my case, I try these:
sms-verification.page.ts
sendSmsVerification(phoneNumber): Promise <firebase.auth.UserCredential> {
return new Promise((resolve, reject) => {
firebase.auth().useDeviceLanguage();
var verificationId;
var code;
const timeOutDuration = 60;
const tell = '+54' + phoneNumber;
this.FireBase.verifyPhoneNumber(tell, timeOutDuration).then(async (credential) => {
// alert(credential.instantVerification);
if (credential.verificationId) {
console.log("Android credential: ", credential);
verificationId = credential.verificationId;
} else {
console.log("iOS credential: ", credential);
verificationId = credential;
}
if (credential.instantVerification) {
code = credential.code;
this.verifySms(verificationId, code)
.then( resp => {
resolve(resp);
})
.catch( err => {
reject(err);
});
} else {
let prompt = await this.alertCtrl.create({
backdropDismiss: false,
header: 'Ingrese el codigo de confirmación del SMS.',
inputs: [{ name: 'confirmationCode', placeholder: 'Código de confirmación' }],
buttons: [
{ text: 'Cancelar',
handler: data => {
console.log('Cancel clicked');
resolve(data);
}
},
{ text: 'Verificar',
handler: data => {
code = data.confirmationCode;
this.verifySms(verificationId,code)
.then( resp => {
resolve(resp);
})
.catch( err => {
reject(err);
}); }
}
]
});
prompt.present();
}
}).catch(error => {
console.log('Error! Catch SMSVerificacion', error);
reject(error);
});
})
}
verifySms(verificationId, code): Promise <any> {
console.log('parametros de verifySms ', verificationId +' ', code);
const signInCredential = firebase.auth.PhoneAuthProvider.credential(verificationId,code);
return firebase.auth().signInAndRetrieveDataWithCredential(signInCredential);
}
Yes, it's possible to use firebase phone authentication using Cordova plugin,
cordova-plugin-firebase-authentication
Add this plugin to your ionic 4 project
cordova plugin add cordova-plugin-firebase-authentication --save
With this we can verify phone without using reCaptcha.
Note that this only work on real android device, not emulator or browser.
Function implementation
verifyPhoneNumber(phoneNumber, timeout)
cordova.plugins.firebase.auth.verifyPhoneNumber("+123456789", 30000)
.then(function(verificationId) {
// pass verificationId to signInWithVerificationId
});
or
AngularFire (With reCaptcha)
https://github.com/angular/angularfire
First, install angularfire lib into your project
npm install firebase #angular/fire --save
then import this lib into your class
import * as firebase from 'firebase/app';
code example:
firebase.auth().signInWithPhoneNumber(phoneNumber,recaptchaVerifier)
.then(confirmationResult => {
this.windowRef.confirmationResult = confirmationResult;
})

Any way to use Firebase google authentication in expo (create-react-native-app) without "eject" project

As the question, for Login with google in firebase need to set google-service but if you create new react-native project with create-react-native-app there will have no "android" or "ios" folder (accept used "eject") so, anyone have a suggestion for me?
However I've no idea for how to setting google-service in my project too (even I "eject" the project).
#brentvatne 's answer is a bit out of date. Here's how I got it working on Expo v27
Important bit: you can get your client ids with these instructions.
Just select your firebase app from the project dropdown on the google page.
const _loginWithGoogle = async function() {
try {
const result = await Expo.Google.logInAsync({
androidClientId:"YOUR_ANDROID_CLIENT_ID",
iosClientId:"YOUR_iOS_CLIENT_ID",
scopes: ["profile", "email"]
});
if (result.type === "success") {
const { idToken, accessToken } = result;
const credential = firebase.auth.GoogleAuthProvider.credential(idToken, accessToken);
firebase
.auth()
.signInAndRetrieveDataWithCredential(credential)
.then(res => {
// user res, create your user, do whatever you want
})
.catch(error => {
console.log("firebase cred err:", error);
});
} else {
return { cancelled: true };
}
} catch (err) {
console.log("err:", err);
}
};
It isn't necessary to make any changes to the android or ios folders in order to support Google sign in with firebase on an app built with Expo.
Follow the guide for configuring Google auth on the Expo docs
Use the approach described in Expo's Using Firebase guide, where it describes how to authenticate with Facebook, and swap out Google where needed.

How to add additional information to firebase.auth()

How can I add extra attributes phone number and address to this data set? It seems like Firebase documentation doesn't specify anything about that.
I have implemented the login, register and update using firebase.auth()
Login :
//Email Login
firebase.auth().signInWithEmailAndPassword(email, password).then(
ok => {
console.log("Logged in User",ok.user);
},
error => {
console.log("email/pass sign in error", error);
}
);
Register:
//Sign Up
firebase.auth().createUserWithEmailAndPassword(email, password).then(
ok => {
console.log("Register OK", ok);
},
error => {
console.log("Register error", error);
}
)
Update:
//User Authentication
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
$scope.data=user;
} else {
// No user, Redirect to login page
}
});
//Save Function
$scope.save=function(values){
$scope.data.updateProfile({
displayName: "Test User",
email: "test#gmail.com",
/* phone: 123412341,
address: "Temp Address",*/
photoURL: "www.example.com/profile/img.jpg"
}).then(function() {
// Update successful.
}, function(error) {
// An error happened.
});
};
As far as I know, you have to manage the users profiles by yourself if you want to have more fields than the default user provided by Firebase.
You can do this creating a reference in Firebase to keep all the users profiles.
users: {
"userID1": {
"name":"user 1",
"gender": "male"
},
"userID2": {
"name":"user 2",
"gender": "female"
}
}
You can use onAuthStateChanged to detect when the user is logged in, and if it is you can use once() to retrieve user's data
firebaseRef.child('users').child(user.uid).once('value', callback)
Hope it helps
This can be done by directly storing your custom data in Firebase Auth as "custom claims" on each user via the Admin SDK on your backend.
Note this can't be done purely client-side, your server (or you can use a Cloud Function as per the linked guide if you don't already have a server/API set up) needs to make a request through the Admin SDK to securely set the data using the admin.auth().setCustomUserClaims() method:
https://firebase.google.com/docs/auth/admin/custom-claims#defining_roles_via_an_http_request
You could write some code that combines data from firebase auth and firestore document and expose that to the app as a single data entity. To take subscriptions and notify that changes to the whole app, you would be better served with event libraries like Rxjs. Bellow, I wrote the example below using a simple library that implements an event bus.
// auth.js
import { publish } from '#joaomelo/bus'
import { fireauth, firestore } from './init-firebase.js'
const authState = {
userData: null
};
fireauth.onAuthStateChanged(user => {
if (!user) {
authState.userData = null;
publish('AUTH_STATE_CHANGED', { ...authState });
return;
}
// we must be carefull
// maybe this doc does not exists yet
const docRef = firestore
.collection('profiles')
.doc(user.uid);
docRef
// 'set' secures doc creation without
// affecting any preexisting data
.set({}, { merge: true })
.then(() => {
docRef.onSnapshot(doc => {
// the first data load
// and subsequent updates
// will trigger this
authState.userData = {
id: user.uid,
email: user.email,
...doc.data()
};
publish('AUTH_STATE_CHANGED', { ...authState });
});
});
});
// some-place-else.js
import { subscribe } from '#joaomelo/bus'
subscribe('AUTH_STATE_CHANGED',
authState => console.log(authState));
You can expand on that in a post I wrote detailing this solution and also talking about how to update those properties. There is too a small library that encapsulates the answer with some other minor features with code you could check.

Resources