Angular 6 login with Session Authentication & Reactive Form Validation

Angular 6 login with Session Authentication & Reactive Form Validation

ng new project
ng g component login
ng g component dashboard
ng g service auth
ng g interface login
ng g guard auth

login.ts (interface)

export class ILogin {
    userid: string;
    password: string;
}

app.module.ts

import AuthGuard and router module in app.module.ts. configure routes using const appRoutes and import appRoutes using RouterModule.forRoot(appRoutes). forRoot creates a module that contains all the directives, the given routes, and the router service itself. canActivate : [AuthGuard] is useful when we want to check something before a component gets used : checking if an user is authenticated. That's why i have declared in dashboard route section. After checking user , we will give permission to enter dashboard.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth.guard';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { DashboardComponent } from './dashboard/dashboard.component';


const appRoutes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
];

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    DashboardComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [AuthGuard],
  bootstrap: [AppComponent]
})
export class AppModule { }
 
  

app.component.html

routerlink="/login" sets the url. routerLinkActive adds class active which menu is selected. The <router-outlet> tells the router where to display routed views.

<!--The content below is only a placeholder and can be replaced.-->
<div class="container">
 
  <!-- Static navbar -->
  <nav class="navbar navbar-inverse">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li routerLinkActive="active"><a routerLink="/login">Login</a></li>
            <li routerLinkActive="active"><a routerLink="/dashboard">Dashboard</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div><!--/.container-fluid -->
    </nav>

 <router-outlet></router-outlet>
</div>
 
  

login.component.html

Reactive form is being used for validation using [formGroup].

<div class="container">
    <div class="col-md-6 col-md-offset-3 loginBox">
        <h3>Log In</h3>
        <p *ngIf="message" class="text-center error">{{message}}</p>
      <form [formGroup]="loginForm" (ngSubmit)="login()">
          <div class="form-group clearfix" [ngClass]="{ 'has-error': submitted && f.userid.errors }">
              <label for="userid" class="col-md-3 col-sm-5 col-xs-12">Userid</label>
              <div class="col-md-9 col-sm-7 col-xs-12">
                  <input type="text" class="form-control" formControlName="userid" />
                  <div *ngIf="submitted && f.userid.errors" class="help-block">
                        <div *ngIf="f.userid.errors.required">Userid is required</div>
                  </div>
              </div>
          </div>
          <div class="form-group clearfix" [ngClass]="{ 'has-error': submitted && f.password.errors }">
            <label for="password" class="col-md-3 col-sm-5 col-xs-12">Password</label>
            <div class="col-md-9 col-sm-7 col-xs-12">
                <input type="password" class="form-control" formControlName="password"/>
                <div *ngIf="submitted && f.password.errors" class="help-block">
                        <div *ngIf="f.password.errors.required">Password is required</div>
                </div>
            </div>
          </div>
          <div class="col-xs-12 form-group text-right">
            <button class="btn btn-success" type="submit">Login</button>
          </div>
      </form>
    </div>
</div>
 
  

login.component.ts

formBuilder is used for reactive form and have to initialized in ngOnInit() function for validation. login() function is written in this component. this.f.userid.value is used for userid filed data after submitting login form and check the value with this.model.userid (admin). If both userid and password are match of model with the form fields then isLoggedIn variable will be true, create session of token with userid and navigate to the url "/dashboard".

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { ILogin } from '../login';
import { AuthService } from '../auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  model: ILogin = { userid: "admin", password: "admin123" };
  loginForm: FormGroup;
  message: string;
  returnUrl: string;

  constructor(private formBuilder: FormBuilder,private router: Router, public authService: AuthService) { }

  ngOnInit() {
    this.loginForm = this.formBuilder.group({
      userid: ['', Validators.required],
      password: ['', Validators.required]
    });
    this.returnUrl = '/dashboard';
    this.authService.logout();
  }

  // convenience getter for easy access to form fields
  get f() { return this.loginForm.controls; }

  
  login() {

    // stop here if form is invalid
    if (this.loginForm.invalid) {
        return;
    }
    else{
      if(this.f.userid.value == this.model.userid && this.f.password.value == this.model.password){
        console.log("Login successful");
        //this.authService.authLogin(this.model);
        localStorage.setItem('isLoggedIn', "true");
        localStorage.setItem('token', this.f.userid.value);
        this.router.navigate([this.returnUrl]);
      }
      else{
        this.message = "Please check your userid and password";
      }
    }    
}

}

dashboard.component.html

<div class="container">
    <div class="col-md-6 col-md-offset-3 loginBox">
        Welcome,  {{id}}
        <a href="javascript:void(0);" (click)="logout()">Logout</a>
    </div>
</div>

dashboard.component.ts

get the value of token using localStorage.getItem and store it in "id" variable. Call authService.logout() function using logout function of dashboard cimponent.

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

  id: string;
  constructor(private router: Router,public authService: AuthService) { }

  ngOnInit() {
    this.id = localStorage.getItem('token');
  }

  logout(): void {
    console.log("Logout");
    this.authService.logout();
    this.router.navigate(['/login']);
  }

}

auth.service.ts

import { Injectable } from '@angular/core';
import { ILogin } from './login';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  constructor() { }

  logout(): void {
    localStorage.setItem('isLoggedIn', "false");
    localStorage.removeItem('token');
  } 

}

auth.guard.ts

import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable()
export class AuthGuard implements CanActivate {


    constructor(private router : Router){}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        let url: string = state.url;  
        return this.verifyLogin(url);
    }

    verifyLogin(url) : boolean{
        if(!this.isLoggedIn()){
            this.router.navigate(['/login']);
            return false;
        }
        else if(this.isLoggedIn()){
            return true;
        }
    }
    public isLoggedIn(): boolean{
        let status = false;
        if( localStorage.getItem('isLoggedIn') == "true"){
          status = true;
        }
        else{
          status = false;
        }
        return status;
    }
}
 
  

Download code : https://github.com/piyalidas10/login-Authentication-Reactive-Form

can you tell me if there is any specific reason that your created Login as class and created it as an Interface?

Thanx for the post! And what will happen on session timeout on the server side? Frontend will still have "isLoggedIn() == true", right?

Like
Reply

tanx for awsome code please help me to this error 'src/app/dashboard/dashboard.component.ts(21,22): error TS2339: Property 'logout' does not exist on type 'AuthService'.'

Like
Reply

To view or add a comment, sign in

More articles by Piyali Das

  • Accessible Bootstrap Dropdown Navigation

    The Focus Focus refers to what element in your application (such as a field, checkbox, button, or link) currently…

  • Front-end development using Gulp

    Gulp is a JavaScript toolkit which helps you in implementing multiple front end tasks during web development, it can be…

  • Angular Dynamic Context Menu

    "contextmenu" is an event like click, mouseup, mousemove, mousedown. This "contextmenu" event is typically triggered by…

    2 Comments
  • Right-click Context Menu In JavaScript

    "contextmenu" is an event like click, mouseup, mousemove, mousedown. This "contextmenu" event is typically triggered by…

  • Dynamic Height in Angular Application

    In this tutorial, i have explained how you an dynamically set height of a div of component depending on other div of…

  • Code Optimization Advantage with Example

    Dynamic Font Change non-optimize code HTML code…

  • Advantages of Angular Library in Architectural Design

    Application Strategic Design Decompose the big application into smaller libraries Smaller libraries are easily…

  • Angular Multi Application Project Creation

    If your installed Angular global version is different and you want to create different version Angular application…

    1 Comment
  • Tree shaking vs. Non tree shaking providers in Angular

    In our example we are importing and referencing our Service in the AppModule causing an explicit dependency that cannot…

  • Angular Port Change

    3 steps to change port in Angular Change in Angular.json Change in script of package.

    2 Comments

Others also viewed

Explore content categories