I trying to build AuthGuard for Angular 2 application with firebase-auth but there is one issue.
After the application loads If I'm signed in the AuthGuard
returns false
because of async operation.
The final effect is when page loads the AuthGuard
returns firstime false
and then true
, so eachtime redirects to signIn page and not to the root page.
I thougth I use *ngIf to show only SignInComponent
, if the user is not sign in, but this is not the solution because avery time will be SignInComponent visible for short time.
How to solved this Issue not to redirect to signIn page immediately?
Thank You for Your answers.
AuthService
@Injectable()
export class AuthService {
static UNKNOWN_USER = new AuthInfo(null);
user: Observable<firebase.User>;
authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);
constructor(private afAuth: AngularFireAuth) {
this.afAuth.authState.subscribe(
auth => {
if (auth) {
const authInfo = new AuthInfo(auth.uid);
this.authInfo$.next(authInfo);
} else {
this.authInfo$.next(AuthService.UNKNOWN_USER);
}
},
err => {
console.log(err);
}
);
}
}
AuthInfo
export class AuthInfo {
constructor(
public $uid: string
) {
}
isLoggedIn() {
return !!this.$uid;
}
}
AuthGuard
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.authInfo$
.map( authInfo => authInfo.isLoggedIn())
.take(1)
.do(allowed => {
console.log('authguard: ' + allowed);
if (!allowed) {
this.router.navigate(['/signin']);
}
});
}
}
Sorry, It was duplicated question for this question
My solution was
AuthService
@Injectable()
export class AuthService {
static UNKNOWN_USER = new AuthInfo(null);
authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);
constructor(private afAuth: AngularFireAuth) {}
getAuthInfo(): Observable<AuthInfo> {
return this.afAuth.authState.map(
auth => {
if (auth) {
const authInfo = new AuthInfo(auth.uid);
this.authInfo$.next(authInfo);
return authInfo;
} else {
this.authInfo$.next(AuthService.UNKNOWN_USER);
return AuthService.UNKNOWN_USER;
}
},
err => {
console.log(err);
}
);
}
AuthGuard
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
if (this.authService.authInfo$.getValue().isLoggedIn()) {
return true;
}
return this.authService.getAuthInfo()
.map( (authInfo: AuthInfo) => authInfo.isLoggedIn())
.do(allowed => {
if (!allowed) {
this.router.navigate(['/signin']);
return false;
} else {
return true;
}
}).take(1);
}
}