Angular 9 + Spring Boot Basic Authentication - Login and Logout Example

In this tutorial:

1. We will create a Spring boot project with simple REST API

2. We will add spring security to our spring boot project to secure REST API

3. We will create an Angular 9 App

4. We will implement login and logout features in the Angular 9 App.

5. We will have a demo

6. Conclusion

Let's start creating a simple spring boot hello world application with simple REST API and then we will continue with this application to implement login, logout features.
Learn full stack app development using Spring boot and Angular 9 at
Spring Boot + Angular 9 CRUD Example Tutorial

1. Creating a Simple REST API using Spring Boot

We’ll build a service that will accept HTTP GET requests at:
http://localhost:8080/greeting
and respond with a JSON representation of a greeting:
{"id":1,"content":"Hello, World!"}
We can customize the greeting with an optional name parameter in the query string:
http://localhost:8080/greeting?name=User
The name parameter value overrides the default value of "World" and is reflected in the response:
{"id":1,"content":"Hello, User!"}

1.1. Create a Spring Boot Application

There are many ways to create a Spring Boot application. You can refer below articles to create a Spring Boot application.

1.2. Add maven dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>net.javaguides.springboot</groupId>
 <artifactId>Springboot-helloworld-application</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>Springboot-helloworld-application</name>
 <description>Demo project for Spring Boot</description>

 <parent>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>2.0.5.RELEASE</version>
     <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
     <java.version>1.8</java.version>
 </properties>

 <dependencies>
     <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
     </dependency>

     <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
     </dependency>
 </dependencies>

 <build>
     <plugins>
         <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
     </plugins>
 </build>
</project>
Note that we haven't added spring security dependency yet. We will implement spring security after developing REST API.

1.3. Greeting.java

To model the greeting representation, We create a resource representation Greeting class. Provide a plain old java object with fields, constructors, and accessors for the id and content data:
package net.javaguides.springboot.Springboothelloworldapplication;

public class Greeting {
    private final long id;
    private final String content;

    public Greeting(long id, String content) {
         this.id = id;
         this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
         return content;
    }
}
Next, we create a resource controller that will serve these greetings.

1.4. Create a resource controller - GreetingController.java

In Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. These components are easily identified by the @RestController annotation, and the GreetingController below handles GET requests for /greeting by returning a new instance of the Greeting class:
package net.javaguides.springboot.Springboothelloworldapplication;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
         return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }
}

1.5. SpringbootHelloworldApplication.java

package net.javaguides.springboot.Springboothelloworldapplication;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootHelloworldApplication {

    public static void main(String[] args) {
         SpringApplication.run(SpringbootHelloworldApplication.class, args);
    }
}
The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. 

1.6. Running the Application

In this article, the two ways we can start the standalone Spring boot application.
  1. From the root directory of the application and type the following command to run it -
$ mvn spring-boot:run
  1. From your IDE, run the SpringbootHelloworldApplication.main() method as a standalone Java class that will start the embedded Tomcat server on port 8080 and point the browser to http://localhost:8080/.

Test REST API

Before developing an Angular client, let's test this web service.

Now that the service is up, visit http://localhost:8080/api/v1/greeting, where you see:
Provide a name query string parameter with http://localhost:8080/greeting?name=User. Notice how the value of the content attribute changes from "Hello, World!" to "Hello User!":
Now, we will create a step by step /greeting REST API. Next, we will add Spring security to our spring boot project to secure REST API.

2. Security implementation in Spring boot application

2.1 Add spring-boot-starter-security Dependency

Spring boot made the easiest way to secure REST services by adding a very simple dependency - spring boot starter security:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
Here is the complete pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.javaguides.springboot</groupId>
    <artifactId>Springboot-helloworld-application</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Springboot-helloworld-application</name>
    <description>Demo project for Spring Boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/>
        <!-- lookup parent from repository -->
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
Once Spring Security is on the classpath, then Spring Boot automatically secures all HTTP endpoints with "basic" authentication.

2.2 Default Security Setup

Let's understand how default spring security works in spring boot application. Once we add below security starter dependency to our spring-boot project:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
This will include the SecurityAutoConfiguration class – containing the initial/default security configuration.
Simply put, by default, the Authentication gets enabled for the Application. Also, content negotiation is used to determine if basic or formLogin should be used.
When you start the spring boot project, the default password is randomly generated and printed in the console log:
 c8be15de-4488-4490-9dc6-fab3f91435c6
Default username - user
Default password - c8be15de-4488-4490-9dc6-fab3f91435c6

2.3 Configure standard user and password

We can override the default user and password using the below properties in the application.properties file:
spring.security.user.name=javaguides
spring.security.user.password=password

2.3 Configure WebSecurityConfigurerAdapter

To enable authentication and authorization support in spring boot rest APIs, we can configure a utility class WebSecurityConfigurerAdapter. It helps in requiring the user to be authenticated prior to accessing any configured URL (or all URLs) within our application.
package net.javaguides.springboot.helloworldapp.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().
        disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic();
    }
}

2.4 Define AuthenticationBean and BasicAuthController

Let's create an AuthenticationBean, which is used to return a success message to the client:
package net.javaguides.springboot.helloworldapp.bean;

public class AuthenticationBean {

    private String message;

    public AuthenticationBean(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public String toString() {
        return String.format("HelloWorldBean [message=%s]", message);
    }
}
Let's create a BasicAuthController class with /basicauth REST API for returning the authentication success message.
package net.javaguides.springboot.helloworldapp.controller;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import net.javaguides.springboot.helloworldapp.bean.AuthenticationBean;

@CrossOrigin(origins = "http://localhost:4200")
@RestController
@RequestMapping("/api/v1")
public class BasicAuthController {

    @GetMapping(path = "/basicauth")
    public AuthenticationBean basicauth() {
        return new AuthenticationBean("You are authenticated");
    }
}

2.5 Testing above Security Implementation using Postman Rest Client

3. Creating Angular 9 App

Let's develop a step by step Angular 9 app which consume below greeting Rest web service.
http://localhost:8080/api/v1/greeting
Make sure that you have installed NodeJs and NPM on your machine. Use below commands o check it's version:
C:\Angular>node -v
v10.15.3

C:\Angular>npm -v
6.9.0

3.1 Install the latest version of Angular CLI

Use below command to install or update Angular CLI:
npm install -g @angular/cli
Now, let's check the latest version of Angular CLI:
C:\angular>ng --version

3.2 Create Angular 9 Application using Angular CLI

The Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications.
If you are new to Angular CLI then check out the official documentation at https://cli.angular.io.
Let's use the below command to generate an Angular 9 app. We name this project as "angular-frontend".
ng new angular-frontend

3.3 Create Angular Service & Components

Let's auto-generate service and components using Angular CLI. Change your project directory to angular-frontend and run the following commands:
- ng g s hello-world
– ng g c hello-world
– ng g c menu
Create a modal folder and run the following command to generate Message.ts typescript class:
– ng generate class Message

3.4 Angular Project Structure

Below screenshot shows our angular project structure:

3.5 Integrate Bootstrap with Angular

Use NPM to download Bootstrap & JQueryBootstrap and jQuery will be installed into the node_modulesfolder.
npm install bootstrap jquery --save
Configure installed Bootstrap & JQuery in an angular.json file:
...
 
"styles": [
  "src/styles.css",
  "node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
  "node_modules/jquery/dist/jquery.min.js",
  "node_modules/bootstrap/dist/js/bootstrap.min.js"
]
 
...
If bootstrap.min.css won't work then import this bootstrap.min.css in a style.css file like this:
/* You can add global styles to this file, and also import other style files */
@import url(https://unpkg.com/bootstrap@4.1.0/dist/css/bootstrap.min.css)

3.6 hello-world.service.ts -> HelloWorldService

The HelloWorldService will be used to get the data from backend by calling spring boot APIs. Update the hello-world.service.ts file inside src/app directory with the following code to it -
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { MessageModel } from '../model/Message';

@Injectable({
    providedIn: 'root'
})
export class HelloWorldService {
    constructor(private http: HttpClient) {
    }
    executeHelloWorldService() {
        return this.http.get<MessageModel>('http://localhost:8080/api/v1/greeting');
    }
}

3.7 Model -> Message.ts

Let's create a Message model typescript to hold REST API response data and display on HTML template -
export class MessageModel {
    id: number;
    content: string;
    constructor(private _id: number, public message: string) {
        this.id = _id;
        this.content = message;
    }
}

3.8 hello-world.component.ts -> HelloWorldComponent 

The hello-world.component.ts defines the logic associated with HelloWorldComponent.
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { HelloWorldService } from '../service/hello-world.service';

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

  welcomeMessage = '';

  constructor(private route: ActivatedRoute,
    private router: Router, private helloWorldService: HelloWorldService) { }

  ngOnInit() {
    this.helloWorldService.executeHelloWorldService().subscribe((res) => {
      this.welcomeMessage = res.content;
    });
  }
}

3.9 hello-world.component.html -> HelloWorldComponent

The hello-world.component.html defines the HTML template associated with the HelloWorldComponent.
<div class="container">
  Message from server ->  <h1>{{this.welcomeMessage}}</h1>
</div>

3.20 menu.component.ts -> MenuComponent

The menu.component.ts file defines the logic for the menu component, named MenuComponent.
import { Component, OnInit } from '@angular/core';

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

  welcomeMessage = 'Test';

  constructor() { }

  ngOnInit() {

  }
}

3.11 menu.component.html -> MenuComponent

The menu.component.html defines the HTML template associated with the MenuComponent.
<header>
  <nav class="navbar navbar-expand-md navbar-dark bg-dark">
      <div><a href="https://www.javaguides.net" class="navbar-brand">JavaGuides</a></div>
      <ul class="navbar-nav">
          <li><a class="nav-link" href="/hello-world">Hello World Tab</a></li>
      </ul>
  </nav>
</header>

3.12 app.module.ts -> AppModule

Every application has at least one Angular module, the root module that you bootstrap to launch the application. By convention, it is usually called AppModule. Here is the code for AppModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HelloWorldService } from './service/hello-world.service';
import { MenuComponent } from './menu/menu.component';
import { HelloWorldComponent } from './hello-world/hello-world.component';

@NgModule({
  declarations: [
    AppComponent,
    MenuComponent,
    HelloWorldComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
  ],
  providers: [
    HelloWorldService,
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

3.13 app-routing.module.ts -> AppRoutingModule

The app-routing.module.ts file defines the routing configuration in AppRoutingModule for Angular app:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HelloWorldComponent } from './hello-world/hello-world.component';

const routes: Routes = [
  {path: '', component: HelloWorldComponent},
  {path: 'hello-world', component: HelloWorldComponent},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

3.14 app.component.ts -> AppComponent

The app.component.ts file defines the logic for the app's root component, named AppComponent:
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'frontend-spring-boot-angular-hello-world-example';
}

3.15 app.component.html -> AppComponent

The app.component.html file defines the HTML template associated with the root AppComponent.
<app-menu></app-menu>
<router-outlet></router-outlet>

3.16 Running Angular 9 Application

Let's run the above developed Angular App with a command:
ng serve
By default, the Angular app runs on 4200 port but you can change default port with the following command:
ng serve --port 4204

Hit http://localhost:4200/ link in the browser will open below page on the screen.

4. Adding Basic Login and Logout implementation in Angular 9 Application

4.1 Login Authentication Implementation

Let's create a login component with the following command:
C:\angular-frontend\src\app> ng g c login
CREATE src/app/login/login.component.html (20 bytes)
CREATE src/app/login/login.component.spec.ts (621 bytes)
CREATE src/app/login/login.component.ts (265 bytes)
CREATE src/app/login/login.component.css (0 bytes)
UPDATE src/app/app.module.ts (724 bytes)
Let's create an Angular auth service with the following command:
PS C:\angular-frontend\src\app> ng g s /login/auth
CREATE src/app/login/auth.service.spec.ts (323 bytes)
CREATE src/app/login/auth.service.ts (133 bytes)
Let's understand each file generated above and implement the login feature.

4.2 LoginComponent

Open LoginComponent file and add the following code to it -
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { AuthenticationService } from './auth.service';

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

  username: string;
  password : string;
  errorMessage = 'Invalid Credentials';
  successMessage: string;
  invalidLogin = false;
  loginSuccess = false;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private authenticationService: AuthenticationService) {   }

  ngOnInit() {
  }

  handleLogin() {
    this.authenticationService.authenticationService(this.username, this.password).subscribe((result)=> {
      this.invalidLogin = false;
      this.loginSuccess = true;
      this.successMessage = 'Login Successful.';
      this.router.navigate(['/hello-world']);
    }, () => {
      this.invalidLogin = true;
      this.loginSuccess = false;
    });      
  }
}

4.3 Login HTML Template

Let's open the login.component.html file and add the following code to it -
<app-menu></app-menu>
<div class="container col-lg-6">
    <h1 class="text-center">Login</h1>
    <div class="card">
      <div class="card-body">
        <form class="form-group">
          <div class="alert alert-warning" *ngIf='invalidLogin'>{{errorMessage}}</div>
          <div class="alert alert-success" *ngIf='loginSuccess'>{{successMessage}}</div>
          <div class="form-group">
            <label for="email">User Name :</label>
            <input type="text" class="form-control" id="username" [(ngModel)]="username" placeholder="Enter User Name"
              name="username">
          </div>
          <div class="form-group">
            <label for="pwd">Password:</label>
            <input type="password" class="form-control" [(ngModel)]="password" id="password" placeholder="Enter password"
              name="password">
          </div>
          <button (click)=handleLogin() class="btn btn-success">Login</button>
        </form>
      </div>
    </div>
  </div>

Add the login path to the routing module:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HelloWorldComponent } from './hello-world/hello-world.component';
import { LoginComponent } from './login/login.component';

const routes: Routes = [
  {path: 'login', component: LoginComponent},
  {path: '', component: LoginComponent},
  {path: 'hello-world', component: HelloWorldComponent},
  {path: 'logout', component: LoginComponent},
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

export class AppRoutingModule { }

4.4 AuthenticationService

Let's create AuthenticationService class which makes a basic auth Rest API call for basic authentication. We also need to store authenticated user in sessionStorage for logout implementation. 
Let's open the auth.service.ts file and add the following content to it -
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';

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

  // BASE_PATH: 'http://localhost:8080'
  USER_NAME_SESSION_ATTRIBUTE_NAME = 'authenticatedUser'

  public username: String;
  public password: String;

  constructor(private http: HttpClient) {

  }

  authenticationService(username: String, password: String) {
    return this.http.get(`http://localhost:8080/api/v1/basicauth`,
      { headers: { authorization: this.createBasicAuthToken(username, password) } }).pipe(map((res) => {
        this.username = username;
        this.password = password;
        this.registerSuccessfulLogin(username, password);
      }));
  }

  createBasicAuthToken(username: String, password: String) {
    return 'Basic ' + window.btoa(username + ":" + password)
  }

  registerSuccessfulLogin(username, password) {
    sessionStorage.setItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME, username)
  }

  logout() {
    sessionStorage.removeItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME);
    this.username = null;
    this.password = null;
  }

  isUserLoggedIn() {
    let user = sessionStorage.getItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME)
    if (user === null) return false
    return true
  }

  getLoggedInUserName() {
    let user = sessionStorage.getItem(this.USER_NAME_SESSION_ATTRIBUTE_NAME)
    if (user === null) return ''
    return user
  }
}

4.5 Add and Configure HttpInterceptor

We will be creating a new HttpInterceptor service called BasicAuthInterceptor Service. This service will check if the session has a valid username and basicauth String, then it will update the headers of all outgoing HTTP requests. We implement the interceptor by extending the HttpInterceptor.
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { AuthenticationService } from './login/auth.service';

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {

    constructor(private authenticationService: AuthenticationService) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (this.authenticationService.isUserLoggedIn() && req.url.indexOf('basicauth') === -1) {
            const authReq = req.clone({
                headers: new HttpHeaders({
                    'Content-Type': 'application/json',
                    'Authorization': `Basic ${window.btoa(this.authenticationService.username + ":" + this.authenticationService.password)}`
                })
            });
            return next.handle(authReq);
        } else {
            return next.handle(req);
        }
    }
}
Now we will register the created HTTPInterceptor using the app.module.ts by updating it in the provider section.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HelloWorldComponent } from './hello-world/hello-world.component';
import { MenuComponent } from './menu/menu.component';
import { LoginComponent } from './login/login.component';

import { FormsModule } from '@angular/forms';
import { LogoutComponent } from './logout/logout.component';
import { HttpInterceptorService } from './httpInterceptor.service';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    HelloWorldComponent,
    MenuComponent,
    LoginComponent,
    LogoutComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpInterceptorService,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

4.6 Logout Implementation

Let's create a logout component with the following command:
C:\angular-frontend\src\app> ng g c logout
CREATE src/app/logout/logout.component.html (21 bytes)
CREATE src/app/logout/logout.component.spec.ts (628 bytes)
CREATE src/app/logout/logout.component.ts (269 bytes)
CREATE src/app/logout/logout.component.css (0 bytes)

4.7 Add Logout Button to Menu Template

In the previous tutorial, we have created a Menu Html template, and let's update it with the logout button.
<header>
    <nav class="navbar navbar-expand-md navbar-dark bg-dark">
        <div><a href="https://www.javaguides.net" class="navbar-brand">JavaGuides</a></div>
        <ul class="navbar-nav navbar-collapse justify-content-end">
            <li>
                <a *ngIf="isLoggedIn" class="nav-link" href="/logout" (click)=handleLogout()>Logout</a>
            </li>
        </ul>
    </nav>
  </header>

4.8 Update MenuComponent

Let's update MenuComponent for logout implementation. Once we will click on the logout button then the user stored in sessionStorage will be removed. 
Let's open the menu.component.ts file and add the below code to it -
import { Component, OnInit } from '@angular/core';
import { AuthenticationService } from '../login/auth.service';
import { ActivatedRoute, Router } from '@angular/router';

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

  isLoggedIn = false;

  constructor(private route: ActivatedRoute,
    private router: Router,
    private authenticationService: AuthenticationService) { }

  ngOnInit() {
    this.isLoggedIn = this.authenticationService.isUserLoggedIn();
    console.log('menu ->' + this.isLoggedIn);
  }

  handleLogout() {
    this.authenticationService.logout();
  }
}

4.9 Update Routing Module

After user logout, a user should navigate to the login screen so let's update the AppRoutingModule file as -
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HelloWorldComponent } from './hello-world/hello-world.component';
import { LoginComponent } from './login/login.component';

const routes: Routes = [
  {path: 'login', component: LoginComponent},
  {path: '', component: LoginComponent},
  {path: 'hello-world', component: HelloWorldComponent},
**  {path: 'logout', component: LoginComponent},**
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

export class AppRoutingModule { }

5. Demo


The below GIF image shows the demo of this application.
Username: javaguides
Password: password

6. Conclusion

In this tutorial:

- We created a Spring boot project

- We created a simple REST API

- We have added spring security to our spring boot project to secure REST API

- We created the Angular 9 App

- We have implemented login and logout features in the Angular App.

- Finally, we had a demo

Comments