I'm building a simple login page with authentication using Angular and Express. I have the following:
- a login component
- a service that makes http calls and sets the local storage with the received jwt token
- a route guard for registration page
My guard is working in that it prevents access to the '/registration' route if there is no token. Because the very first login does not have a token, and the guard seems to check before the token is set when the login component's onSubmit() is invoked, I have to trigger onSubmit() twice - once to get the key and then another to login. I'd like to be able to login immediately after entering the correct credentials.
How do I resolve this? Thanks in advance!
login-component.ts
...
this.loginForm = this.fb.group({
username: ['', Validators.required],
password: ['', Validators.required]
})
...
onSubmit() {
const formValue = this.loginForm.value;
if (formValue.username && formValue.password) {
this.authService.login(formValue.username, formValue.password)
.subscribe(
resp => { console.log(resp); },
err => { console.log(err); }
)
this.router.navigateByUrl('/registration');
}
}
auth-service.service.ts:
export class AuthSerivce {
constructor(private http: HttpClient) {}
login(username: string, password: string) {
const body = {
username: username,
password: password
}
return this.http.post<AuthResp>(ROUTES.login, body)
.pipe(
tap(res => this.setSession(res)),
catchError(this.handleError),
shareReplay()
)
}
...
private setSession(authResp: AuthResp) {
const expiresAt = moment().add(authResp.expiresIn, 'second');
localStorage.setItem('id_token', authResp.token);
localStorage.setItem("expires_at", JSON.stringify(expiresAt.valueOf()));
}
public isLoggedIn() {
return moment().isBefore(this.getExpiration());
}
public getExpiration() {
const expiration = localStorage.getItem("expires_at");
const expiresAt = JSON.parse(expiration);
return moment(expiresAt);
}
}
auth.guard.ts
export class AuthGuard implements CanActivate {
constructor(
private _authService: AuthService,
private _router: Router) { }
canActivate(): boolean {
if (this._authService.isLoggedIn()) {
return true;
} else {
this._router.navigate(['login']);
return false;
}
}
}