I would like to provide a server-side authentication before I give access to a specific route in angular.
I have a AuthGuard which implements CanActivate and a service AuthService.
The authService already has a private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
which views subscribe to in order to know if the user is logged in or not. I don't really know if my approach is wrong, but it does not seem to work.
This is what I have in auth.guard.ts:
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) : Observable<boolean> {
return this.authService.isAuthenticated().map((isLoggedIn) => {
if (isLoggedIn) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
})
}
and this is auth.service.ts:
@Injectable()
export class AuthService {
private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(null);
constructor(
private router: Router,
private http: HttpClient
) {
}
get isLoggedIn() {
return this.loggedIn.asObservable();
}
isAuthenticated() : Observable<boolean> {
const headers = new HttpHeaders().set("X-Requested-With", "XMLHttpRequest");
return this.http.get('/user', {headers: headers}).map(
response => {
if (response['username']) {
this.loggedIn.next(true);
return true;
} else {
return false;
}
}
)
}
AuthGuard is used to protect the routes from unauthorized access in angular. How AuthGuard Works? Auth guard provide lifecycle event called canActivate. The canActivate is like a constructor.
The canActivate method returns a boolean indicating whether or not navigation to a route should be allowed. If the user isn't authenticated, they are re-routed to some other place, in this case a route called /login . Now the guard can be applied to any routes you wish to protect.
Guards in Angular are nothing but the functionality, logic, and code which are executed before the route is loaded or the ones leaving the route. Different types of guards, CanActivate guard (e.g. it checks route access). CanActivateChild guard (checks child route access).
Here is approach for RXJS6, added a variable _isAuthenticated
in authentication service to request the server state just when the flag is disabled. I hope that helps others.
Ensure canActivate
returns a plain boolean or an observable. The route handler will subscribe to the given observable and reacts to first boolean value coming from the value stream.
auth.guard.ts
import { Injectable } from '@angular/core';
import { Router, CanActivate } from '@angular/router';
import { Observable } from 'rxjs/';
import { map, finalize } from 'rxjs/operators';
import { DataService } from '../data.service';
import { AuthenticationService } from './authentication.service';
@Injectable()
export class AuthenticationGuard implements CanActivate {
constructor(private router: Router,
private dataService: DataService,
private authenticationService: AuthenticationService) { }
canActivate(): any {
const isAuthenticated = this.authenticationService.isAuthenticated();
// All good
if ( isAuthenticated ) {
return true;
// Hmm, let's verify the user first
} else {
return this.authenticationService.isSessionAlive()
.pipe(
map(res => {
// No valid session; let's move to the login page
if ( res === false ) {
this.router.navigate(['/login'], { replaceUrl: true });
}
return res;
})
);
}
}
}
auth.service.ts (I'm using rxjs 6)
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { DataService } from '@app/core';
@Injectable()
export class AuthenticationService {
private _isAuthenticated = false;
constructor(
private dataService: DataService
) {}
isAuthenticated(): boolean {
return this._isAuthenticated;
}
isSessionAlive(): Observable<any> {
return Observable.create((observer) => {
this.dataService.SessionIsAlive()
.subscribe((res) => {
this._isAuthenticated = true;
observer.next(res.success); // your server response
}, (err) => {
this._isAuthenticated = false;
observer.next(false);
// observer.error(err); // won't work here you need to use next
});
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With