My firebase facebook popup login on ionic was working correctly but suddenly it stop working (well, i was modifiying the app but i didnt touch the service). The process still works on browser (when i use ionic serve) but not running on ionic app.
var auth = $fAuth(ref);
// login with Facebook
auth.$onAuth(function(authData){ // authData -> null
console.log("Auth..", authData); // Auth.. null
/* refresh user data on firebase and registering push */
});
auth.$authWithOAuthPopup("facebook").catch(function(error) {
console.log("Authentication failed:", error);
});
When it was working, $onAuth cb function was recieving an object in authData variable with properties like uid and facebook.
when i run:
ref.authWithOAuthPopup("facebook",function(){console.log(arguments)})
or:
ref.authWithOAuthPopup("twitter",function(){console.log(arguments)})
the callback function never fires.
I run the auth process on $ionicPlatform.ready event.
I already uninstalled and reinstalled the app, and cleaned app data.
thanks!
Are you sure it doesn't fire?
A callback function that will be called when authentication has completed. On failure, the first argument will be an Error object indicating the failure, with a machine-readable code attribute. On success, the first argument will be null and the second will be an object containing the fields uid (the unique user id), provider (string identifying the provider), auth (the auth. token payload), and expires (expiration time in seconds since the Unix epoch) - and more, depending upon the provider used to authenticate.
You didn't put the arguments there.
I think it should work if you try it again.
Example code from firebase:
ref.authWithOAuthPopup("facebook", function(error, authData) {
// ^^^^^ ^^^^^^^^
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
});
Related
I'm trying to generate a new messaging token but it seems to generate the same one, over and over again.
I tried both
FirebaseMessaging.getInstance().deleteToken().addOnCompleteListener {
Log.d("Notifications", "Token Deleted!!!")
}
and
FirebaseInstallations.getInstance().delete().addOnCompleteListener {
Log.d("Notifications", "Token Deleted!!!")
}
Neither seem to trigger the
override fun onNewToken(refreshedToken: String) {}
of the service. And each time i query for the current token i get the same one.
What am i doing wrong?
I am not exactly sure if you can delete the generated token to get a new one. However, as per documentation a token is generated once on app's initial startup.
If you want a new token - simply uninstall the app and install it once again. Then Firebase will generate a new token.
I was having the same issue when trying to log out users.
I would recommend using the depreciated method below:
Thread(Runnable {
Thread.sleep(1000)
FirebaseInstanceId.getInstance().deleteInstanceId()
}).start()
This will not call onNewToken, however, if you now call..
FirebaseMessaging.getInstance().token.addOnCompleteListener { -> task
// get the result here
}
Result should be a new token
I have an issue with react-native-firebase (or firebase) in which my app does not receive a trigger after the auth token refreshes. It's pretty much the same issue as [1], but they never posted a solution.
So, what happens is that both on an Android phone and on the Android emulator (no idea about iOS), signing up, logging in and logging out works perfectly, meaning the listeners correctly see when I do a logout() etc. But the listeners never fire when the token refreshes.
My first question is: Am I correct to assume that the onIdTokenChanged-listener should automatically fire after 60 minutes without having to do anything else, e.g. call any firebase function, such that the app just sits there doing nothing for 60 minutes and then receiving the event and replacing the token?
My main component which contains the listeners looks like this:
class ReduxAppWrapper extends Component {
componentDidMount() {
firebase.auth().onAuthStateChanged((user) => {
console.log('COMP DID MOUNT: AUTH STATE CHANGED! ' + JSON.stringify(user));
});
firebase.auth().onIdTokenChanged((user) => {
console.log('COMP DID MOUNT: TOKEN CHANGED! ' + JSON.stringify(user));
});
firebase.auth().onUserChanged((user) => {
console.log('COMP DID MOUNT: USER CHANGED! ' + JSON.stringify(user));
});
};
render() {
return (
<ReduxProvider store={store}>
<MenuProvider>
<PaperProvider>
<AppContainer />
</PaperProvider>
</MenuProvider>
</ReduxProvider>);
}
}
Normally inside the listener I have a function that dispatches a redux-action such that the authentication information is broadcast across my components. Inside those components I use the jwt token for http-requests to my backend.
Now the backend of course uses firebase to validate that token (and this is where the problem occurs after the 60 minutes since it retrieves an outdated jwt), but I think I am right to assume that the problem lies within the app since the refresh does not happen.
I'd be really glad if someone could point me to where to look, I also tried to find out in the firebase console whether a token refresh event was sent, but I could not find anything about that.
So basically:
1) Am I right to assume that the firebase.auth().onIdTokenChanged() function should be called without me doing anything else? Or is it not enough to define the listener once in the main component (also regarding the fact that other screens will be rendered on top of that due to the stack-nvigation).
2) If the code is fine, do you have any hints for where to look?
Thanks so much!
[1] https://github.com/invertase/react-native-firebase/issues/531
For anyone with the same issue, I ended up asking firebase asking for the token everytime I needed it. I still think this should not be necessary but I did not want to spend any more time analyzing why the refresh did not work automatically. So what I am doing in the app is
firebase.auth().currentUser.getIdToken().then((token) => {
fetch(url, {
method: 'GET',
headers: { Authorization: token }
})
}
¯\_(ツ)_/¯
Apparently, with getIdToken, Firebase only makes a call to its server to get a new token if the current token has expired; it does not create unnecessary requests if it does not have to.
Quite a crucial detail which can be confusing if you are not aware of it and makes you (rightfully) assume that onIdTokenChanged is a listener which you would need to use to automatically update the token ...
https://firebase.google.com/docs/reference/js/firebase.User.html#getidtoken
Returns the current token if it has not expired. Otherwise, this will refresh the token and return a new one.
I see how execute a Cloud Function on user account creation:
exports.myFunction = functions.auth.user().onCreate(event => {
But I need my function to execute when the user logs in. Is there a onLogin trigger?
And can someone with 1500 points create a tag for firebase-cloud-functions?
There's no event for login, because only the client side can define exactly when a login happens. Different clients may define this in different ways. If you need to trigger something on login, figure out when that point is in your app, then trigger it from the client via a database or HTTP function.
This worked in the controller:
firebase.auth().onAuthStateChanged(function(user) { // this runs on login
if (user) { // user is signed in
console.log("User signed in!");
$scope.authData = user;
firebase.database().ref('userLoginEvent').update({'user': user.uid}); // update Firebase database to trigger Cloud Function
} // end if user is signed in
else { // User is signed out
console.log("User signed out.");
}
}); // end onAuthStateChanged
And this is the trigger in the Cloud Function:
exports.getWatsonToken = functions.database.ref('userLoginEvent').onUpdate(event => { // authentication trigger when user logs in
I made a location in Firebase Database called userLoginEvent.
One confusing bit is that in the functions console it's /userLoginEvent but in your code you must leave out the slash.
You can create your own analytics event, like login and used it as the trigger for your cloud function.
Then in your app, when the user successfully authenticate you use firebase analytics to send an event with the name you defined, like login
exports.sendCouponOnPurchase = functions.analytics.event('login').onLog((event) => {
const user = event.user;
const uid = user.userId; // The user ID set via the setUserId API.
});
You can trigger an https onCall firebase cloud function on login
ex: This is your login button trigger function which calls an https onCall function after authenticating the user.
_login() {
firebase
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then(function (user) {
var addMessage = firebase.functions().httpsCallable('myCloudFunctionName');
addMessage("whatever variable I want to pass")
.catch(error => {
console.log("I triggered because of an error in addMessage firebase function " + error)
)}
}).catch(error => {
console.log(error);
});
}
There is also another way you can do this inside Google Cloud if you enable Identity Platform for a project. Then you can follow this guide:
https://cloud.google.com/functions/docs/calling/logging
And trigger cloud functions for any of these Firebase Authentication events:
https://cloud.google.com/identity-platform/docs/activity-logging?authuser=1&_ga=2.226566175.-360767162.1535709791#logged_operations
The only problem I've just noticed is that the logs generated for Sign In event do not include the firebase app id or anything to determine which client the user logged in on which is really annoying as this was the main reason we needed to do this!
Im using ngOpenFB on Ionic, and Ive got my callback set to localhost:8100/oauthcallback.html
$scope.submit= function () {
ngFB.login({scope: 'email'}).then(
function (response) {
if (response.status === 'connected') {
alert('Facebook login succeeded');
} else {
alert('Facebook login failed');
}
});
}
When I hit submit, the oauthcallback.html window gets opened, and in the url I see the valid access token. However, neither of the alerts fire. Theres is no success, and no failure. Just a blank oauthcallback.html page, with the access token in the URL.
I know I can use some trickery to just get that token from the URL and close the window myself. But surely this should be automatic in the ngOpenFB library?
Like it should do it for me no?? Store in sessionStorage, and close the window.
Otherwise, if I don't solve this, Im just going to do it the hacky way, and get the token, and save it myself.
But any ideas on why its not working as it should?
I am using https://github.com/Wizcorp/phonegap-facebook-plugin to connect my cordova Android app to Facebook.
I can login with:
facebookConnectPlugin.login(["email"],
fbLoginSuccess,
function (error) { alert("ERROR:" + JSON.stringify(error)); }
);
, logout even call facebookConnectPlugin.getLoginStatus and get:
userID
accessToken
expiresIn
sig
status
but when FB.api('/me', function(response){...}) is called, I receive
{error:
{
message: An active access token must be used to query information about the current user,
type: OAuthException,
code: 2500
}
}
Also this only happens when the app is built, not tested in browser.
Solved issue by manually giving FB.apicall a token with:
FB.api('/me?access_token='+userdata.authResponse.accessToken, function(response) {...
where userdata is the response of facebookConnectPlugin.getLoginStatus
I just don't understand why doesn't it provide token automatically in android app like it does in browser.
Send the access token and the data retrieving fields with the apiString
const fields = ['email', 'first_name', 'last_name', 'gender', 'birthday', 'picture.type(large)'];
const apiString = `me?access_token=${accessToken}&fields=${fields.join(',')}`;