I have checkAuth
function in ngOnInit
in app.component.ts
which checks localStorage for token and if token is valid authService logs you in.
Also, I have AuthGuard in /profile
route which checks if you logged in.
If I click the link in the navbar this works great, but if I go to link directly authGuard working before my checkAuth
function and returns false.
Where do I need to place my checkAuth
function to make it work correctly?
Or maybe I need to change something in AuthGuard or in app.component
Here is AuthGuard code
@Injectable({
providedIn:'root'
})
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private auth:AuthService, private router:Router) {
}
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
console.log(this.auth.isAuth)
console.log(this.auth.isLoggedIn())
if (this.auth.isLoggedIn()){
return of(true)
} else {
this.router.navigate(['/login'])
return of(false)
}
}
canActivateChild(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
return this.canActivate(route, state)
}
}
app.component
ngOnInit() {
if (localStorage.getItem('token')){
this.auth.checkAuth().subscribe(
(data) => {
console.log(data)
console.log(this.auth.isAuth)
}
)
}
}
and checkAuth in AuthService
checkAuth():Observable<UserDto>{
return this.http.get<UserDto>(`/api/user/refresh`, {withCredentials:true, observe:'body', responseType:'json'})
.pipe(
tap(
(data) => {
localStorage.setItem('token', data.accessToken)
this.setAuth(true)
this.setUser(data.user)
},
(error) => {
console.log(error)
}
)
)
}
CodePudding user response:
If you want checkAuth
to run before the guard, you have to make it a guard as well, and use it before the guard that you already have. E.g: canActivate: [CheckAuthGuard, AuthGuard]
.
This is what's going on right now:
First scenario - accessing /profile
by clicking in the navbar
- You access the application's root component
- Whatever guards you have on the root route run
- The root component is initialized and
AppComponent.ngOnInit()
runs, thus runningcheckAuth()
- You click the link in the navbar to go the
/profile
route - Guards for the profile route are run
Second scenario - accessing /profile
by visiting the URL directly
- You access the application's root component, but this time it is routed to the
/profile
route - Whatever guards you have on the profile route run
- The root component and it's child are initialized, running their
ngOnInit()
methods
See? In the second scenario, the guard runs before ngOnInit and checkAuth
. I advise you to put some console.log
calls on your app, so you can more easily see the order in which things are happening.
Basically this is it, guards run before the component is rendered, so you should keep that in mind. Extract your checkAuth
call to a guard and you'll be fine.