Angular is the most trending js frameworks for the single page App and front end development, now i am here to explain how the login/authentication functionality works in angular.
Here are some basic concepts of authentication:
How the authentication works
In angular if a use enters the email and password on the login page then the email/password should be validated from the backend server, so we should call a login API and the API will validate the passed email/password. so for calling the server we use the HTTP library
a. How to call the backend API
Here in the code, we created a login function and we are passing login form data(email and password).
this function sends a request to the server and receives the response from the server.
login(formData:any):Observable<HttpResponse<CommonResponse>>{
return this.http.post<CommonResponse>(this.endPoint+"login", formData, { observe: 'response' })
.pipe(
tap((resp: HttpResponse<CommonResponse>) => {
if(resp.headers.get('x-auth')){
this.cookieService.set("currentUser",resp.headers.get('x-auth'));
this.loginStatus.next(true);
}
return resp;
}),
catchError(this.handleError)
);
}
b. How to manage the authentication
So to manage the authentication, angular provides the route guards, by using the guard we can restrict the end-user to open the page which one we don't want to open the page without login.
After getting the response from the server, we store the token in the cookie
if(resp.headers.get('x-auth')){
this.cookieService.set("currentUser",resp.headers.get('x-auth'));
this.loginStatus.next(true);
}
Here in this code, we are checking the cookie is there or not, if there is a cookie what we have put in the login function then the user is logged in.
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.cookieService.get('currentUser')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page with the return url
this.router.navigate(['/login']);
return false;
}
Installation:
Install the Angular CLI
npm install -g @angular/cli
Create a workspace and initial application
ng new login-in-angular
cd new login-in-angular
npm start
Lets build a login application
install the cookie package
npm i ngx-cookie-service
1. Create the login component
//File location in login folder and file name login.component.ts
import { Component, OnInit } from '@angular/core';
import {FormGroup, FormControl, Validators} from '@angular/forms';
import { Router } from '@angular/router';
import { CommonResponse } from "../common/common-response";
import { ApiService } from "../auth/api.service";
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
loginForm = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required])
})
public loginError:String;
constructor(private apiService:ApiService,private router: Router) { }
ngOnInit() {
}
onSubmit(){
if(this.loginForm.valid){
this.apiService.login(this.loginForm.value)
.subscribe((data) => { console.log(data);
if(data.status === 200 && !data.body.ErrorCode){
this.router.navigate(['/dashboard']);
}else{
this.loginError = data.body.message;
}
},
error => this.loginError = error
)
}
}
}
<!-- File location in login folder and file name login.component.html -->
<div class="form-signin">
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<p *ngIf="loginError">{{loginError}}</p>
<mat-form-field>
<input matInput placeholder="Enter your email" formControlName="email" required>
<mat-error *ngIf="!loginForm.controls.email.valid">Please enter valid email id</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Enter your password" type="password" formControlName="password" required>
<mat-error *ngIf="!loginForm.controls.password.valid">Please enter password</mat-error>
</mat-form-field><br/>
<button type="submit" mat-raised-button color="warn">Login</button>
</form>
</div>
2. Create the auth service
// folder name auth and file name api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { CookieService } from 'ngx-cookie-service';
import { Observable, throwError, BehaviorSubject } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { CommonResponse } from "../common/common-response";
@Injectable({
providedIn: 'root'
})
export class ApiService {
private endPoint:string = "/api/";
loginStatus = new BehaviorSubject<boolean>(this.hasToken());
constructor(private http: HttpClient, private cookieService: CookieService, private router: Router ) {}
/**
*
* @param formData as the login form data
*/
login(formData:any):Observable<HttpResponse<CommonResponse>>{
return this.http.post<CommonResponse>(this.endPoint+"login",formData, { observe: 'response' })
.pipe(
tap((resp: HttpResponse<CommonResponse>) => {
if(resp.headers.get('x-auth')){
this.cookieService.set("currentUser",resp.headers.get('x-auth'));
this.loginStatus.next(true);
}
return resp;
}),
catchError(this.handleError)
);
}
/**
*
* @param error error
*/
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
};
logout(){
this.loginStatus.next(false);
this.cookieService.deleteAll();
this.router.navigate(['/login']);
}
/**
*
* @returns {Observable<T>}
*/
isLoggedIn() : Observable<boolean> {
return this.loginStatus.asObservable();
}
/**
* if we have token the user is loggedIn
* @returns {boolean}
*/
private hasToken() : boolean {
return this.cookieService.check('currentUser');
}
}
3. Create the auth guard
// Folder name auth and file name auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { CookieService } from 'ngx-cookie-service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private cookieService: CookieService, private router: Router) { }
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.cookieService.get('currentUser')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page with the return url
this.router.navigate(['/login']);
return false;
}
}
Demo
You can check the demo from Here and can get the code from the Github repo
Top comments (0)