如何在角度Firebase中修复浏览器刷新上的“ TypeError:无法读取null的属性'getIdToken'”?

时间:2019-10-30 12:42:23

标签: angular firebase firebase-authentication

我正在用角度8中的Firebase来验证前端和后端的用户。要在后端对用户进行身份验证,我需要发送用户ID令牌。

我正在使用firebase getIdToken来获取令牌,并且它只能部分工作。刷新页面时,发生错误“ TypeError:无法读取null的属性'getIdToken'”。

我试图将令牌硬编码为getToken()方法,即使刷新也可以使用,但这是不可行的,所以我使getToken方法返回Observable。

在Http拦截器TokenInterceptorService中获取该可观察对象,以将该令牌添加到所有请求中。

export class AuthService {

  constructor(
    public afs: AngularFirestore,   // Inject Firestore service
    public afAuth: AngularFireAuth, // Inject Firebase auth service
    public router: Router,
    public ngZone: NgZone // NgZone service to remove outside scope warning
  ) {}


  // Other authentication methods for sign up etc.
  // removed here for readability


  getToken(): Observable<string> {

    // getIdToken() returns promise so using 'from' to 
    // convert it to an Observable
    const result = from(this.afAuth.auth.currentUser.getIdToken()
      .then( token => {
          console.log(token);
          return token;
      })
    );

    return result;
  }


}
export class TokenInterceptorService implements HttpInterceptor {


  constructor(private authService: AuthService) { }


  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return this.authService.getToken()
      .pipe(
        switchMap(token => {

          const newRequest = request.clone({
            setHeaders: {Authorization: `JWT ${token}`}
          });

          return next.handle(newRequest);

        })
      );

 }

}

我看到过类似的my wrong example,并且正在使用该解决方案进行一些修改。

我什至尝试从getToken()方法返回promise,但这也不起作用。

1 个答案:

答案 0 :(得分:2)

获取currentUser是异步的,因此可以预期最初它是null。就像documentation中提到的那样:

  

注意:currentUser也可能为空,因为auth对象尚未完成初始化。

相反,您应该使用authState来获取当前用户。然后,从您那里获得的用户,可以调用getIdToken(),这将返回一个承诺。您可以在此处使用from将其转换为可观察的:

getToken(): Observable<string | null> {
  return this.afAuth.authState.pipe(
    take(1),
    switchMap((user) => {
      if (user) {
        return from(user.getIdToken())
      }
      return of(null);
    })
  )
}

然后在您的拦截器中,也检查令牌是否存在。如果没有用户,它将返回null