auth().currentUser.reload() returns undefined
The firebase core doesn't include the auth module. You need to add the auth module:
import firebase from 'firebase/app';
import 'firebase/auth';
If no user is currently authenticated, currentUser will be null and will not have a reload() function. Trying to call it would give you and error.
The reload() function returns a promise so you can use .then, but the promise doesn't return the currentUser object. To view the currentUser after the reload, just refer to the currentUser...
if (firebase.auth().currentUser) {
firebase.auth().currentUser.reload().then(() => {
console.log(JSON.stringify(firebase.auth().currentUser));
});
} else {
console.log('No authenticated user');
}
Firebase user: isEmailVerified returns false
By applying the intent filter you have, you've told Android that you will handle all web requests that target https://test-project.firebaseapp.com
. Now that your application has trapped browsing to this URL, you now need to make the request to the server on the user's behalf.
By default, when you send an email verification off to the user, they will receive an email with a link that looks like:
https://<PROJECT_ID>.firebaseapp.com/__/auth/action?mode=verifyEmail&oobCode=<VERIFICATION_CODE>&apiKey=<API_KEY>&lang=<LANGUAGE>
Note: These links can be customized using custom action handlers or you could make use of dynamic links so that you don't intercept everything headed for https://test-project.firebaseapp.com
.
Because a user may wish to visit your app's website in a browser, you should make your intent filter more specific to just handling email actions.
<intent-filter android:label="@string/filter_view_handle_action_code">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="test-project.firebaseapp.com"
android:pathPrefix="/__/auth/action" />
</intent-filter>
Disclaimer: I haven't tested if the below method works, but in theory it should.
If you intercept such a URL, you need to handle it in the onCreate
method:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = this.getIntent();
if (intent.hasCategory(android.intent.category.BROWSABLE)) {
// intent came from browser
Uri data = intent.getData();
String mode = data.getQueryParameter("mode");
String oobCode = data.getQueryParameter("oobCode");
if (mode != "verifyEmail" || oobCode == null) {
Log.i("MyActivity", "Started with unexpected browsable intent");
return;
}
handleVerifyEmailActionCode(oobCode);
}
}
private handleVerifyEmailActionCode(String oobCode) {
String email = null;
FirebaseAuth.getInstance().checkActionCode(oobCode)
.onSuccessTask( actionCodeResult -> {
if (actionCodeResult.getOperation() != ActionCodeResult.VERIFY_EMAIL) {
throw new UnsupportedActionCodeOperationException(actionCodeResult.getOperation());
}
email = actionCodeResult.getInfo().getEmail();
return FirebaseAuth.getInstance().applyActionCode(oobCode);
})
.addOnCompleteListener( applyActionCodeTask -> {
if (!applyActionCodeTask.isSuccessful()) {
Exception ex = applyActionCodeTask.getException();
// TODO: Handle exceptions
Toast.makeText(getApplicationContext(), "Failed to verify email. " + ex.getMessage(), Toast.LENGTH_SHORT).show();
return;
}
// email verified successfully!
// do something interesting
Toast.makeText(getApplicationContext(), email + " was verified!", Toast.LENGTH_SHORT).show();
FirebaseUser user = FirebaseAuth.getCurrentUser(); // WARN: May not have finished initializing yet?
if (user != null && user.getEmail() == email) {
user.reload()
.addOnFailureListener(ex -> {
Log.e(MyActivity.class, "Failed to refresh user token: " + ex.getMessage());
});
} else {
Log.i(
MyActivity.class,
user == null
? "User wasn't signed in, skipping reload"
: "User email mismatch, skipping reload"
);
}
});
}
/**
* Custom exception to be used when a OOB code's `ActionCodeResult.Operation`
* doesn't match what it was expected to be.
*
* @see https://firebase.google.com/docs/reference/android/com/google/firebase/auth/ActionCodeResult#constant-summary
*/
public class UnsupportedActionCodeOperationException extends Exception {
protected int operation;
public UnsupportedActionCodeOperationException(int operation) {
super("The ActionCodeResult.Operation value of " + operation + " is not supported");
this.operation = operation;
}
public int getOperation() {
return this.operation;
}
}
What use case has the reload() function of a FirebaseUser in flutter?
This seems to be the intended behavior.
Like it was already said only calling .reload
does not work.
await user.reload();
print(user.emailVerified) // false
Instead you also have to get the currentUser
again.
await user.reload();
// `currentUser` is synchronous since FirebaseAuth rework
user = firebaseAuth.currentUser;
print(user.emailVerified) // true
With the rework (firebase_auth: ^0.18.0
) FirebaseAuth
does also expose a .userChanges()
-Stream.
This seems to be the preferred solution instead of manually reloading the user information.
From the documentation of FirebaseAuth.userChanges()
:
This is a superset of both [authStateChanges] and [idTokenChanges]. It
provides events on all user changes, such as when credentials are
linked, unlinked and when updates to the user profile are made. The
purpose of this Stream is to for listening to realtime updates to the
user without manually having to call [reload] and then rehydrating
changes to your application.
Taken from the comments below it does not seem to work for .isEmailVerified
though.
firebaseAuth.userChanges().listen((user) {
// Your logic
});
Firebase AuthInstance.currentUser is null after successfully reload
The authInstance.currentUser
sometimes takes some time to be updated. You can move your reload
call to the main thread on the observeOn
to give authInstance
more time to be updated, and also just in case add a retry
clause to your code. It would be something like this:
RxFirebaseUser.reload(authInstance.currentUser!!)
.subscribeOn(Schedulers.io())
.repeatUntil { authInstance.currentUser != null }
.defaultTimeout()
.subscribe({
val user = authInstance.currentUser
val emailVerified = user?.isEmailVerified ?: false
dispatcher.dispatchOnUi(VerifyUserEmailCompleteAction(requestState = if (user == null) requestRunning() else requestSuccess(),
verified = emailVerified))
}, { error ->
dispatcher.dispatchOnUi(VerifyUserEmailCompleteAction(requestState = requestFailure(error),
verified = false))
})
Related Topics
Empty Class in Swift Playground Gives _Lldb_Expr_ Error
Swift Function Compiler Error 'Missing Return'
Swiftui Tabview Gives an Error Message During Add/Delete the Element of Coredata
iOS 13 Swiftui: App Crashes Upon Launch on Real Device
Randomizing Node Movement Duration
How to Create a Dynamic Link in Firebase Programmatically? Swift
How to Convert This Date Format in Swift
Uibarbuttonitem Action Not Work Uitableview Cell
From Which Direction Swift Starts to Read Dictionaries
What Does an Exclamation Mark in a Property in Swift Language
Tests for Custom Uitableviewcell, Cellforrowatindexpath Crashes with Nil Outlets
Datefromstring() Returns Incorrect Date
Swift Decodable, Endpoint Returns Completely Different Types
Getch() Equivalent in Swift: Read a Single Character from Stdin Without a Newline
Swift Tuple Has Unexpected Print Result
Access Enum Associated Value as Optional