firebase / firebase/firebase-js-sdk
multiFactor throws internal error when reloadListener exists on user.
- Dominant language
- TypeScript
- Stars
- 5.1k
- Forks
- 1k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 37
Description
### Operating System
macOS 12.6
### Browser Version
Chrome/117.0.5938.149
### Firebase SDK Version
10.5.0
### Firebase SDK Product:
Auth, Database, Firestore
### Describe your project's tooling
CRACO react app
### Describe the problem
During the upgrade from v8.0.0 to v10.5.0 we also migrated to the modular api. In our application we (partially) enrolled multi-factor authentication and therefore need to check if the user has `enrolledFactors` and show the enrollment flow when applicable.
However, we encountered that the previous check to get the `enrolledFactors` were failing after the migration. Prior to the migration the enrolled factors were obtained via `user.multiFactor.enrolledFactors`. This is equivalent to `multiFactor(user).enrolledFactors`. But there is an assertion that checks whether that the reloadListener on the `user` object is null. Why is the assertion there? It means you cannot check the multiFactor once the reloadListener is set or we have to clear it ourselves.
The internal error:
```
assert.ts:136 Uncaught FirebaseError: Firebase: Error (auth/internal-error).
at createErrorInternal (assert.ts:136:55)
at _assert (assert.ts:167:11)
at UserImpl._onReload (user_impl.ts:154:5)
at new MultiFactorUserImpl (mfa_user.ts:37:10)
at MultiFactorUserImpl._fromUser (mfa_user.ts:47:12)
at multiFactor (mfa_user.ts:121:27)
```
### Steps and code to reproduce issue
When we update claims on the user, we force a refresh of the JWT:
```
await firebaseUser.getIdTokenResult(true);
setFirebaseUser(_.clone(firebaseUser));
```
This updates the local state `firebaseUser` and following check fails as user has a reloadListener.
```
const userHasMultifactorEnabled = useMemo((): boolean => {
return firebaseUser ? multiFactor(firebaseUser).enrolledFactors.length > 0 : false;
}, [firebaseUser]);
```
Do we need to manually clear the `reloadListener` or check on reloadListener in `userHasMultifactorEnabled`? Can we get some clarification on the assertion?
Workaround:
```
const userHasMultifactorEnabled = useMemo((): boolean => {
try {
return firebaseUser ? multiFactor(firebaseUser).enrolledFactors.length > 0 : false;
} catch (error) {
return true;
}
}, [firebaseUser]);
```
Contributor guide
Assessment
This issue has not been assessed yet.