Я пытаюсь реализовать аутентификацию с помощью Observables в Angular 10 . Я использую ReplaySubject в AuthService для установки текущего пользователя, вошедшего в систему. Проблема в том, что AuthGuard никогда не перенаправляет на главную после входа пользователя. Я описываю проблему ниже на auth.guard.ts
файл.
app.routing.ts
const routes: Routes = [
{
path: 'not-found',
component: NotFoundComponent,
},
{
path: '',
component: MainLayoutComponent,
children: [
{
path: '',
canActivateChild: [AuthGuard],
loadChildren: () =>
import('./modules/landing/landing.module').then(
(m) => m.LandingModule
),
},
],
},
{ path: '**', redirectTo: 'not-found', pathMatch: 'full' },
];
auth.service.ts
@Injectable({ providedIn: 'root' })
export class AuthService {
baseUrl = environment.apiUrl;
private currentUserSource = new ReplaySubject<LoggedIn>(1);
currentUser$ = this.currentUserSource.asObservable();
constructor(private http: HttpClient) {}
signIn(user: SignInDto) {
return this.http.post(this.baseUrl + 'auth/signin', user).pipe(
map((user: LoggedInDto) => {
if (user) {
localStorage.setItem('token', user.token);
this.currentUserSource.next(user);
return user;
}
})
);
}
getCurrentUser(token: string) {
if (token === null) {
this.currentUserSource.next(null);
return of(null);
}
const headers = new HttpHeaders().set('Authorization', 'Bearer ' + token);
return this.http.get(this.baseUrl + 'auth/me', { headers }).pipe(
map((user: LoggedIn) => {
if (user) {
localStorage.setItem('token', user.token);
this.currentUserSource.next(user);
}
})
);
}
}
app.component.ts
export class AppComponent implements OnInit {
constructor(private readonly authService: AuthService) {}
ngOnInit(): void {
this.getCurrentUser();
}
getCurrentUser() {
const token = localStorage.getItem('token');
this.authService.getCurrentUser(token).subscribe(() => {
console.log('user loaded');
}, console.log);
}
}
export class SignInComponent implements OnInit {
returnUrl: string;
constructor(
private readonly authService: AuthService,
private readonly router: Router,
private readonly activatedRoute: ActivatedRoute
) {}
ngOnInit(): void {
this.returnUrl = this.activatedRoute.snapshot.queryParams.returnUrl || '';
}
onSubmit() {
this.authService.signIn({username: 'xxx', password: 'xxx'}).subscribe(
(response) => {
this.router.navigateByUrl(this.returnUrl);
},
console.log
);
}
}
auth.guard.ts
Проблема здесь ... Когда пользователь подписывается в currentUser $ observable всегда равно null , все остальное работает нормально (токен сохраняется в локальном хранилище). Если я попытаюсь обновить sh страницу после входа в систему, охрана будет работать нормально, но если я вошел в систему без обновления страницы, ничего не произошло.
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivateChild {
logged: boolean = false;
constructor(private authService: AuthService, private router: Router) {}
canActivateChild(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.currentUser$.pipe(
map((auth) => {
// when you sign in, auth object is always null
// so the guard never redirect. But, if I refresh the page
// after the token was saved the guard works fine, the auth object comes with data
// What's the problem? :(
if (auth) {
return true;
}
this.router.navigate(['/signin'], {
queryParams: { returnUrl: state.url },
});
})
);
}
}
Итак, вопрос в том, что я делаю не так или игнорируя?