Auth.Auth().Currentuser.Reload() Doesn't Refresh Currentuser.Isemailverified

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



Leave a reply



Submit