Spring Boot JWT Security-Mr - RAGHU Spring Boot Application: Raghu Sir (Naresh I Technologies, Ameerpet, Hyderabad)
Spring Boot JWT Security-Mr - RAGHU Spring Boot Application: Raghu Sir (Naresh I Technologies, Ameerpet, Hyderabad)
server.servlet.context-path=/api
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/bootdb
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
raghu.app.jwtSecret=NITRAGHU
raghu.app.jwtExpTimeInMs=88800000
b. Setup SQLs
create database bootdb;
use bootdb;
insert into roles_tab(name) values('ROLE_USER');
insert into roles_tab(name) values('ROLE_MODERATOR');
insert into roles_tab(name) values('ROLE_ADMIN');
import javax.validation.constraints.NotBlank;
import lombok.Data;
1|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@Data
public class LoginRequest {
@NotBlank
private String username;
@NotBlank
private String password;
}
package in.nareshit.raghu.request;
import java.util.Set;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Data;
@Data
public class SignupRequest {
@NotBlank
@Size(min = 3, max = 20)
private String username;
@NotBlank
@Size(max=50)
@Email
private String email;
@NotBlank
@Size(min = 4, max = 40)
private String password;
2|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
package in.nareshit.raghu.response;
import java.util.Set;
import lombok.Data;
import lombok.NonNull;
@Data
public class JwtResponse {
@NonNull
private String token;
@NonNull
private Long id;
@NonNull
private String username;
@NonNull
private String email;
@NonNull
private Set<String> roles;
}
package in.nareshit.raghu.response;
import lombok.AllArgsConstructor;
import lombok.Data;
3|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@Data
@AllArgsConstructor
public class MessageResponse {
d. Models
package in.nareshit.raghu.model;
package in.nareshit.raghu.model;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
@Data
@Entity
@Table(name="roles_tab")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Enumerated(EnumType.STRING)
private ERole name;
4|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
package in.nareshit.raghu.model;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@Entity
@Table(
name="users_tab",
uniqueConstraints = {
@UniqueConstraint(columnNames = "username"),
@UniqueConstraint(columnNames = "email")
})
public class User {
@Id
5|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(max=20)
@NonNull
private String username;
@NotBlank
@Size(max=50)
@Email
@NonNull
private String email;
@NotBlank
@Size(max=120)
@NonNull
private String password;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name="users_roles_tab",
joinColumns = @JoinColumn(name="user_id"),
inverseJoinColumns = @JoinColumn(name="role_id")
)
private Set<Role> roles;
package in.nareshit.raghu.model;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import
org.springframework.security.core.authority.SimpleGrantedAuthori
ty;
6|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import
org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class UserDetailsImpl implements UserDetails {
@JsonIgnore
private String password;
7|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
return authorities;
}
e. Repository Interfaces
package in.nareshit.raghu.repo;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import in.nareshit.raghu.model.ERole;
8|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import in.nareshit.raghu.model.Role;
package in.nareshit.raghu.repo;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import in.nareshit.raghu.model.User;
f. Utils
package in.nareshit.raghu.util;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import in.nareshit.raghu.model.ERole;
import in.nareshit.raghu.model.Role;
import in.nareshit.raghu.repo.RoleRepository;
@Component
9|Page
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
public class RolesUtils {
@Autowired
private RoleRepository repository;
case "mod":
Role modRole =
repository.findByName(ERole.ROLE_MODERATOR)
.orElseThrow(()->new
RuntimeException("Error: Role is not found"));
dbRoles.add(modRole);
break;
default:
Role userRole =
repository.findByName(ERole.ROLE_USER)
.orElseThrow(()->new
RuntimeException("Error: Role is not found"));
dbRoles.add(userRole);
10 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
break;
}
});
}
}
}
package in.nareshit.raghu.util;
import java.util.Date;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import in.nareshit.raghu.model.UserDetailsImpl;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@Component
public class JwtUtils {
@Value("${raghu.app.jwtSecret}")
private String jwtSecret;
@Value("${raghu.app.jwtExpTimeInMs}")
private int jwtExpTimeInMs;
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
11 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
.setExpiration(new
Date(System.currentTimeMillis() + jwtExpTimeInMs))
.signWith(SignatureAlgorithm.HS512,
jwtSecret)
.compact()
;
}
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token
);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
g. UserDetailsServiceImpl
package in.nareshit.raghu.service;
import org.springframework.beans.factory.annotation.Autowired;
12 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import
org.springframework.security.core.userdetails.UserDetails;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.core.userdetails.UsernameNotFoundEx
ception;
import org.springframework.stereotype.Service;
import in.nareshit.raghu.model.User;
import in.nareshit.raghu.model.UserDetailsImpl;
import in.nareshit.raghu.repo.UserRepository;
@Service
public class UserDetailsServiceImpl implements
UserDetailsService {
@Autowired
private UserRepository repository;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException
{
//loading model class user object
User user = repository.findByUsername(username)
.orElseThrow(()->new
UsernameNotFoundException("User not exist" + username));
//converting into Spring Security User object
return UserDetailsImpl.build(user);
}
import java.io.IOException;
13 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import
org.springframework.security.core.AuthenticationException;
import
org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
/**
* Logic is executed if login(JWT) failed
*/
@Component
public class AuthenticationEntryPointJwt implements
AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws
IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized");
i. RestControllers
package in.nareshit.raghu.rest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
14 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@RestController
@RequestMapping("/home")
public class HomeRestController {
@GetMapping("/all")
public String allowAll() {
return "Permit All Data!";
}
@GetMapping("/user")
public String userData() {
return "User Data!";
}
@GetMapping("/mod")
public String moderatorData() {
return "Moderator Data!";
}
@GetMapping("/admin")
public String adminData() {
return "Admin Data!";
}
package in.nareshit.raghu.rest;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
15 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import
org.springframework.security.authentication.AuthenticationManage
r;
import
org.springframework.security.authentication.UsernamePasswordAuth
enticationToken;
import org.springframework.security.core.Authentication;
import
org.springframework.security.core.context.SecurityContextHolder;
import
org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import in.nareshit.raghu.model.Role;
import in.nareshit.raghu.model.User;
import in.nareshit.raghu.model.UserDetailsImpl;
import in.nareshit.raghu.repo.UserRepository;
import in.nareshit.raghu.request.LoginRequest;
import in.nareshit.raghu.request.SignupRequest;
import in.nareshit.raghu.response.JwtResponse;
import in.nareshit.raghu.response.MessageResponse;
import in.nareshit.raghu.util.JwtUtils;
import in.nareshit.raghu.util.RolesUtils;
@RestController
@RequestMapping("/auth")
public class AuthenticationRestController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserRepository userRepository;
16 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@Autowired
private RolesUtils rolesUtils;
@Autowired
private PasswordEncoder encoder;
//login
@PostMapping("/login")
public ResponseEntity<?> authenticateUser(
@Valid @RequestBody LoginRequest loginRequest
)
{
// set as SecurityContext(Authentication)
SecurityContextHolder.getContext().setAuthentication(authen
tication);
// return response
return ResponseEntity.ok(
new JwtResponse(
jwt, //token
userDetails.getId(), //id
17 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
userDetails.getUsername(),
//username
userDetails.getEmail(), //email
userDetails.getAuthorities()
.stream()
.map(auth->auth.getAuthority())
.collect(Collectors.toSet())
//Set<String>
)
);
}
//register
@PostMapping("/register")
public ResponseEntity<?> createUser(
@Valid @RequestBody SignupRequest signupRequest
)
{
// check username exist
if(userRepository.existsByUsername(signupRequest.getUsernam
e())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error :
Username already exist"));
}
//check email exist
if(userRepository.existsByEmail(signupRequest.getEmail()))
{
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error :
EmailId already exist"));
}
//create user
User user = new User(
18 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
signupRequest.getUsername(),
signupRequest.getEmail(),
encoder.encode(signupRequest.getPassword())
);
//roles given by UI
Set<String> usrRoles = signupRequest.getRole();
//roles need to be stored in DB
Set<Role> dbRoles = new HashSet<>();
rolesUtils.mapRoles(usrRoles, dbRoles);
user.setRoles(dbRoles);
userRepository.save(user);
j. Security Filter
package in.nareshit.raghu.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.security.authentication.UsernamePasswordAuth
enticationToken;
19 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import
org.springframework.security.core.context.SecurityContextHolder;
import
org.springframework.security.core.userdetails.UserDetails;
import
org.springframework.security.web.authentication.WebAuthenticatio
nDetailsSource;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import in.nareshit.raghu.service.UserDetailsServiceImpl;
import in.nareshit.raghu.util.JwtUtils;
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsServiceImpl userDetailsService;
20 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
null,
userDetails.getAuthorities()
);
authentication.setDetails(new
WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authen
tication);
}
} catch (Exception e) {
e.printStackTrace();
}
filterChain.doFilter(request, response);
k. Security Config
package in.nareshit.raghu.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import
org.springframework.security.authentication.AuthenticationManage
r;
21 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import
org.springframework.security.config.annotation.authentication.bu
ilders.AuthenticationManagerBuilder;
import
org.springframework.security.config.annotation.web.builders.Http
Security;
import
org.springframework.security.config.annotation.web.configuration
.EnableWebSecurity;
import
org.springframework.security.config.annotation.web.configuration
.WebSecurityConfigurerAdapter;
import
org.springframework.security.config.http.SessionCreationPolicy;
import
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
;
import
org.springframework.security.crypto.password.PasswordEncoder;
import
org.springframework.security.web.AuthenticationEntryPoint;
import
org.springframework.security.web.authentication.UsernamePassword
AuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import
org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import in.nareshit.raghu.filter.SecurityFilter;
import in.nareshit.raghu.service.UserDetailsServiceImpl;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private UserDetailsServiceImpl userDetailsService;
22 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
@Bean
public SecurityFilter securityFilter() {
return new SecurityFilter();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean()
throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
.antMatchers("/home/mod").hasAuthority("ROLE_MODERATOR")
.antMatchers("/home/admin").hasAuthority("ROLE_ADMIN")
.anyRequest().authenticated()
.and()
23 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
;
http.addFilterBefore(securityFilter(),
UsernamePasswordAuthenticationFilter.class);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",
new
CorsConfiguration().applyPermitDefaultValues());
return source;
}
Angular Application
ng new angular-spring-jwt
24 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
ng g s services/authentication --skipTests=true
ng g s services/token-storage --skipTests=true
ng g s services/user --skipTests=true
ng g c pages/login-page --skipTests=true
ng g c pages/register-page --skipTests=true
ng g c pages/home-page --skipTests=true
ng g c pages/profile-page --skipTests=true
ng g c pages/admin-page --skipTests=true
ng g c pages/moderator-page --skipTests=true
ng g c pages/user-page --skipTests=true
a. models
export class UserModel {
constructor(
public username: String,
public email: String,
public password: String
) {
}
}
constructor(public message:string) {
}
}
25 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
}
constructor(
public token:string,
public type:string,
public id:number,
public username:string,
public email:string,
public roles:string[])
{
}
}
B. SERVICES
AuthenticationService.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { JwtModel } from '../models/jwt-model';
import { LoginModel } from '../models/login-model';
import { MessageModel } from '../models/message-model';
26 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import { UserModel } from '../models/user-model';
@Injectable({
providedIn: 'root',
})
export class AuthenticationService {
constructor(private http: HttpClient) {}
// register
registerUser(user: UserModel): Observable<MessageModel> {
return this.http.post<MessageModel>(`${baseUrl}/register`, u
ser);
}
// login
loginUser(login: LoginModel): Observable<JwtModel> {
return this.http.post<JwtModel>(`${baseUrl}/login`, login);
}
}
UserService.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class UserService {
27 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
constructor(private http: HttpClient) {}
getPublicContent(): Observable<any> {
return this.http.get(baseUrl + '/all', { responseType: 'text
' });
}
getUserData(): Observable<any> {
return this.http.get(baseUrl + '/user', { responseType: 'tex
t' });
}
getModeratorData(): Observable<any> {
return this.http.get(baseUrl + '/mod', { responseType: 'text
' });
}
getAdminData(): Observable<any> {
return this.http.get(baseUrl + '/admin', { responseType: 'te
xt' });
}
}
TokenStorageService.ts
@Injectable({
providedIn: 'root',
})
export class TokenStorageService {
28 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
constructor() {}
signOut(): void {
window.sessionStorage.clear();
}
return {};
}
}
C. PAGES
RegisterPageComponent.ts
29 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import { Component, OnInit } from '@angular/core';
import { UserModel } from 'src/app/models/user-model';
import { AuthenticationService } from 'src/app/services/authenti
cation.service';
@Component({
selector: 'app-register-page',
templateUrl: './register-page.component.html',
styleUrls: ['./register-page.component.css']
})
export class RegisterPageComponent implements OnInit {
ngOnInit(): void {
}
onSubmit() {
this.auth.registerUser(this.user).subscribe(
data => {
console.log(data);
this.isSuccessful = true;
this.message = data.message;
}, err => {
console.log(err);
this.isSuccessful = false;
this.message = err.error.message;
});
}
30 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
RegisterPageComponent.html
31 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
Username must be at most 20 characters
</div>
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input
type="email"
class="form-control"
name="email"
[(ngModel)]="user.email"
required
email
#email="ngModel"
/>
<div
class="alert-danger"
*ngIf="email.invalid && (email.touched || registerForm.sub
mitted)"
>
<div *ngIf="email.errors?.required">Email is required</div
>
<div *ngIf="email.errors?.email">Email must be a valid ema
il address</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
class="form-control"
name="password"
32 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
[(ngModel)]="user.password"
required
minlength="6"
#password="ngModel"
/>
<div
class="alert-danger"
*ngIf="password.invalid && (password.touched || registerFo
rm.submitted)"
>
<div *ngIf="password.errors?.required">Password is require
d</div>
<div *ngIf="password.errors?.minlength">
Password must be at least 6 characters
</div>
</div>
</div>
<div class="form-group">
<button [disabled]="!registerForm.form.valid" class="btn btn
-success btn-block">Sign Up</button>
</div>
<div
class="alert alert-warning"
*ngIf="registerForm.submitted && !isSuccessful && message !=
''"
>
{{ message }}
</div>
</form>
33 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
</div>
LoginPageComponent.ts
@Component({
selector: 'app-login-page',
templateUrl: './login-page.component.html',
styleUrls: ['./login-page.component.css'],
})
export class LoginPageComponent implements OnInit {
//------variables----------------------
isLoggedIn = false;
isLoginFailed = false;
errorMessage = '';
roles: string[] = [];
loginModel : LoginModel = new LoginModel('','');
//---------DI-------------------
constructor(
private authService: AuthenticationService,
private tokenStorage: TokenStorageService
) {}
//---------OnInit-------------------
ngOnInit(): void {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
34 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
}
onSubmit(): void {
this.authService.loginUser(this.loginModel).subscribe(
data => {
this.tokenStorage.saveToken(data.token);
this.tokenStorage.saveUser(data);
this.isLoginFailed = false;
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
this.reloadPage();
},
err => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
}
);
}
reloadPage(): void {
window.location.reload();
}
}
LoginPageComponent.html
<h3>User Login Form</h3>
<form
*ngIf="!isLoggedIn"
name="form"
(ngSubmit)="loginForm.form.valid && onSubmit()"
#loginForm="ngForm"
35 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
>
<div class="form-group">
<label for="username">Username</label>
<input
type="text"
class="form-control"
name="username"
[(ngModel)]="loginModel.username"
required
#username="ngModel"
/>
<div
class="alert alert-danger"
role="alert"
*ngIf="username.errors && (username.touched || loginForm.s
ubmitted)"
>
Username is required!
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input
type="password"
class="form-control"
name="password"
[(ngModel)]="loginModel.password"
required
minlength="6"
#password="ngModel"
/>
<div
class="alert alert-danger"
role="alert"
36 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
*ngIf="password.errors && (password.touched || loginForm.s
ubmitted)"
>
<div *ngIf="password.errors.required">Password is required
</div>
<div *ngIf="password.errors.minlength">
Password must be at least 6 characters
</div>
</div>
</div>
<div class="form-group">
<button [disabled]="!loginForm.form.valid" class="btn btn-
success btn-block">Login</button>
</div>
<div class="form-group">
<div
class="alert alert-danger"
role="alert"
*ngIf="loginForm.submitted && isLoginFailed"
>
Login failed: {{ errorMessage }}
</div>
</div>
</form>
HomePageComponent.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from 'src/app/services/user.service';
@Component({
37 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css'],
})
export class HomePageComponent implements OnInit {
content?: string;
ngOnInit(): void {
this.userService.getPublicContent().subscribe(
(data) => {
this.content = data;
},
(err) => {
console.log(err);
}
);
}
}
HomePageComponent.html
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>
ProfilePageComponent.ts
38 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@Component({
selector: 'app-profile-page',
templateUrl: './profile-page.component.html',
styleUrls: ['./profile-page.component.css']
})
export class ProfilePageComponent implements OnInit {
currentUser: any;
ngOnInit(): void {
this.currentUser = this.token.getUser();
}
ProfilePageComponent.html
<div class="container" *ngIf="currentUser; else loggedOut">
<header class="jumbotron">
<h3>
<strong>{{ currentUser.username }}</strong> Profile
</h3>
</header>
<p>
<strong>Token:</strong>
{{ currentUser.token.substring(0, 20) }} ...
{{ currentUser.token.substr(currentUser.token.length -
20) }}
</p>
<p>
<strong>Email:</strong>
{{ currentUser.email }}
</p>
39 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
<strong>Roles:</strong>
<ul>
<li *ngFor="let role of currentUser.roles">
{{ role }}
</li>
</ul>
</div>
UserPageComponent.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from 'src/app/services/user.service';
@Component({
selector: 'app-user-page',
templateUrl: './user-page.component.html',
styleUrls: ['./user-page.component.css']
})
export class UserPageComponent implements OnInit {
content?: string;
ngOnInit(): void {
this.userService.getUserData().subscribe(
data => {
this.content = data;
},
err => {
console.log(err);
}
);
40 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
UserPageComponent.ts
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>
AdminPageComponent.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from 'src/app/services/user.service';
@Component({
selector: 'app-admin-page',
templateUrl: './admin-page.component.html',
styleUrls: ['./admin-page.component.css'],
})
export class AdminPageComponent implements OnInit {
content?: string;
ngOnInit(): void {
this.userService.getAdminData().subscribe(
(data) => {
this.content = data;
},
(err) => {
console.log(err);
41 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
}
);
}
}
AdminPageComponent.html
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>
ModeratorPageComponent.ts
@Component({
selector: 'app-moderator-page',
templateUrl: './moderator-page.component.html',
styleUrls: ['./moderator-page.component.css']
})
export class ModeratorPageComponent implements OnInit {
content?: string;
ngOnInit(): void {
this.userService.getModeratorData().subscribe(
data => {
this.content = data;
},
err => {
42 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
console.log(err);
}
);
}
ModeratorPageComponent.html
<div class="container">
<header class="jumbotron">
<p>{{ content }}</p>
</header>
</div>
d. Security Interceptor
AuthInterceptor.ts
43 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
//inject token service
constructor(private tokenService: TokenStorageService) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
let authReq = request;
const token = this.tokenService.getToken();
if (token != null) {
authReq = request.clone({
headers: request.headers.set(TOKEN_HEADER_KEY, 'Bearer '
+ token),
});
}
return next.handle(authReq);
}
}
AppRouting.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AdminPageComponent } from './pages/admin-page/admin-
page.component';
import { HomePageComponent } from './pages/home-page/home-
page.component';
44 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import { LoginPageComponent } from './pages/login-page/login-
page.component';
import { ModeratorPageComponent } from './pages/moderator-
page/moderator-page.component';
import { ProfilePageComponent } from './pages/profile-
page/profile-page.component';
import { RegisterPageComponent } from './pages/register-
page/register-page.component';
import { UserPageComponent } from './pages/user-page/user-
page.component';
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
AppComponent.html
<div id="app">
<nav class="navbar navbar-expand navbar navbar-dark bg-
primary">
<a href="#" class="navbar-brand">NareshIT</a>
<ul class="navbar-nav mr-auto" routerLinkActive="active">
45 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
<li class="nav-item">
<a href="/home" class="nav-link text-
white" routerLink="home">Home </a>
</li>
<li class="nav-item" *ngIf="showAdminPage">
<a href="/admin" class="nav-link text-
white" routerLink="admin">Admin</a>
</li>
<li class="nav-item" *ngIf="showModeratorPage">
<a href="/mod" class="nav-link text-
white" routerLink="mod">Moderator</a>
</li>
<li class="nav-item">
<a href="/user" class="nav-link text-
white" *ngIf="isLoggedIn" routerLink="user">User</a>
</li>
</ul>
46 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
<li class="nav-item">
<a href class="nav-link text-
white" (click)="logout()">LogOut</a>
</li>
</ul>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
</div>
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
private roles: string[] = [];
isLoggedIn = false;
showAdminPage = false;
showModeratorPage = false;
username?: string;
ngOnInit(): void {
this.isLoggedIn = !!this.tokenStorageService.getToken();
47 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
if (this.isLoggedIn) {
const user = this.tokenStorageService.getUser();
this.roles = user.roles;
this.showAdminPage = this.roles.includes('ROLE_ADMIN');
this.showModeratorPage = this.roles.includes('ROLE_MODERAT
OR');
this.username = user.username;
}
}
logout(): void {
this.tokenStorageService.signOut();
window.location.reload();
}
}
48 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
import { ModeratorPageComponent } from './pages/moderator-
page/moderator-page.component';
import { UserPageComponent } from './pages/user-page/user-
page.component';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { authInterceptorProviders } from './security/auth.interc
eptor';
@NgModule({
declarations: [
AppComponent,
LoginPageComponent,
RegisterPageComponent,
HomePageComponent,
ProfilePageComponent,
AdminPageComponent,
ModeratorPageComponent,
UserPageComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule
],
providers: [authInterceptorProviders],
bootstrap: [AppComponent]
})
export class AppModule { }
index.html
<!doctype html>
49 | P a g e
RAGHU SIR [NARESH i TECHNOLOGIES, AMEERPET, HYDERABAD]
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angularjwtapp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-
scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/b
ootstrap/4.0.0/css/bootstrap.min.css"
>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/
1.12.9/umd/popper.min.js"
crossorigin></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/j
s/bootstrap.min.js"
> </script>
</head>
<body>
<div class="container">
<app-root></app-root>
</div>
</body>
</html>
50 | P a g e