The problem is with Angular Universal, if I build app without Universal It's working fine but with Angular Universal this is the problem.
I'm using angular with ngrx and Angular Universal, on every reload I'm sending request to the backend then retreiveing user data. If route is protected with auth guard on reload if user is logged in first it redirects to /login then after 0.5 seconds redirects to protected route, data is loaded everything works fine, but why It's showing /login first ?
AuthGuard
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.store.select(fromAuth.selectAuthState).pipe(
map(authState => authState.isInitializing),
filter((isInit) => !isInit),
tap((data) => console.log(data)),
switchMap(() => {
return this.store.select(fromAuth.selectAuthState).pipe(
map(authState => authState),
map((isAuth) => {
console.log(isAuth);
if (isAuth.user) return true;
return this.router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url } });
}),
take(1)
);
})
);
Initial state in Ngrx/store
export const initialState: State = {
isAuthenticated: false,
isInitializing: true
On login success and on login fail isInitializing is set to false
on(AuthActions.logInSuccess, (state) => {
return {
isInitializing: false,
isAuthenticated: true,
};
}),
I'm dispatching isLoggedIn action in APP_INITIALIZER
export function appInitializerFactory(
store: Store<any>
) {
return () => {
store.dispatch(AuthActions.isLoggedIn());
};
}
providers: [
{
provide: APP_INITIALIZER,
useFactory: appInitializerFactory,
deps: [Store],
multi: true
}
]
Inside Auth Effects
isLoggedIn$ = createEffect(() =>
this.actions$.pipe(
ofType(AuthActions.isLoggedIn),
switchMap(() => {
return this.authService.isLoggedIn().pipe(
switchMap((user: any) => {
return [
AuthActions.logInSuccess({ token: user.token, name: user.data.user.name, email: user.data.user.email, id: user.data.user._id, likedProperties: [...user.data.user.likedPropertiesSell, ...user.data.user.likedPropertiesRent], myProfileInformations: userProfile })]
}),
catchError(err => {
return of(AuthActions.logInFail({ error: `code ${err.status}` }))
}
)
);
})
)
);
Console log from Auth Guard
2020-12-24T14:01:53.070535+00:00 app[web.1]: isAuthenticated: false,
2020-12-24T14:01:53.070535+00:00 app[web.1]: user: null,
2020-12-24T14:01:53.070536+00:00 app[web.1]: errorMessage: 'code undefined',
2020-12-24T14:01:53.070537+00:00 app[web.1]: likedProperties: null,
2020-12-24T14:01:53.070537+00:00 app[web.1]: following: null,
2020-12-24T14:01:53.070538+00:00 app[web.1]: followingListLoaded: false,
2020-12-24T14:01:53.070538+00:00 app[web.1]: myProfileInformations: null,
2020-12-24T14:01:53.070539+00:00 app[web.1]: isInitializing: false
2020-12-24T14:01:53.070539+00:00 app[web.1]: }
So store is setting isInitializing to false before user data is retreived and I really don't know why errorMessage exists there, in redux store logInFail() is never dispatched