javascript - 如何在启动 Angular 应用程序之前等待 Firebase 身份验证

标签 javascript angular firebase firebase-authentication angularfire2

我想在firebase身份验证检索用户 token 时显示一个小的加载 Logo ,然后“真正”启动单页应用程序。

到目前为止,我有一个身份验证服务:

constructor(
    public afAuth: AngularFireAuth,
    ) {
      this.afAuth.onAuthStateChanged(user => {
        if (user) {
           this.setCredentials(user)
        }
      })
    }

  setCredentials(user: firebase.User) {
      return user.getIdTokenResult(true).then(idTokenResult => {
        this.credentials = {
          userId: idTokenResult.claims.id,
          role: idTokenResult.claims.role,
          token: idTokenResult.token,
        };
        // STARTS THE APPLICATION NOW ?
      })
  }

是否有可能实现这种行为?我已经阅读了有关 APP_INITIALIZER 的信息,但没有成功。我想避免本地存储/ session 存储,而是完全依赖这个初始化。

更新 :

创建了一个初始化函数:
export function initApp(auth: AuthService, afAuth: AngularFireAuth) {
    return () => {
      return new Promise((resolve) => {
        afAuth.user.pipe(
            take(1),
        ).subscribe(user => {
          if (user) {
            auth.setCredentials(user)
            .then(() => resolve())
          } else {
              resolve();
          }
        })
      });
    }
  }

并编辑了 AppModule 提供者:
providers: [
    interceptorProviders /* my interceptors */,
    {
      provide: APP_INITIALIZER,
      useFactory: initApp,
      deps: [AuthService, AngularFireAuth],
      multi: true
    }
  ]

仍然需要弄清楚如何添加等待标志,但这是另一个问题。我会尽快更新。

最佳答案

回答我自己的问题
总而言之,我想确保在处理路由之前将与 firebase 用户关联的 token 声明( Angular 色和用户 ID)存储在我的身份验证服务中,因为这些路由中的组件将使用这些凭据。
最后我没有遵循 APP_INITIALIZER 这不是一个很好的解决方案。
认证服务

private _credentials: BehaviorSubject<Credentials> = new BehaviorSubject<Credentials>(null);
public readonly credentials$: Observable<Credentials> = this._credentials.asObservable();

constructor(private afAuth: AngularFireAuth) {
this.afAuth.authState.subscribe(user => {
      this._credentials.next(null);
      if (user) {
        user.getIdTokenResult().then(data => {
          const credentials = {
            role: data.claims.role,
            token: data.token,
            userId: data.claims.userId
          }

          this._credentials.next(credentials);
          console.log(credentials);
        })
      } else {
        this._credentials.next({role: null, token: null, userId: null});
      }
    })
}

get credentials(): Credentials {
    return this._credentials.value;
}
在 app.component 中显示等待微调器
如果未设置凭据,则下面会阻止显示路由。
在模板中:
<div *ngIf="!(credentials$ | async)" class="logged-wrapper">
    <div class="spinner-wrapper">
        <mat-spinner class="spinner"></mat-spinner>
    </div>
</div>
<router-outlet *ngIf="(credentials$ | async)"></router-outlet>
在组件中:
credentials$: Observable<any>;

constructor(
    private auth: AuthService,
  ) {
    this.credentials$ = this.auth.credentials$;
  }
身份验证
takewhile 让我可以确保在进一步操作之前设置我的凭据。
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Promise<boolean> {
    return new Promise((resolve) => {
        this.auth.credentials$.pipe(
            takeWhile(credentials => credentials === null),
        ).subscribe({
            complete: () => {
                const credentials = this.auth.credentials
                if (!credentials.role) {
                    this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } })
                    resolve(false);
                }
                if (next.data.roles && next.data.roles.indexOf(credentials.role) === -1) {
                    this.router.navigate(['/']);
                    resolve(false);
                }
                resolve(true)
            }
        })
    })
}

关于javascript - 如何在启动 Angular 应用程序之前等待 Firebase 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62099759/

相关文章:

javascript - 此聚光灯效果在 Safari 7.1+ 中不起作用

angular - Angular 2/Jasmine 测试中的 testbed.get 和 inject 有什么区别?

android - Firebase A/B 测试推出领导者

java - Firebase Java Admin SDK 线程安全吗?

尝试将非空白与工作演示匹配时,Javascript Regexp 表现奇怪

javascript - 这是在钩子(Hook) react 中更新状态的正确方法吗?

javascript - 为什么这在 Internet Explorer 上不起作用? [jQuery、单选、选择器]

javascript - 无法使用 Angular $ http post将数据发布到实时服务器上的php,但在localhost上工作

javascript - 值未在表 Angular 中呈现

java - Java 应用程序(非 Android)的 Firebase 用户身份验证