Login and signup example in Angular
Tags: angular, angular11, angularlogin
Published: 2021-03-12 08:30:31

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.
```javascript
  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 
```javascript
  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.
```javascript
  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` <br/>
 `cd  new login-in-angular`<br/>
 `npm start`<br/>
 
### Lets build a login application

 install the cookie package
 `npm i ngx-cookie-service`
 
### 1. Create the login component

```javascript
//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
        )
      }    
    }
  }
```

```html
<!-- 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
```javascript
  // 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
 ```javascript
 // 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](https://admiring-ardinghelli-c7c662.netlify.app/)  and can get the code from the [Github repo](https://github.com/akshay-s-770/login-in-angular)