I am implementing Facebook Sign In with Firebase in my Flutter App, and when a user signs in with Facebook Sign In for the first time I am changing the "emailverified" property to true. I do this through functions with the following code:
if (facebookUser.user?.emailVerified == false) {
try {
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('verifyFacebook');
await callable.call();
} on FirebaseFunctionsException catch (e) {
print(e.code);
print(e.plugin);
print(e.message);
}
}
where verifyFacebook is:
exports.verifyFacebook = functions.auth.user().onCreate(async (snap) => {
return await admin.auth().updateUser(snap.uid, {
emailVerified: true
});
})
What I do not understand is that a Firebase Function Exception of "unauthenticated" is printed in the console, but when I sign in for the second time the "emailverified" property is changed to true (meaning that the Firebase Function was executed properly)! How could this happen if in the try-catch part I was thrown an error?
I searched for other answers such as adding a permission in Google Cloud Console but none helped me :(
Thanks in advance!
In Google Cloud Console I added "allUsers" in the Permission property, and I expected my app to work fine without the "unauthenticated" error. However, the issue persisted.
The verifyFacebook function triggers every time a user is created with Firebase Authentication and is not a callable function. You don't have to call the function yourself. When you try to call it, the callable function does not exists and hence you get an error but the function triggered by Firebase Auth does run.
Related
I am trying to implement deleteUser function in cognito which allows the user to delete their own account information by using this code
void deleteUser() async {
try {
await Amplify.Auth.deleteUser();
final state = AuthState(authFlowStatus: AuthFlowStatus.none);
authStateController.add(state);
print('Delete user succeeded');
} on AmplifyException catch (e) {
print('Delete user failed with error: $e');
}
}
However, this code of course is not working for some reason and I don't know why. I also have the user's database in Amplify datastore graphql so I tried deleting the user's datastore data first before getting rid of the user's congnito data but it still does not work. This is the code that I am using to delete user's data from datastore. Please help me out by telling me how I can delete a user's cognito and datastore data.
void deleteUser (DeleteUserData data) async {
(await Amplify.DataStore.query(User.classType, where: User.EMAIL.eq(data.email)))
.forEach((element) async {
try {
await Amplify.DataStore.delete(element);
print('Deleted a user');
} on DataStoreException catch (e) {
print('Delete failed: $e');
}
});
}
Please help me out.
I was facing the same problem, I took a look into the insides of deleteUser method in the AWS api, something I strongly recommend, and I discovered that this API is only available in iOS.
screenshot
I was using amplify_auth_cognito: 0.4.5 and amplify_flutter: 0.4.5.
Upgraded the libraries to 0.5.1 and the warning has disappeared, maybe you can try using a different version of yours (I'm not using Amplify, just simple Cognito).
Cheers.
So I have a weird bug that I can't seem to track down. I'm using firebase functions on the backend and SwiftUI. My login flow goes like this:
User logs in from loginView. The loginView then uses a callback to pass a user to move on to the next View after a user logs in.
After this a user is passed to the View where it calls the firebase functions.
The problem is that every once in a while a user fails authentication. This doesn't happen every time and usually happens when a user has not logged in for 12 hours or more. I thought it may have been a race condition at first but after further investigation decided that it wasn't given the fact that it's using a callback.
Has anyone else experienced anything similar? If so is there any way to fix this?
I have tried making my firebase function stay warm by setting minimum instances to 1 because I initially thought it may be a cold start issue but this hasn't helped.
Any help would be greatly appreciated. Thanks.
On the frontend the code is pulling like so:
FirebaseAuthService().signIn(email: email, password: password) { result, error in
if (error?.occurred) != nil {
self.errorMessage = error!.details
self.state = .failed
self.showErrorAlert = true
return
}
if (localAuthEnabled) {
...... This piece of code works
FirebaseFirestoreService().fetchUser(userID: result?.user.uid ?? "", completion: { user, error
....... This piece of code works.
}
})
}
User is then taken to another view AFTER logging in
This view pulls from 5 or so firebase functions asynchronously (but the user is already logged in by this point). The function that it fails at is as follows
self.function.httpsCallable("api-report").call() { (result, error) in
... It is at times it gives me an auth error inside of this function.
}
I am using this to log out whenever a user put the app in the background or hits the log out button:
func signOut() -> Bool {
do {
try Auth.auth().signOut()
self.session = nil
return true
} catch let err as NSError {
print("Error signing out: %#", err)
return false
}
}
on the backend the report call does the following with the report. This is a large function. I have only added the call to show whats going on.
exports.handler = async (data, context) => {
if (!context.auth) {
console.log("report error context");
console.log(context);
throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
'by authenticated users.', 'User must be authenticated');
}
}
It seems the call to your backend may be happening just as/after the user is logged out, or their token is being refreshed. If it's the token being refreshed, the client should just retry the call in cases such as this.
You could also check whether the token is about to expire, and force a refresh when that is the case, or delay calling the Cloud Function until the token has refreshed.
I have a firebase cloud function to create a user document with user data whenever a user registers. How would I return an error when the set() fails? Since this is not an http request (an I don't want to use an http request in this case) I have no response. So how would I catch errors?
export const onUserCreated = functions.region('europe-west1').auth.user().onCreate(async user => {
const privateUserData = {
phoneNumber: user.phoneNumber
}
const publicUserData = {
name: 'Nameless'
}
try
{
await firestore.doc('users').collection('private').doc('data').set(privateUserData);
}catch(error)
{
//What do I put here?
}
try
{
await firestore.doc('users').collection('public').doc('data').set(publicUserData);
}catch(error)
{
//What do I put here?
}
});
You can't "return" an error, since the client doesn't even "know" about this function running, there is nobody to respond to.
You can make a registration collection, and in your function make a document there for the current user (using the uid as the document id). In that document, you can put any information you'd like your user to know (status, errors, etc).
So your clients would have to add a listener to this document to learn about their registration.
In your particular code, I think the error is in doc('users'). I guess you meant doc('users/'+user.uid).
Your catch -block will receive errors that occur on your set -call:
try {
await firestore.doc('users').collection('public').doc('data').set(publicUserData);
} catch (error) {
// here you have the error info.
}
I have the following code that I am using to log a user in silently
try {
result = await GoogleSignIn().signInSilently().catchError((x) {
print(x);
});
} catch (e) {
print(e);
}
If the user cannot sign in silently, it results in an error.
PlatformException (PlatformException(sign_in_required, com.google.android.gms.common.api.ApiException: 4: 4: , null))
The problem I am having is that I cannot seem to catch the exception. catchError nor the catch block are being hit. How do I catch this error?
Do the following in your method
try {
result = await GoogleSignIn().signInSilently(suppressErrors: false).catchError((x) {
print(x);
});
} catch (e) {
print(e);
}
By default suppressErrors = true suppressing the error messages you want to catch.
Looking at the source code
The SignInSilently method is used to suppress error messages thus not throwing the exception you want to catch.
From the docs of this method:
/// When [suppressErrors] is set to `false` and an error occurred during sign in
/// returned Future completes with [PlatformException] whose `code` can be
/// either [kSignInRequiredError] (when there is no authenticated user) or
/// [kSignInFailedError] (when an unknown error occurred).
Full Method
/// Attempts to sign in a previously authenticated user without interaction.
///
/// Returned Future resolves to an instance of [GoogleSignInAccount] for a
/// successful sign in or `null` if there is no previously authenticated user.
/// Use [signIn] method to trigger interactive sign in process.
///
/// Authentication process is triggered only if there is no currently signed in
/// user (that is when `currentUser == null`), otherwise this method returns
/// a Future which resolves to the same user instance.
///
/// Re-authentication can be triggered only after [signOut] or [disconnect].
///
/// When [suppressErrors] is set to `false` and an error occurred during sign in
/// returned Future completes with [PlatformException] whose `code` can be
/// either [kSignInRequiredError] (when there is no authenticated user) or
/// [kSignInFailedError] (when an unknown error occurred).
Future<GoogleSignInAccount> signInSilently({bool suppressErrors = true}) {
final Future<GoogleSignInAccount> result = _addMethodCall('signInSilently');
if (suppressErrors) {
return result.catchError((dynamic _) => null);
}
return result;
}
Reference
Google Sign In Plugin Repo
Method Source Code Starting Line 283
This might help.
Checklists :
Did not register a sha fingerprint.
Make sure to have my "support email" set.
Enable the Google Sign-in method.
The catchError block is actually getting hit if you use suppressErrors = false
Try the following code and see what it prints on your console.
result = await GoogleSignIn().signInSilently(suppressErrors: false).
catchError((x) {
print("inside catchError");
});
The problem is the print(e); line in the catch statement. 'e' is not a string so an error occurs. I don't know why but no breakpoints are hit in the catch statement for this error and no error is output to the console. If I put a catch statement around a function that calls the login code ie.
void tryLogin(){
try{
myLoginLogic();
} catch(e) {
print(e);
}
}
Then I do get an error message
Unhandled Exception: type '_TypeError' is not a subtype of type 'String'
So to be clear the correct code would be
try {
result = await GoogleSignIn().signInSilently().catchError((e) {
print(e.toString());
});
} catch (e) {
print(e.toString());
}
Why code doesn't break on error and no message is written to the console for the original function I don't know. Also what I don't understand is why, even when the catch statement is written without errors, in debug mode the code breaks on the signInSilently() line.
I have a website—utilizing Visualize.js—that has a simple login/logout feature. Everytime I login I call the authenicateUser() function and logout destroySession(). When I try login and then logout and then login again, when I try to render my existing reports I get this thrown error:
HTTP Status 401 - Full authentication is required to access this resource
The functions authenicateUser() and destroySession() are shown below:
function authenticateUser () {
var myConfig = {
auth : {
name : "superuser",
password : "superuser"
}
};
visualize.config( myConfig );
}
function destroySession() {
visualize( function ( v ) {
// Logout form JRS and finish the session.
v.logout().done( function () {
} );
} )
}
I would like to point out that when I first login my account this error is not thrown and renders the reports perfectly.
Why is this happening after logout and then login again?
This seemed to have worked for me. So I called visualize.config( config ) first so that I can store common configuration, to share them between visualize calls and then called the login method so that I can perform authentification with provided auth object. My reference: http://community.jaspersoft.com/wiki/visualizejs-api-notes-and-samples-v56
visualize.config( config );
visualize( function ( v ) {
v.login( config );
} );
This solution was not in their documentation though, but I put them piece by piece to finally solve the problem.
The documentation contained solution to this problem although it is not very explicit. See sample code and sample link from documentation link
visualize.config({
auth: {
name: "superuser",
password: "superuser"
}
});
Share common config between 'visualize' calls
Just a note:
Actually when you login you need to logout at some appropriate event. This depends on your application requirement e.g. if you are embedding reports within an existing web application, it seems more appropriate to link it existing application login/lougut