如何通过自定义REST API使用Firebase Auth实现登录?Cognito登录后导航栏不显示用户名
问题根因排查
- 认证状态监听逻辑断层:Google登录走Firebase SDK的
signInWithPopup流程,会自动触发afAuth.authState流推送登录态,所以导航栏能正常渲染用户信息;但Cognito登录流程仅调用了自建后端接口、往Firestore写入用户文档,完全没有触发Firebase认证状态的更新,afAuth.authState会一直保持未登录的null值,直接匹配模板里的anonymousUser分支。 - 类属性名与模板读取规则不匹配:AuthService里定义的用户数据流属性是
cuser$,但导航栏模板读取的是auth.user$,属性名不一致会导致永远取不到对应数据流。 - 参考的示例逻辑没有完整落地:原示例的标准设计是将认证状态流与对应uid的Firestore用户文档做关联,不管是Firebase官方渠道还是自建的Cognito渠道,只要认证状态匹配到有效用户id,就能自动拉取对应用户数据渲染到页面,当前实现仅落地了Firebase渠道的状态关联部分。
具体整改步骤
- 统一AuthService的用户流属性名,把原本的
cuser$改名为user$,和导航栏模板的读取逻辑保持一致。 - 重构用户数据流的绑定逻辑,兼容双渠道登录的状态感知:
不要把用户流直接绑定死afAuth.authState,需要合并两个维度的状态源:- 原有的Firebase官方渠道(Google/Facebook/Twitter)的状态监听:拿到
afAuth.authState的用户后,关联对应uid的Firestore文档拉取完整用户信息 - 新增自建Cognito登录的状态触发器,当Cognito登录完成后,手动把当前登录用户推送到触发流里
替换后的核心代码示例:
import { BehaviorSubject, merge, of } from 'rxjs'; import { switchMap } from 'rxjs/operators'; // AuthService 类内部 private cognitoLoginState$ = new BehaviorSubject<CUser | null>(null); user$: Observable<CUser | null>; constructor(private afAuth: AngularFireAuth, private httpClient: HttpClient, private afs: AngularFirestore) { // 合并双渠道的登录状态流 this.user$ = merge( // 处理Firebase原生渠道的登录状态 this.afAuth.authState.pipe( switchMap(fbUser => { if (!fbUser) return of(null); return this.afs.doc<CUser>(`users/${fbUser.uid}`).valueChanges(); }) ), // 处理Cognito自建渠道的登录状态 this.cognitoLoginState$.asObservable() ); } - 原有的Firebase官方渠道(Google/Facebook/Twitter)的状态监听:拿到
- 补全Cognito登录成功后的状态推送逻辑:
在doCognitoLogin方法的成功分支里,写入Firestore用户文档后,把构造好的Cognito用户对象推送到cognitoLoginState$流里,让导航栏的用户流感知到登录状态变化,修改后的核心代码:doCognitoLogin(email, password){ // ... 省略接口参数构造逻辑 return this.httpClient.post(this.apiUrl + '/signin', payload).pipe( map((response: any) => { const res = response; if (!res.error) { const currentUser: CUser = { uid: email, email: email, displayName: email, photoURL: "", emailVerified: true }; this.updateUserData(currentUser); // 主动推送登录状态到流中 this.cognitoLoginState$.next(currentUser); return true; } else { console.log('wrong password'); return false; } }) ); } - 完善登出逻辑的状态重置:
原来的登出方法仅调用了afAuth.signOut(),需要补全Cognito渠道的状态清空,避免登出后残留旧的用户信息:logout() { this.afAuth.signOut(); // 清空Cognito渠道的登录状态 this.cognitoLoginState$.next(null); }
额外注意事项
- 现有代码混用了旧版本rxjs的操作符导入方式(
import 'rxjs/add/operator/switchMap'),和新版本rxjs的模块化导入规则不兼容,会导致流操作失效,建议统一换成从rxjs/operators导入对应操作符。 - Cognito渠道写入Firestore的用户uid需要保证全局唯一,避免和Firebase原生登录生成的随机uid冲突,导致不同渠道的用户数据串用。
内容的提问来源于stack exchange,提问作者Amir
相关产品推荐
相关产品推荐

