In my web Angular project I've created an AuthenticationGuard and an AuthenticationService to handle the security.
These files comes from another branch of my project who works perfectly.
Here is how my scripts should works:
My problem is when AuthGuard access the AuthService : AuthService always return false.
auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
let url: string = state.url;
return this.checkLogin(url);
}
checkLogin(url: string): boolean {
if (this.authService.getIsLoggedIn()) {
return true;
}
// Store the attempted URL for redirecting
this.authService.redirectUrl = url;
// Navigate to the login page with extras
this.router.navigate(['/auth/login']);
return false;
}
}
auth.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/delay';
import { config } from './../shared/smartadmin.config';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import 'rxjs/add/operator/map'
@Injectable()
export class AuthService {
private isLoggedIn: boolean = false;
public redirectUrl: string;
constructor(private router: Router, private http: Http) {
}
public getIsLoggedIn(): boolean {
console.log("getIsLoggedIn() = " + this.isLoggedIn); // Always returns false
return this.isLoggedIn;
}
public login(username: string, password: string) {
this.ProcessLogin(username, password)
.subscribe(result => {
if (result === true) {
console.log("before attribution");
console.log("this.isLoggedIn = " + this.isLoggedIn); // returns false
this.isLoggedIn = true;
console.log("after attribution");
console.log("this.isLoggedIn = " + this.isLoggedIn); // returns true
this.router.navigate(this.redirectUrl ? [this.redirectUrl] : ['/home']);
} else {
this.logout();
}
});
}
public logout(): void {
localStorage.removeItem('oAuthToken');
this.isLoggedIn = false;
}
private ProcessLogin(username: string, password: string): Observable<boolean> {
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
let body = 'grant_type=password&username=' + encodeURIComponent(username) + '&password=' + encodeURIComponent(password);
let endpoint = config.API_ENDPOINT + 'token';
return this.http.post(endpoint, body, options)
.map((response: Response) => {
// login successful if there's a jwt token in the response
let token = response.json() && response.json().access_token;
if (token) {
localStorage.setItem('oAuthToken', token);
// return true to indicate successful login
return true;
} else {
localStorage.removeItem('oAuthToken');
// return false to indicate failed login
return false;
}
});
}
}
Without having seen your module definitions I suspect that you have not made AuthService a core service (a Singleton) which mean that every module that makes use of it will have its own instance (keeping track of its own isLoggedIn flag).
To make a service a singleton in angular it has to be served by the root module injector. To accomplish this you will need to do this:
import { NgModulep } from '@angular/core';
import { CommonModule, ModuleWithProviders } from '@angular/common';
import { AuthService, AuthGuard } from './services/index';
@NgModule({
imports: [
CommonModule,
ModuleWithProviders
]
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [
AuthService,
AuthGuard
]
};
}
}
And then call the forRoot method when importing the SharedModule into the root AppModule.
@NgModule({
imports: [
...
SharedModule.forRoot(),
...
],
...,
bootstrap: [AppComponent]
})
export class AppModule { }
Have a look att "Configure Core Services" here https://angular.io/docs/ts/latest/guide/ngmodule.html#!#core-for-root
I had a similar problem, which in my case was being caused by the click event being wired to a button element, but in Chrome the entire form was being submitted every time the button was clicked, because CHrome's default action is to treat a button click as a submit if there is no type attribute on the button.
The fix was to add the tag type="button" to the login button in the html
Description here
Dependencies are singletons within the scope of an injector.
However, Angular DI is a hierarchical injection system, which means that nested injectors can create their own service instances. For more information, see Hierarchical Injectors.
Source
Just double check where you provide
your service.
List your modules and inspect providers
section in each.
If there are more than one instance - each module will provide its own instance of service.
I had a same issue and found I add AuthService
to AppModule and forget to remove it from AuthModule, so login page(in the auth module) had other instance of it.
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