firebase / firebase/firebase-js-sdk

multiFactor throws internal error when reloadListener exists on user.

Open
#7,709 5 comments 0 reactions 0 assignees View on GitHub
api: auth needs-attention question stack:React
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.