Как дождаться аутентификации firebase перед запуском приложения angular - PullRequest
0 голосов
/ 30 мая 2020

Я хотел бы отобразить небольшую загрузку lo go, пока аутентификация firebase получает токен пользователя, прежде чем запускать «по-настоящему» одностраничное приложение.

Пока у меня есть служба аутентификации:

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 безуспешно. Я хочу избежать локального хранилища / хранилища сеансов и вместо этого полагаться исключительно на эту инициализацию.

Обновление :

создал функцию инициализации:

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
    }
  ]

Еще нужно выяснить, как добавить ожидающий lo go, но это другой вопрос. Я обновлю как можно скорее.

Ответы [ 2 ]

0 голосов
/ 18 августа 2020

Отвечая на мой собственный вопрос

Подводя итог, я хотел убедиться, что мои утверждения токенов (роль и идентификатор пользователя, скажем,), связанные с пользователем firebase, хранились в моей службе аутентификации перед тем, как заняться маршрутизацией, потому что компоненты внутри этих маршрутов будут использовать эти учетные данные.

В конце концов, я не последовал APP_INITIALIZER, что на самом деле не очень хорошее решение. 1010 *

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$;
  }

Auth Guard

Это позволяет мне убедиться, что мои учетные данные установите перед тем, как продолжить.

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)
            }
        })
    })
}
0 голосов
/ 30 мая 2020

Вы должны использовать свою службу аутентификации в CanActivate защите маршрутизатора: https://angular.io/api/router/CanActivate

Это означает, что ваш AppModule сначала загрузится, а затем ваш дочерний маршрут (например, MainModule с маршрутизатором путь '') имеет охранник. Затем в AppModule вы можете проверить статус службы и показать информацию о загрузке, пока не будет активирован MainModule (когда аутентификация firebase завершена)

...