Tutorial: “Angular 10 Spring Boot JWT Authentication Example with Angular 10 + MySQl + Spring Security – Angular 10 Spring boot Login Example”
In tutorial ‘Angular 10 + Spring Boot JWT Token Based Authentication Example’, I guide you very clearly how to implement full stack example to demonistrade an jwt token based authentication flow from frontend Angular10 to backend: SpringBoot and MySQL.
– I give you an Epic of the application, a fullstack excutive flow from frontend Angular 10 to backend jwt SpringBoot Security to database (MySQL/PostgreSQL) with overall architecture diagram.
– I give you a layer diagram of Angular Jwt Authentication application with localStorage and Angular HttpClient (plus Interceptor)
– I guide you detail-steps how to implement a security SpringBoot Jwt Token Authentication.
– I guide you step by step how to develop a Angular Jwt Authentication application.
– Finally, I do an integrative testing from Angular 10 to Jwt Based Token SpringBoot Security RestApis.
Overview Project – Angular 10 Spring Boot JWT Authentication Example
JSON Web Token – Angular Spring Boot Jwt Authentication Example
In the tutorial: ‘Angular 10 Spring Boot JWT Authentication Example’, we use JWT token based to security our website, so the question is: What is JSON Web Token, JWT?
JSON Web Token (JWT) defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
Scenarios where JSON Web Tokens are useful:
Authorization
: the most common scenario for using JWT. Single Sign On is a feature that widely uses JWTInformation Exchange
: Because JWTs can be signed, JSON Web Tokens are a good way of securely transmitting information between parties.
JSON Web Tokens consist of 3 parts:
- Header
- Payload
- Signature
-> JWT
looks like Header-Base64-String.Payload-Base64-String.Signature-Base64-String
Header consists of two parts:
- token type.
- hashing algorithm.
-> Example:
{
"alg": "HS256",
"typ": "JWT"
}
Payload contains the claims. Claims are statements about an entity and additional information.
There are 3 types of claims ->
Registered claims
-> These are a set of predefined claims: iss (issuer), exp (expiration time), sub (subject)Public claims
Private claims
Example:
{
"sub": "thomasgkz",
"iat": 1537603195,
"exp": 1537689595
}
Signature -> To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.
Example:
HMACSHA512(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
Combine all together, we get 3 Base64-URL strings separated by dots,
-> Example:
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0aG9tYXNna3oiLCJpYXQiOjE1Mzc2MDMxOTUsImV4cCI6MTUzNzY4OTU5NX0.m2YMjTYmOnfR7nnVNxqCzWbQ2FhKRe1eiizxnC2TF4eAoEzKlwo7PheVkKcxj08ST3vB-ZOIhiORvYVfSgzcog
When accessing a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema.
Example:
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0aG9tYXNna3oiLCJpYXQiOjE1Mzc2MDMxOTUsImV4cCI6MTUzNzY4OTU5NX0.m2YMjTYmOnfR7nnVNxqCzWbQ2FhKRe1eiizxnC2TF4eAoEzKlwo7PheVkKcxj08ST3vB-ZOIhiORvYVfSgzcog
Angular Spring Boot JWT Authentication example
In the tutorial “Angular 10 SpringBoot Jwt Authentication example”, We will build an application, from frontend (Angular) to backend (Spring Boot), which allows users to register, login account. This application is secured with JWT (JSON Web Token) authentication and Spring Security. Then, depending on the role of current User (user, pm or admin), this system accepts what he can access:




The diagram below show how our system handles User Registration and User Login processes:

Spring Boot back-end with Spring Security – Angular SpringBoot Jwt Authentication Example
In the tutorial “Angular 10 Springboot jwt authentication example”, This is diagram for SpringBoot Token based authentication Security/JWT classes that are separated into 3 layers:
– HTTP
– Spring Security
– REST API

– SecurityContextHolder
provides access to the SecurityContext
.
– SecurityContext
holds the Authentication
and possibly request-specific security information.
– Authentication
represents the principal which includes GrantedAuthority
that reflects the application-wide permissions granted to a principal.
– UserDetails
contains necessary information to build an Authentication
object from DAOs or other source of security data.
– UserDetailsService
helps to create a UserDetails
from a String-based username and is usually used by AuthenticationProvider
.
– JwtAuthTokenFilter
(extends OncePerRequestFilter
) pre-processes HTTP request, from Token, create Authentication
and populate it to SecurityContext
.
– JwtProvider
validates, parses token String or generates token String from UserDetails
.
– UsernamePasswordAuthenticationToken
gets username/password from login Request and combines into an instance of Authentication
interface.
– AuthenticationManager
uses DaoAuthenticationProvider
(with help of UserDetailsService & PasswordEncoder) to validate instance of UsernamePasswordAuthenticationToken, then returns a fully populated Authentication instance on successful authentication.
– SecurityContext
is established by calling SecurityContextHolder.getContext().setAuthentication(…)
with returned authentication object above.
– AuthenticationEntryPoint
handles AuthenticationException
.
– Access to Restful API is protected by HTTPSecurity
and authorized with Method Security Expressions.
Angular 10 front-end with Interceptor – Angular SpringBoot Jwt Authentication Example
In the tutorial, “Angular 10 Spring Boot JWT Authentication Example – Angular 10 Spring Boot Login Example”, we need the Angular HTTP Interceptor to add JWT Token Based for Security authentication:

– app.component
is the parent component that contains routerLink
and router-outlet
for routing. It also has an authority variable as the condition for displaying items on navigation bar.
– user.component
, pm.component
, admin.component
correspond to Angular Components for User Board, PM Board, Admin Board. Each Board uses user.service
to access authority data.
– register.component
contains User Registration form, submission of the form will call auth.service
.
– login.component
contains User Login form, submission of the form will call auth.service
and token-storage.service
.
– user.service
gets access to authority data from Server using Angular HttpClient ($http service).
– auth.service
handles authentication and signup actions with Server using Angular HttpClient ($http service).
– every HTTP request by $http service will be inspected and transformed before being sent to the Server by auth-interceptor (implements HttpInterceptor).
– auth-interceptor
check and get Token from token-storage.service to add the Token to Authorization Header of the HTTP Requests.
– token-storage.service
manages Token inside Browser’s sessionStorage.
Video Guide – Angular SpringBoot JWT Authentication Example – Angular 10 Spring Boot Login Example
Build Backend SpringBoot JWT Security RestAPIs – Angular 10 Spring Boot Login Example
- SpringBoot JWT Authentication RestAPIs
- Overview
- Generate/Validate Token
- Filter the Request
- Create AuthenticationToken from Token
- Store Authentication object in SecurityContext
- Authenticate with AuthenticationProvider
- Retrieve User details with UserDetailsService
- Protect Resources with HTTPSecurity & Method Security Expressions
- Handle AuthenticationException – AuthenticationEntryPoint
- Practice – Build Backend SpringBoot
SpringBoot JWT Authentication RestAPIs Overview
Look back to the diagram for Spring Security/JWT classes that are separated into 3 layers:
– HTTP
– Spring Security
– REST API

For more details about this Architecture, please please back to SPRING BOOT BACK-END WITH SPRING SECURITY.
SpringBoot Jwt Authentication Generate/Validate Token
In the tutorial “Angular 10 Springboot jwt authentication example”, We use a class named JwtProvider
. It gets username
from Authentication
object, then builds JWT Token with username
, Date()
object, secretKey
. JwtProvider
can also be used to validate JWT Token:
class JwtProvider {
@Value("${grokonez.app.jwtSecret}")
private String jwtSecret;
@Value("${grokonez.app.jwtExpiration}")
private int jwtExpiration;
public String generateJwtToken(Authentication authentication) {
UserPrinciple userPrincipal = (UserPrinciple) authentication.getPrincipal();
return Jwts.builder()
.setSubject((userPrincipal.getUsername()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpiration*1000))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
public boolean validateJwtToken(String authToken) {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return ...;
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser()
.setSigningKey(jwtSecret)
.parseClaimsJws(token)
.getBody().getSubject();
}
}
Spring Boot Jwt RestAPI Filter the Request
In the tutorial “Angular 10 SpringBoot Jwt Authentication Example”, We add our JwtAuthTokenFilter
(that extends Spring OncePerRequestFilter
abstract class) to the chain of filters.
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
JwtAuthTokenFilter
validates the Token using JwtProvider
:
class JwtAuthTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtProvider tokenProvider;
@Override
protected void doFilterInternal(...) {
String jwt = getJwt(request);
if (jwt!=null && tokenProvider.validateJwtToken(jwt)) {
...
}
filterChain.doFilter(request, response);
}
}
Now we have 2 cases:
– Login/SignUp: RestAPI with non-protected APIs -> authenticate Login Request with AuthenticationManager
, if error occurs, handle AuthenticationException
with AuthenticationEntryPoint
.
– With protected Resources:
+ jwt
token is null/invalid -> if Authenticated Error occurs, handle AuthenticationException
with AuthenticationEntryPoint
.
+ jwt
token is valid -> from token, get User information, then create AuthenticationToken
.
SpringBoot Create Authentication Token
JwtAuthTokenFilter
extracts username
/password
from the received token using JwtProvider
, then based on the extracted data, JwtAuthTokenFilter
:
– creates a AuthenticationToken
(that implements Authentication
)
– uses the AuthenticationToken
as Authentication
object and stores it in the SecurityContext
for future filter uses (e.g: Authorization
filters).
In this tutorial, we use UsernamePasswordAuthenticationToken
:
// extract user information
String username = tokenProvider.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// create AuthenticationToken
UsernamePasswordAuthenticationToken authentication
= new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SpringBoot Jwt Store Authentication object in SecurityContext – Angular SpringBoot Jwt Authentication Example
SecurityContextHolder.getContext().setAuthentication(authentication);
SecurityContextHolder
is the most fundamental object where we store details of the present security context of the application (includes details of the principal). Spring Security uses an Authentication
object to represent this information and we can query this Authentication
object from anywhere in our application:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// currently authenticated user
Object principal = authentication.getPrincipal();
getContext()
returns an instance of SecurityContext
interface that holds the Authentication
and possibly request-specific security information.
Spring Boot Authenticate with AuthenticationProvider
These are some authentication providers that Spring Framework provides, in this example, we use >DaoAuthenticationProvider
. This Provider works well with form-based logins or HTTP Basic authentication which submits a simple username/password authentication request.
It authenticates the User simply by comparing the password submitted in a UsernamePasswordAuthenticationToken
against the one loaded by the UserDetailsService
(as a DAO):
@Autowired
AuthenticationManager authenticationManager;
...
Authentication authentication =
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.username, loginRequest.password)
);
Configuring this provider is simple with AuthenticationManagerBuilder
:
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Spring Boot Jwt Retrieve User details with UserDetailsService
We can obtain a principal from the Authentication
object. This principal can be cast into a UserDetails
object to lookup the username
, password
and GrantedAuthoritys
.
Therefore, after authenticating is successful, we can simply get UserDetails
from Authentication
object:
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// userDetails.getUsername()
// userDetails.getPassword()
// userDetails.getAuthorities()
DaoAuthenticationProvider
also uses UserDetailsService
for getting UserDetails object. This is the common approach in which we only pass a String-based ‘username’ argument and returns a UserDetails
:
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
It is simple to implement UserDetailsService
and easy for us to retrieve authentication information using a persistence strategy:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username).orElseThrow(
() -> new UsernameNotFoundException("User Not Found with -> username or email : " + username));
return UserPrinciple.build(user); // UserPrinciple implements UserDetails
}
}
Spring Boot JWT Protect Resources with HTTPSecurity & Method Security Expressions
– Spring security configure HTTPSecurity:
To help Spring Security know when we want to require all users to be authenticated, which Exception Handler to be chosen, which filter and when we want it to work. We implement WebSecurityConfigurerAdapter
and provide a configuration in the configure(HttpSecurity http)
method:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().
authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
...;
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
– Method Security Expressions:
Spring Security provides some annotations for pre and post-invocation authorization checks, filtering of submitted collection arguments or return values: @PreAuthorize
, @PreFilter
, @PostAuthorize
and @PostFilter
.
To enable Method Security Expressions, we use @EnableGlobalMethodSecurity
annotation:
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
}
In the code below, we use the most useful annotation @PreAuthorize
to decide whether a method can actually be invoked or not:
@RestController
public class TestRestAPIs {
@GetMapping("/api/test/user")
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
public String userAccess() {
return ">>> User Contents!";
}
@GetMapping("/api/test/pm")
@PreAuthorize("hasRole('PM') or hasRole('ADMIN')")
public String projectManagementAccess() {
return ">>> Project Management Board";
}
@GetMapping("/api/test/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return ">>> Admin Contents";
}
}
Spring Boot Jwt Handle AuthenticationException – AuthenticationEntryPoint
If the user requests a secure HTTP resource without being authenticated, AuthenticationEntryPoint
will be called. At this time, an AuthenticationException
is thrown, commence()
method on the entry point is triggered:
@Component
public class JwtAuthEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException e)
throws IOException, ServletException {
logger.error("Unauthorized error. Message - {}", e.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error -> Unauthorized");
}
}
SpringBoot Jwt Authentication Project Overview
The diagram below show how our system handles User Registration and User Login processes:

We expose 2 RestAPIs to signup and signin:
– SignUp API: /api/auth/signup

– SignIn API: /api/auth/signin

– In the tutorial, “Angular 10 + Spring Boot JWT Token Based Authentication Example”, We expose 3 RestAPIs to test protected resources:
@GetMapping("/api/test/user")
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
public String userAccess() {
return ">>> User Contents!";
}
@GetMapping("/api/test/pm")
@PreAuthorize("hasRole('PM') or hasRole('ADMIN')")
public String projectManagementAccess() {
return ">>> Board Management Project";
}
@GetMapping("/api/test/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return ">>> Admin Contents";
}
Access Successfully:

Unauthorized:

Technologies- Building Spring Boot Jwt Authentication Example
– Spring Boot 2
– jjwt – 0.9.0
– Spring Security
– Spring JPA
– MySQL/PostgreSQL
Project Structure – SpringBoot token based authentication example

– model
package defines 2 entities User
& Role
that have many-to-many relationship:
– repository
package contains interfaces that use Hibernate JPA to store/retrieve data from MySQL database.
– controller
package defines RestAPIs for user signup/signin and testing protected resources that is secured with JWT.
– message
package defines payload data transferred from user agents (Browser/RestClient…) to RestAPIs and message back.
– security
package is the main part of the project that implements JWT security.
Create SpringBoot Jwt Authentication Project
Dependency for the Project:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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-web</artifactId>
</dependency>
<!-- For Working with Json Web Tokens (JWT) -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
If you are using MySQL database, add the below dependency:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
If you use PostgreSQL database, add more the below dependency:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
SpringBoot Create Models
– User
model includes 5 attributes:
- id
- name
- username
- password
model/User.java
package com.loizenjava.jwtauthentication.model;
import java.util.HashSet;
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 org.hibernate.annotations.NaturalId;
@Entity
@Table(name = "users", uniqueConstraints = {
@UniqueConstraint(columnNames = {
"username"
}),
@UniqueConstraint(columnNames = {
"email"
})
})
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(min=3, max = 50)
private String name;
@NotBlank
@Size(min=3, max = 50)
private String username;
@NaturalId
@NotBlank
@Size(max = 50)
@Email
private String email;
@NotBlank
@Size(min=6, max = 100)
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
public User() {}
public User(String name, String username, String email, String password) {
this.name = name;
this.username = username;
this.email = email;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
– Role
model with 2 attributes:
- id
- rolename
model/Role.java
package com.loizenjava.jwtauthentication.model;
import javax.persistence.Column;
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 org.hibernate.annotations.NaturalId;
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
@NaturalId
@Column(length = 60)
private RoleName name;
public Role() {}
public Role(RoleName name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public RoleName getName() {
return name;
}
public void setName(RoleName name) {
this.name = name;
}
}
model/RoleName.java
package com.loizenjava.jwtauthentication.model;
public enum RoleName {
ROLE_USER,
ROLE_PM,
ROLE_ADMIN
}
SpringBoot Implement Repository – Angular Spring Boot Jwt Authentication Example
repository/UserRepository.java
package com.loizenjava.jwtauthentication.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.grokonez.jwtauthentication.model.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
repository/UserRepository.java
package com.loizenjava.jwtauthentication.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.grokonez.jwtauthentication.model.Role;
import com.grokonez.jwtauthentication.model.RoleName;
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
Optional<Role> findByName(RoleName roleName);
}
SpringBoot Implement JWT Security
In the tutorial “Angular 10 SpringBoot jwt authentication example”, we configure a WebSecurity file as below:
security/WebSecurityConfig.java
package com.loizenjava.jwtauthentication.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
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.authentication.UsernamePasswordAuthenticationFilter;
import com.grokonez.jwtauthentication.security.jwt.JwtAuthEntryPoint;
import com.grokonez.jwtauthentication.security.jwt.JwtAuthTokenFilter;
import com.grokonez.jwtauthentication.security.services.UserDetailsServiceImpl;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
prePostEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
private JwtAuthEntryPoint unauthorizedHandler;
@Bean
public JwtAuthTokenFilter authenticationJwtTokenFilter() {
return new JwtAuthTokenFilter();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().
authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
SpringBoot Jwt Create UserDetails Service
In the tutorial “Angular 10 SpringBoot jwt Authentication Example”, we implement a UserDetails Service as below:
– UserDetailsServiceImpl
implements UserDetailsService
and overrides loadUserByUsername()
method.
loadUserByUsername
method finds a record from users database tables to build a UserDetails
object for authentication.
security/services/UserDetailsServiceImpl.java
package com.loizenjava.jwtauthentication.security.services;
import com.grokonez.jwtauthentication.model.User;
import com.grokonez.jwtauthentication.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username).orElseThrow(
() -> new UsernameNotFoundException("User Not Found with -> username or email : " + username));
return UserPrinciple.build(user);
}
}
– UserPrinciple
will implement UserDetails
.
UserPrinciple
is not used directly by Spring Security for security purposes.
It simply stores user information which is later encapsulated into Authentication
objects. This allows non-security related user information (such as email addresses, telephone numbers etc) to be stored.
security/services/UserPrinciple.java
package com.loizenjava.jwtauthentication.security.services;
import com.grokonez.jwtauthentication.model.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class UserPrinciple implements UserDetails {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String username;
private String email;
@JsonIgnore
private String password;
private Collection extends GrantedAuthority> authorities;
public UserPrinciple(Long id, String name,
String username, String email, String password,
Collection extends GrantedAuthority> authorities) {
this.id = id;
this.name = name;
this.username = username;
this.email = email;
this.password = password;
this.authorities = authorities;
}
public static UserPrinciple build(User user) {
List authorities = user.getRoles().stream().map(role ->
new SimpleGrantedAuthority(role.getName().name())
).collect(Collectors.toList());
return new UserPrinciple(
user.getId(),
user.getName(),
user.getUsername(),
user.getEmail(),
user.getPassword(),
authorities
);
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserPrinciple user = (UserPrinciple) o;
return Objects.equals(id, user.id);
}
}
Spring Boot Jwt Authentication Classes
– JwtAuthTokenFilter
extends OncePerRequestFilter
.
org.springframework.web.filter.OncePerRequestFilter
executes once per request. This is a filter base class that is used to guarantee a single execution per request dispatch. It provides a doFilterInternal method with HttpServletRequest
and HttpServletResponse
arguments.
Inside JwtAuthTokenFilter
class, the doFilterInternal
method will:
- get JWT token from header
- validate JWT
- parse username from validated JWT
- load data from users table, then build an authentication object
- set the authentication object to Security Context
security/jwt/JwtAuthTokenFilter.java
package com.loizenjava.jwtauthentication.security.jwt;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import com.grokonez.jwtauthentication.security.services.UserDetailsServiceImpl;
public class JwtAuthTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtProvider tokenProvider;
@Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(JwtAuthTokenFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = getJwt(request);
if (jwt != null && tokenProvider.validateJwtToken(jwt)) {
String username = tokenProvider.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Can NOT set user authentication -> Message: {}", e);
}
filterChain.doFilter(request, response);
}
private String getJwt(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.replace("Bearer ", "");
}
return null;
}
}
– JwtAuthEntryPoint
is used to handle Error exception when having unauthorized requests.
security/jwt/JwtAuthEntryPoint.java
package com.loizenjava.jwtauthentication.security.jwt;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
@Component
public class JwtAuthEntryPoint implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthEntryPoint.class);
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException e)
throws IOException, ServletException {
logger.error("Unauthorized error. Message - {}", e.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error -> Unauthorized");
}
}
– JwtProvider
is an util class -> it implements useful functions:
- generate a JWT token
- valiate a JWT token
- parse username from JWT token
security/jwt/JwtProvider.java
package com.loizenjava.jwtauthentication.security.jwt;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.grokonez.jwtauthentication.security.services.UserPrinciple;
import java.util.Date;
@Component
public class JwtProvider {
private static final Logger logger = LoggerFactory.getLogger(JwtProvider.class);
@Value("${grokonez.app.jwtSecret}")
private String jwtSecret;
@Value("${grokonez.app.jwtExpiration}")
private int jwtExpiration;
public String generateJwtToken(Authentication authentication) {
UserPrinciple userPrincipal = (UserPrinciple) authentication.getPrincipal();
return Jwts.builder()
.setSubject((userPrincipal.getUsername()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpiration*1000))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
logger.error("Invalid JWT signature -> Message: {} ", e);
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token -> Message: {}", e);
} catch (ExpiredJwtException e) {
logger.error("Expired JWT token -> Message: {}", e);
} catch (UnsupportedJwtException e) {
logger.error("Unsupported JWT token -> Message: {}", e);
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty -> Message: {}", e);
}
return false;
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser()
.setSigningKey(jwtSecret)
.parseClaimsJws(token)
.getBody().getSubject();
}
}
SpringBoot Jwt RestAPI Create Payload Message
In the tutorial “Angular 10 SpringBoot jwt Authentication Example”, we create a Login Form as below:
– LoginForm
with username
& password
.
message/request/LoginForm.java
package com.loizenjava.jwtauthentication.message.request;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
public class LoginForm {
@NotBlank
@Size(min=3, max = 60)
private String username;
@NotBlank
@Size(min = 6, max = 40)
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
– SignUpForm
includes:
- name
- username
- role
- password
message/request/SignUpForm.java
package com.loizenjava.jwtauthentication.message.request;
import java.util.Set;
import javax.validation.constraints.*;
public class SignUpForm {
@NotBlank
@Size(min = 3, max = 50)
private String name;
@NotBlank
@Size(min = 3, max = 50)
private String username;
@NotBlank
@Size(max = 60)
@Email
private String email;
private Set role;
@NotBlank
@Size(min = 6, max = 40)
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set getRole() {
return this.role;
}
public void setRole(Set role) {
this.role = role;
}
}
– JwtResponse
object will be returned by SpringBoot server once an authentication is successful, it contains:
- JWT Token
- Schema Type of Token
- Username
- Array of User’s Authorities
message/response/JwtResponse.java
package com.loizenjava.jwtauthentication.message.response;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
public class JwtResponse {
private String token;
private String type = "Bearer";
private String username;
private Collection extends GrantedAuthority> authorities;
public JwtResponse(String accessToken, String username, Collection extends GrantedAuthority> authorities) {
this.token = accessToken;
this.username = username;
this.authorities = authorities;
}
public String getAccessToken() {
return token;
}
public void setAccessToken(String accessToken) {
this.token = accessToken;
}
public String getTokenType() {
return type;
}
public void setTokenType(String tokenType) {
this.type = tokenType;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
}
– ResponseMessage
object is just a message object.
message/response/ResponseMessage.java
package com.loizenjava.jwtauthentication.message.response;
public class ResponseMessage {
private String message;
public ResponseMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
SpringBoot Jwt Authentication Implement RestAPIs Controller – Angular SpringBoot Jwt Authentication Example
In the tutorial “Angular 10 SpringBoot jwt Authentication Example”, we implement a file AuthRestAPIs
that defines 2 APIs:
– /api/auth/signup
: sign up
-> check username/email is already in use.
-> create User object
-> store to database
– /api/auth/signin
: sign in
-> attempt to authenticate with AuthenticationManager
bean.
-> add authentication object to SecurityContextHolder
-> Generate JWT token, then return JWT to client
controller/AuthRestAPIs.java
package com.loizenjava.jwtauthentication.controller;
import java.util.HashSet;
import java.util.Set;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.CrossOrigin;
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 com.grokonez.jwtauthentication.message.request.LoginForm;
import com.grokonez.jwtauthentication.message.request.SignUpForm;
import com.grokonez.jwtauthentication.message.response.JwtResponse;
import com.grokonez.jwtauthentication.message.response.ResponseMessage;
import com.grokonez.jwtauthentication.model.Role;
import com.grokonez.jwtauthentication.model.RoleName;
import com.grokonez.jwtauthentication.model.User;
import com.grokonez.jwtauthentication.repository.RoleRepository;
import com.grokonez.jwtauthentication.repository.UserRepository;
import com.grokonez.jwtauthentication.security.jwt.JwtProvider;
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/auth")
public class AuthRestAPIs {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
PasswordEncoder encoder;
@Autowired
JwtProvider jwtProvider;
@PostMapping("/signin")
public ResponseEntity> authenticateUser(@Valid @RequestBody LoginForm loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtProvider.generateJwtToken(authentication);
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
return ResponseEntity.ok(new JwtResponse(jwt, userDetails.getUsername(), userDetails.getAuthorities()));
}
@PostMapping("/signup")
public ResponseEntity> registerUser(@Valid @RequestBody SignUpForm signUpRequest) {
if (userRepository.existsByUsername(signUpRequest.getUsername())) {
return new ResponseEntity<>(new ResponseMessage("Fail -> Username is already taken!"),
HttpStatus.BAD_REQUEST);
}
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return new ResponseEntity<>(new ResponseMessage("Fail -> Email is already in use!"),
HttpStatus.BAD_REQUEST);
}
// Creating user's account
User user = new User(signUpRequest.getName(), signUpRequest.getUsername(), signUpRequest.getEmail(),
encoder.encode(signUpRequest.getPassword()));
Set strRoles = signUpRequest.getRole();
Set roles = new HashSet<>();
strRoles.forEach(role -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(RoleName.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException("Fail! -> Cause: User Role not find."));
roles.add(adminRole);
break;
case "pm":
Role pmRole = roleRepository.findByName(RoleName.ROLE_PM)
.orElseThrow(() -> new RuntimeException("Fail! -> Cause: User Role not find."));
roles.add(pmRole);
break;
default:
Role userRole = roleRepository.findByName(RoleName.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Fail! -> Cause: User Role not find."));
roles.add(userRole);
}
});
user.setRoles(roles);
userRepository.save(user);
return new ResponseEntity<>(new ResponseMessage("User registered successfully!"), HttpStatus.OK);
}
}
TestRestAPIs
define 3 RestAPIs:
– /api/test/user
: access by users has USER_ROLE
or ADMIN_ROLE
– /api/test/pm
: access by users has USER_PM
or ADMIN_ROLE
– /api/test/admin
: access by users has ADMIN_ROLE
controller/TestRestAPIs.java
package com.loizenjava.jwtauthentication.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
public class TestRestAPIs {
@GetMapping("/api/test/user")
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
public String userAccess() {
return ">>> User Contents!";
}
@GetMapping("/api/test/pm")
@PreAuthorize("hasRole('PM') or hasRole('ADMIN')")
public String projectManagementAccess() {
return ">>> Project Management Board";
}
@GetMapping("/api/test/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return ">>> Admin Contents";
}
}
SpringBoot Configure Datasource, JPA and define App Properties
– Configure for MySQL database:
spring.datasource.url=jdbc:mysql://localhost:3306/loizenjavadb
spring.datasource.username=root
spring.datasource.password=12345
spring.jpa.generate-ddl=true
# App Properties
loizenjava.app.jwtSecret=jwtLoizenai.comSecretKey
loizenjava.app.jwtExpiration=86400
– Configure for PostgreSQL database:
## PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/loizenjavadb
spring.datasource.username=postgres
spring.datasource.password=123
#drop & create table again, good for testing, comment this in production
spring.jpa.hibernate.ddl-auto=create
SpringBoot Jwt Authentication – Run & Check Results
– Start Springboot server by commandline mvn spring-boot:run
– Check database tables:

– Insert data to roles table :
INSERT INTO roles(name) VALUES('ROLE_USER');
INSERT INTO roles(name) VALUES('ROLE_PM');
INSERT INTO roles(name) VALUES('ROLE_ADMIN');
1. SignUp:
Sign-Up 3 users:
- Jack has
ROLE_USER
role - Adam has
ROLE_PM
&ROLE_USER
roles - Thomas has
ROLE_ADMIN
role

– Check database’s tables:

2. SignIn and Access Protected Resources<: – Jack can access api/test/user url, can NOT access others. -> Sign In:

Access Protected Resources:


– Adam can access api/test/user
and api/test/pm
url.
Can NOT access /api/test/admin
url.
-> Sign In:

-> Access Protected Resources:



– Thomas can access all URLs.
-> Sign In:


Build Frontent Angular JWT Authentication Example
- How to build JWT Authentication frontend with Angular
- Practice
Angular Add Token to Header with Angular HttpInterceptor – Angular 10 JWT Token Based Authentication
We use Angular HttpInterceptor
with intercept()
method to inspect and transform HTTP requests (before they are sent to server):
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
const TOKEN_HEADER_KEY = 'Authorization';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
...
intercept(req: HttpRequest, next: HttpHandler) {
let authReq = req;
const token = ...;
if (token != null) {
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) });
}
return next.handle(authReq);
}
}
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
];
– The HTTPRequest
object will be inspected and forwarded to handle()
method of the HttpHandler
object.
– handle()
method transforms HTTPRequest
object into an Observable
of HttpEvents
which includes the server’s response.
What is next: HttpHandler
object?
-> This object represents the next interceptor in the chain of interceptors. The final ‘next’ in the chain is the Angular HttpClient handler.
Angular 10 HTTP Request using HttpClient – Angular SpringBoot Jwt Authentication Example
We send HTTP Requests (signin/signup) using Angular HttpClient
:
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
export class AuthService {
private loginUrl = 'http://localhost:8080/api/auth/signin';
private signupUrl = 'http://localhost:8080/api/auth/signup';
constructor(private http: HttpClient) {
}
// JwtResponse(accessToken,type,username,authorities)
attemptAuth(credentials: AuthLoginInfo): Observable {
return this.http.post(this.loginUrl, credentials, httpOptions);
}
// SignUpInfo(name,username,email,role,password)
signUp(info: SignUpInfo): Observable {
return this.http.post(this.signupUrl, info, httpOptions);
}
}
AuthLoginInfo
fields & SignUpInfo
fields are validated using Angular template-driven Form.
Once Token is saved, we can access protected resources simply:
export class UserService {
private userUrl = 'http://localhost:8080/api/test/user';
private pmUrl = 'http://localhost:8080/api/test/pm';
private adminUrl = 'http://localhost:8080/api/test/admin';
constructor(private http: HttpClient) { }
getUserBoard(): Observable {
return this.http.get(this.userUrl, { responseType: 'text' });
}
getPMBoard(): Observable {
return this.http.get(this.pmUrl, { responseType: 'text' });
}
getAdminBoard(): Observable {
return this.http.get(this.adminUrl, { responseType: 'text' });
}
}
Angular 10 Jwt Authentication Signup Response
export class RegisterComponent implements OnInit {
...
constructor(private authService: AuthService) { }
onSubmit() {
...
this.authService.signUp(this.signupInfo).subscribe(
data => {
...
},
error => {
...
}
);
}
}
Angular Login Response Example
In addition to using AuthService
to work with Observable
object, we also call TokenStorageService
methods to save Token
, >Username
, Authorities
:
export class LoginComponent implements OnInit {
...
constructor(private authService: AuthService, private tokenStorage: TokenStorageService) { }
ngOnInit() {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getAuthorities();
}
}
onSubmit() {
...
this.authService.attemptAuth(this.loginInfo).subscribe(
data => {
this.tokenStorage.saveToken(data.accessToken);
this.tokenStorage.saveUsername(data.username);
this.tokenStorage.saveAuthorities(data.authorities);
this.roles = this.tokenStorage.getAuthorities();
...
reloadPage();
},
error => {
...
}
);
}
}
Angular Jwt Authentication Manage Token & User Logout
We use TokenStorageService
to manage Token inside Browser’s sessionStorage:
export class TokenStorageService {
private roles: Array<string> = [];
public saveToken(token: string) {
window.sessionStorage.removeItem(TOKEN_KEY);
window.sessionStorage.setItem(TOKEN_KEY, token);
}
public getToken(): string {
return sessionStorage.getItem(TOKEN_KEY);
}
public saveUsername(username: string) {
window.sessionStorage.removeItem(USERNAME_KEY);
window.sessionStorage.setItem(USERNAME_KEY, username);
}
public getUsername(): string {
return sessionStorage.getItem(USERNAME_KEY);
}
public saveAuthorities(authorities: string[]) {
window.sessionStorage.removeItem(AUTHORITIES_KEY);
window.sessionStorage.setItem(AUTHORITIES_KEY, JSON.stringify(authorities));
}
public getAuthorities(): string[] {
this.roles = [];
if (sessionStorage.getItem(TOKEN_KEY)) {
JSON.parse(sessionStorage.getItem(AUTHORITIES_KEY)).forEach(authority => {
this.roles.push(authority.authority);
});
}
return this.roles;
}
}
For Logout action, we only need to clear Browser’s sessionStorage
:
export class TokenStorageService {
...
signOut() {
window.sessionStorage.clear();
}
}
Angular 10 Project Goal – Angular Client for JWT Authentication
We will build Angular Client which allows users to register, login account. And depending on the role of current User (user, pm or admin), this system accepts what he can access:

Look back below session for more information: Overview Goal
Angular 10 Jwt Authentication Elements Overview

Look back to the session ANGULAR FRONT-END WITH INTERCEPTOR for more details.
Angular 10 Jwt Authentication Technologies
– Angular 6
– RxJS 6
Angular 10 Jwt Authentication Project Structure

Create Angular Jwt Authentication Services & Components
Run commands below:
– ng g s auth/auth
– ng g s auth/token-storage
– ng g s services/user
– ng g c login
– ng g c register
– ng g c home
– ng g c user
– ng g c pm
– ng g c admin
Angular Jwt Authentication AppModule
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { UserComponent } from './user/user.component';
import { RegisterComponent } from './register/register.component';
import { HomeComponent } from './home/home.component';
import { AdminComponent } from './admin/admin.component';
import { PmComponent } from './pm/pm.component';
import { httpInterceptorProviders } from './auth/auth-interceptor';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
UserComponent,
RegisterComponent,
HomeComponent,
AdminComponent,
PmComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule
],
providers: [httpInterceptorProviders],
bootstrap: [AppComponent]
})
export class AppModule { }
Angular Jwt Authentication Auth Models
auth/login-info.ts
export class AuthLoginInfo {
username: string;
password: string;
constructor(username: string, password: string) {
this.username = username;
this.password = password;
}
}
auth/sigup-info.ts
export class SignUpInfo {
name: string;
username: string;
email: string;
role: string[];
password: string;
constructor(name: string, username: string, email: string, password: string) {
this.name = name;
this.username = username;
this.email = email;
this.password = password;
this.role = ['user'];
}
}
auth/jwt-response.ts
export class JwtResponse {
accessToken: string;
type: string;
username: string;
authorities: string[];
}
Angular Jwt Authentication Auth Service
auth/auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { JwtResponse } from './jwt-response';
import { AuthLoginInfo } from './login-info';
import { SignUpInfo } from './signup-info';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
@Injectable({
providedIn: 'root'
})
export class AuthService {
private loginUrl = 'http://localhost:8080/api/auth/signin';
private signupUrl = 'http://localhost:8080/api/auth/signup';
constructor(private http: HttpClient) {
}
attemptAuth(credentials: AuthLoginInfo): Observable {
return this.http.post(this.loginUrl, credentials, httpOptions);
}
signUp(info: SignUpInfo): Observable {
return this.http.post(this.signupUrl, info, httpOptions);
}
}
Angular Jwt Authentication Token Storage Service
auth/token-storage.service.ts
import { Injectable } from '@angular/core';
const TOKEN_KEY = 'AuthToken';
const USERNAME_KEY = 'AuthUsername';
const AUTHORITIES_KEY = 'AuthAuthorities';
@Injectable({
providedIn: 'root'
})
export class TokenStorageService {
private roles: Array = [];
constructor() { }
signOut() {
window.sessionStorage.clear();
}
public saveToken(token: string) {
window.sessionStorage.removeItem(TOKEN_KEY);
window.sessionStorage.setItem(TOKEN_KEY, token);
}
public getToken(): string {
return sessionStorage.getItem(TOKEN_KEY);
}
public saveUsername(username: string) {
window.sessionStorage.removeItem(USERNAME_KEY);
window.sessionStorage.setItem(USERNAME_KEY, username);
}
public getUsername(): string {
return sessionStorage.getItem(USERNAME_KEY);
}
public saveAuthorities(authorities: string[]) {
window.sessionStorage.removeItem(AUTHORITIES_KEY);
window.sessionStorage.setItem(AUTHORITIES_KEY, JSON.stringify(authorities));
}
public getAuthorities(): string[] {
this.roles = [];
if (sessionStorage.getItem(TOKEN_KEY)) {
JSON.parse(sessionStorage.getItem(AUTHORITIES_KEY)).forEach(authority => {
this.roles.push(authority.authority);
});
}
return this.roles;
}
}
Angular Jwt Authentication User Service
services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
private userUrl = 'http://localhost:8080/api/test/user';
private pmUrl = 'http://localhost:8080/api/test/pm';
private adminUrl = 'http://localhost:8080/api/test/admin';
constructor(private http: HttpClient) { }
getUserBoard(): Observable {
return this.http.get(this.userUrl, { responseType: 'text' });
}
getPMBoard(): Observable {
return this.http.get(this.pmUrl, { responseType: 'text' });
}
getAdminBoard(): Observable {
return this.http.get(this.adminUrl, { responseType: 'text' });
}
}
Angular 10 Jwt Authentication HTTP Interceptor
auth/auth-interceptor.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { TokenStorageService } from './token-storage.service';
const TOKEN_HEADER_KEY = 'Authorization';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private token: TokenStorageService) { }
intercept(req: HttpRequest, next: HttpHandler) {
let authReq = req;
const token = this.token.getToken();
if (token != null) {
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + token) });
}
return next.handle(authReq);
}
}
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }
];
Angular Jwt Authentication Implement Home Component
home.component.ts
import { Component, OnInit } from '@angular/core';
import { TokenStorageService } from '../auth/token-storage.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
info: any;
constructor(private token: TokenStorageService) { }
ngOnInit() {
this.info = {
token: this.token.getToken(),
username: this.token.getUsername(),
authorities: this.token.getAuthorities()
};
}
logout() {
this.token.signOut();
window.location.reload();
}
}
home.component.html
<div *ngIf="info.token; else loggedOut">
<h5 class="text-primary">Your Information</h5>
<p>
<strong>Username:</strong> {{info.username}}<br/>
<strong>Roles:</strong> {{info.authorities}}<br />
<strong>Token:</strong> {{info.token}}.
</p>
<button class="btn btn-secondary" (click)="logout()">Logout</button>
</div>
<ng-template #loggedOut>
Please login.
</ng-template>
Angular Jwt Authentication – Login Component
login.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth/auth.service';
import { TokenStorageService } from '../auth/token-storage.service';
import { AuthLoginInfo } from '../auth/login-info';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
form: any = {};
isLoggedIn = false;
isLoginFailed = false;
errorMessage = '';
roles: string[] = [];
private loginInfo: AuthLoginInfo;
constructor(private authService: AuthService, private tokenStorage: TokenStorageService) { }
ngOnInit() {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getAuthorities();
}
}
onSubmit() {
console.log(this.form);
this.loginInfo = new AuthLoginInfo(
this.form.username,
this.form.password);
this.authService.attemptAuth(this.loginInfo).subscribe(
data => {
this.tokenStorage.saveToken(data.accessToken);
this.tokenStorage.saveUsername(data.username);
this.tokenStorage.saveAuthorities(data.authorities);
this.isLoginFailed = false;
this.isLoggedIn = true;
this.roles = this.tokenStorage.getAuthorities();
this.reloadPage();
},
error => {
console.log(error);
this.errorMessage = error.error.message;
this.isLoginFailed = true;
}
);
}
reloadPage() {
window.location.reload();
}
}
login.component.html
<div *ngIf="isLoggedIn; else loggedOut">
Logged in as {{roles}}.
</div>
<ng-template #loggedOut>
<div class="row col-sm-6" style="max-width:350px;">
<form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" [(ngModel)]="form.username" #username="ngModel"
required />
<div *ngIf="f.submitted && username.invalid">
<div *ngIf="username.errors.required">Username is required</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" [(ngModel)]="form.password" #password="ngModel"
required minlength="6" />
<div *ngIf="f.submitted && password.invalid">
<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 class="btn btn-primary">Login</button>
<div *ngIf="f.submitted && isLoginFailed" class="alert alert-danger">
Login failed: {{errorMessage}}
</div>
</div>
</form>
<hr />
<p>Don't have an account?</p>
<a href="signup" class="btn btn-success">Sign Up</a>
</div>
</ng-template>
Angular Jwt Authentication Register Component
register.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth/auth.service';
import { SignUpInfo } from '../auth/signup-info';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
form: any = {};
signupInfo: SignUpInfo;
isSignedUp = false;
isSignUpFailed = false;
errorMessage = '';
constructor(private authService: AuthService) { }
ngOnInit() { }
onSubmit() {
console.log(this.form);
this.signupInfo = new SignUpInfo(
this.form.name,
this.form.username,
this.form.email,
this.form.password);
this.authService.signUp(this.signupInfo).subscribe(
data => {
console.log(data);
this.isSignedUp = true;
this.isSignUpFailed = false;
},
error => {
console.log(error);
this.errorMessage = error.error.message;
this.isSignUpFailed = true;
}
);
}
}
register.component.html
<div *ngIf="isSignedUp; else signupForm">
Your registration is successful. Please login!
</div>
<ng-template #signupForm>
<div class="row col-sm-6" style="max-width:350px;">
<form name="form" (ngSubmit)="f.form.valid && onSubmit()" #f="ngForm" novalidate>
<div class="form-group">
<label for="name">Your name</label>
<input type="text" class="form-control" name="name" [(ngModel)]="form.name" #name="ngModel" required />
<div *ngIf="f.submitted && name.invalid">
<div *ngIf="name.errors.required">Name is required</div>
</div>
</div>
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" [(ngModel)]="form.username" #username="ngModel"
required />
<div *ngIf="f.submitted && username.invalid">
<div *ngIf="username.errors.required">Username is required</div>
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" class="form-control" name="email" [(ngModel)]="form.email" #email="ngModel" required email />
<div *ngIf="f.submitted && email.invalid">
<div *ngIf="email.errors.required">Email is required</div>
<div *ngIf="email.errors.email">Email must be a valid email address</div>
</div>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" [(ngModel)]="form.password" #password="ngModel"
required minlength="6" />
<div *ngIf="f.submitted && password.invalid">
<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 class="btn btn-primary">Register</button>
<div *ngIf="f.submitted && isSignUpFailed" class="alert alert-warning">
Signup failed!<br/>{{errorMessage}}
</div>
</div>
</form>
</div>
</ng-template>
Angular Jwt Authentication Implement [UserRole] Components
user/pm/admin.component.html
<h4>Content from Server</h4>
{{board}}
{{errorMessage}}
user.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
board: string;
errorMessage: string;
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getUserBoard().subscribe(
data => {
this.board = data;
},
error => {
this.errorMessage = `${error.status}: ${JSON.parse(error.error).message}`;
}
);
}
}
pm.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
@Component({
selector: 'app-pm',
templateUrl: './pm.component.html',
styleUrls: ['./pm.component.css']
})
export class PmComponent implements OnInit {
board: string;
errorMessage: string;
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getPMBoard().subscribe(
data => {
this.board = data;
},
error => {
this.errorMessage = `${error.status}: ${JSON.parse(error.error).message}`;
}
);
}
}
admin.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css']
})
export class AdminComponent implements OnInit {
board: string;
errorMessage: string;
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getAdminBoard().subscribe(
data => {
this.board = data;
},
error => {
this.errorMessage = `${error.status}: ${JSON.parse(error.error).message}`;
}
);
}
}
Angular Jwt Authentication Implement App Routing
app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { RegisterComponent } from './register/register.component';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
import { UserComponent } from './user/user.component';
import { PmComponent } from './pm/pm.component';
import { AdminComponent } from './admin/admin.component';
const routes: Routes = [
{
path: 'home',
component: HomeComponent
},
{
path: 'user',
component: UserComponent
},
{
path: 'pm',
component: PmComponent
},
{
path: 'admin',
component: AdminComponent
},
{
path: 'auth/login',
component: LoginComponent
},
{
path: 'signup',
component: RegisterComponent
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.ts
import { Component, OnInit } from '@angular/core';
import { TokenStorageService } from './auth/token-storage.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private roles: string[];
private authority: string;
constructor(private tokenStorage: TokenStorageService) { }
ngOnInit() {
if (this.tokenStorage.getToken()) {
this.roles = this.tokenStorage.getAuthorities();
this.roles.every(role => {
if (role === 'ROLE_ADMIN') {
this.authority = 'admin';
return false;
} else if (role === 'ROLE_PM') {
this.authority = 'pm';
return false;
}
this.authority = 'user';
return true;
});
}
}
}
app.component.html
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">grokonez</a>
</div>
<ul class="nav navbar-nav" routerLinkActive="active">
<li class="nav-item"><a class="nav-link" routerLink="home">Home</a></li>
<li *ngIf="authority === 'user'" class="nav-item">
<a class="nav-link" routerLink="user">User Board</a>
</li>
<li *ngIf="authority === 'admin'" class="nav-item">
<a class="nav-link" routerLink="admin">Admin Board</a>
</li>
<li *ngIf="authority === 'pm'" class="nav-item">
<a class="nav-link" routerLink="pm">PM Board</a>
</li>
<li *ngIf="!authority" class="nav-item">
<a class="nav-link" routerLink="auth/login">Login</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
Further Reading – Angular SpringBoot Jwt Authentication Example
- JSON Web Tokens – jwt.io
- Angular HttpClient
- Spring Security
Sourcecode – Angular SpringBoot Jwt Authentication Example
I includes 2 sourcecodes for the tutorial: ‘Angular 10 SpringBoot JWt Token Based Authentication Example’
- SpringBoot Backend
- Angular Frontend
– All Features of sourcecode for SpringBoot JWT Token Based Authentication Backend:
- Implement JPA Repository
- Implement SpringBoot JWT Security: UserDetails Service & JWT Authentication classes
- Implement Protected RestControllers
Nodejs JWT Authentication Example
– Github Sourcecode:
SpringBoot Angular Jwt Authentication Examples – Backend RestAPIs GitHub
– All Features of sourcecode for Angular JWT Token Based Authentication Example:
- Build Angular Services:
- Auth Service
- Token Storage Service
- User Service
- HTTP Interceptor
- Build Angular Components:
- Home Component
- Login Component
- Register Component
- [UserRole] Components
- App Routing
Angular SpringBoot Jwt Authentication Example – Frontend
– GitHub Sourcecode:
Angular SpringBoot Jwt Authentication Example – Frontend GitHub
Thanks for reading!
Thank you! Keep do it
Angular 10 Spring Boot Jwt Authentication Example – Login Spring Security MySQL – loizenjava.com
Thanks man! Great post
I’m getting error -> Signup failed!
Cannot invoke “java.util.Set.forEach(java.util.function.Consumer)” because “strRoles” is null
What can i need to do.? Please give me solution.