Firebase + ngrx +多个身份验证提供程序

时间:2019-12-07 03:18:53

标签: angular firebase firebase-authentication ngrx

Firebase有一种奇怪的情况,当有人首先使用google provider进行登录时,您将无法使用其他提供商登录,就像您在问题Firebase JS API auth - account-exists-with-different-credential中看到的那样。

最后,我在上述问题的2个第一答案之后实现了这一目标,但是有1个问题和1个改进。

问题是,为什么当我使用异步内部catchError时,它期望一个正常的动作而不是一个可观察的动作。

改进之处在于,当我调用弹出窗口时,是否可以隐藏它?还是避免再次调用SigninProvider操作?(原因是因为用户将看到2个弹出窗口)。

const resultProvider = await this.afAuth.auth.signInWithPopup(linkedProvider);
await resultProvider.user.linkWithCredential(error.credential);

全效果

@Effect()
    signInProvider: Observable<Action> = this.actions$.pipe(
        ofType(AuthActionTypes.SIGNIN_PROVIDER),
        map((action: SigninProvider) => action.payload),
        switchMap((provider) => {
            let result: any;
            let provi = provider;
            if (provider === 'google') {
                result = this.firebaseAuthService.signInGoogleLogin();
            } else if (provider === 'facebook') {
                result = this.firebaseAuthService.signInFacebookLogin();
            } else if (provider === 'twitter') {
                result = this.firebaseAuthService.signInTwitterLogin();
            }

            const resultAction: Observable<Action> = result.pipe(
                switchMap((userSignIn) => {
                    console.log("TCL: AuthEffects -> userSignIn", userSignIn)
                    return combineLatest(this.afAuth.authState.pipe(take(1)), of(userSignIn));
                }),
                switchMap(([user, userFromProvider]) => {
                    console.log("TCL: AuthEffects -> user", user)
                    const userEmail = user.email ? user.email : userFromProvider.additionalUserInfo.profile.email;
                    const userDto: CreateUserProviderDto = {
                        uid: user.uid,
                        fullName: user.displayName,
                        username: userEmail,
                        email: userEmail,
                        terms: true
                    };
                    return combineLatest(of(user), from(user.getIdToken()), this.usersService.usersSignInProviderPost(userDto));
                }),
                map(([user, token, userFromBackend]) => {
                    const currentUser: CurrentUser = {
                        token: token, refreshToken: user.refreshToken, user: {
                            _id: userFromBackend._id,
                            uid: userFromBackend.uid,
                            email: userFromBackend.email,
                            profile: userFromBackend.profile,
                            fullName: userFromBackend.fullName,
                            username: userFromBackend.username
                        }
                    };
                    this.localStorageService
                        .setItem(AUTH_KEY, {
                            token: token,
                            refreshToken: user.refreshToken,
                            isAuthenticated: true,
                            user: currentUser.user
                        });
                    this.ngZone.run(() => {
                        this.router.navigate(['/']);
                    });
                    return new SigninProviderSuccess(currentUser);
                }),
                catchError(async (error) => {
                    let displayMessage;
                    if (error.email && error.credential && error.code === 'auth/account-exists-with-different-credential') {
                        const providers = await this.afAuth.auth.fetchSignInMethodsForEmail(error.email)
                        const firstPopupProviderMethod =
                            providers.find(p => this.firebaseAuthService.supportedPopupSignInMethods.includes(p));

                        // Test: Could this happen with email link then trying social provider?
                        if (!firstPopupProviderMethod) {
                            throw new Error(`Your account is linked to a provider that isn't supported.`);
                        }

                        const linkedProvider = this.firebaseAuthService.getProvider(firstPopupProviderMethod);
                        linkedProvider.setCustomParameters({ login_hint: error.email });

                        const resultProvider = await this.afAuth.auth.signInWithPopup(linkedProvider);
                        await resultProvider.user.linkWithCredential(error.credential);

                        return new SigninProvider(provi);
                    } else if (typeof error === 'object'
                        && error !== null
                        && error.hasOwnProperty('code')
                        && error.hasOwnProperty('message')) {
                        const errorNoTypes: any = { ...error };
                        displayMessage = `${errorNoTypes.code} - ${error.message}`;
                        this.toastrService.danger('Try it again!', displayMessage, {
                            duration: 8000
                        });
                    }
                    return new RetrieveError(error);
                }),

            );
            return resultAction;
        })

    );

0 个答案:

没有答案