Current behaviour: AuthGuard seems to not trigger at all and navigating to /dashboard works but leaves a blank screen, does not even console.log the Observable and does not trigger a redirect.
Expected Behaviour: Navigating to /dashboard should trigger the AuthGuard and redirect to /login.
auth.service.ts
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { catchError, tap } from 'rxjs/operators';
import { Subject, throwError } from 'rxjs';
import { User } from './user.model';
interface AuthResponseData {
data: {
firstName: string;
lastName: string;
userId: string;
userToken: string;
};
}
@Injectable({
providedIn: 'root',
})
export class AuthService {
user = new Subject<User>();
constructor(private http: HttpClient) {}
login(email: string, password: string) {
const headers = new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded',
});
let body = new HttpParams()
.set('username', email)
.set('password', password);
return this.http
.post<AuthResponseData>('${apiUrl}/Login', body, {
headers: headers,
withCredentials: false,
})
.pipe(
catchError((errorRes) => {
const meta = errorRes.error.meta;
let errorMessage = 'UNKNOWN';
if (!meta.errorName) {
return throwError(errorMessage);
}
switch (meta.errorName) {
case 'PASSWORD_DOES_NOT_MATCH':
case 'NO_SUCH_USER':
errorMessage = meta.errorName;
break;
default:
errorMessage = errorMessage;
}
return throwError(errorMessage);
}),
tap((resData) => {
const user = new User(
resData.data.firstName,
resData.data.lastName,
resData.data.userId,
resData.data.userToken,
);
this.user.next(user);
})
);
}
}
Router:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthComponent } from './auth/auth.component';
import { AuthGuard } from './auth/auth.guard';
import { DashboardComponent } from './dashboard/dashboard.component';
import { LayoutComponent } from './layout/layout.component';
const routes: Routes = [
{ path: '', redirectTo: '/login', pathMatch: 'full' },
{
path: '',
component: LayoutComponent,
canActivate: [AuthGuard],
children: [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
],
},
{ path: 'login', component: AuthComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
auth.guard.ts:
import { Injectable } from '@angular/core';
import {
CanActivate,
ActivatedRouteSnapshot,
RouterStateSnapshot,
Router,
UrlTree,
} from '@angular/router';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
return this.authService.user.pipe(
take(1),
map((user) => {
const isAuth = !!user;
if (isAuth) {
return true;
}
console.log(user);
return this.router.createUrlTree(['/login']);
})
);
}
}
How about modifing your login
method as below?
login(email: string, password: string) {
const headers = new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded',
});
let body = new HttpParams()
.set('username', email)
.set('password', password);
this.http
.post<AuthResponseData>('${apiUrl}/Login', body, {
headers: headers,
withCredentials: false,
})
.subscribe(resData => {
const user = new User(
resData.data.firstName,
resData.data.lastName,
resData.data.userId,
resData.data.userToken,
);
this.user.next(user);
}, (errorRes) => {
const meta = errorRes.error.meta;
let errorMessage = 'UNKNOWN';
if (!meta.errorName) {
return throwError(errorMessage);
}
switch (meta.errorName) {
case 'PASSWORD_DOES_NOT_MATCH':
case 'NO_SUCH_USER':
errorMessage = meta.errorName;
break;
default:
errorMessage = errorMessage;
}
return throwError(errorMessage);
});
}
I think you need to change your guard
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> {
return this.authService.user.pipe(
take(1),
map((user) => {
const isAuth = !!user;
if (isAuth) {
return true;
} esle {
this.router.navigate(['/login']) <==== HERE
return false
}
})
);
}
}
And add in your routes
...
canActivate: [AuthGuard],
canActivateChild: [AuthGuard]
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.