📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.
✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.
🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.
▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Full code on GitHub at https://github.com/RameshMF/angular8-springboot-basic-auth-login-logout
Source Code on GitHub
Get the source code of this tutorial on my GitHub Repository.Server Side - Security implementation in Spring boot application
Add spring-boot-starter-security Dependency
<?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>
Default Security Setup
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
c8be15de-4488-4490-9dc6-fab3f91435c6
Default username - user
Default password -
c8be15de-4488-4490-9dc6-fab3f91435c6
Configure standard user and password
spring.security.user.name=javaguides
spring.security.user.password=password
Configure WebSecurityConfigurerAdapter
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();
}
}
Define AuthenticationBean and BasicAuthController
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);
}
}
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");
}
}
Testing the above Security Implementation using Postman Rest Client
Frontend Side - Basic Login and Logout implementation in Angular 8 Application
Login Authentication Implementation
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)
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)
LoginComponent
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;
});
}
}
Login HTML Template
<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>
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 { }
AuthenticationService
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
}
}
Add and Configure 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);
}
}
}
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 { }
Logout Implementation
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)
Add Logout Button to Menu Template
<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>
Update MenuComponent
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();
}
}
Update 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 { }
Demo
Get the source code of this tutorial on my GitHub Repository.
The 'spring-boot-starter-test' artifact has 1000's of dependencies like couchbase, cassandra, elastic search, mongodb etc ... which are not at all required in app ...
ReplyDeleteCan you remove those and just put the required dependencies instead ?
Hello! After refresh page the logged in user is remove. How can i save authorization data and get it after refresh with out login again?
ReplyDeleteHi, Did you find the solution? Same problem here. The problem is from back end.
Deletesame problem
Deleteits not the backend, its the front end.
DeleteYou are only saving the username and password as properties in the auth service not in the session.
You want to be saving the token in the session and then using the token in the interceptor instead of calling the username and password from the service.
1. in the authenicationService method:
let basicAuthToken = this.createBasicAuthToken(username, password)
2. Save it to the session in registerSuccessfulLogin(basicAuthToken):
sessionStorage.setItem(this.SESSION_TOKEN, basicAuthToken);
3. Use the token from the session in the interceptor:
'Authorization': sessionStorage.getItem(this.SESSION_TOKEN)
I am trying to make a call to the database and validate the user instead of properties file.
ReplyDeleteHow can I, and I want to know how the username and password is reading from properties file they didn't called application.properties file anywhere
Spring boot internally process this application.properties file so we no need to manually call and process it. You can this tutorial to validate username and password with database at https://www.javaguides.net/2019/10/spring-security-hibernate-database-authentication-example.html
Deletein the current example is there any chance to stop the spring security.. just I want to authenticate from my db call
DeleteThank you for your tutorial.I followed above task and when i was trying to login i had following error.
ReplyDelete"Access to XMLHttpRequest at 'http://localhost:8080/api/v1/basicauth' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource".
Can you please tell me any solution for that?
Did you find a solution? Having the same issue
DeleteAdd cors() to the configure method in SpringSecurityConfig. For example:
Delete@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().
disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.and()
.cors();
}
Goto the c drive where you have kept the chrome and run below command inside the application folder example : C:\Program Files (x86)\Google\Chrome\Application
Deleterun below command:-
chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
this should solve the problem