================
Spring Security
=================
1) Authentication (verifying credentials)
2) Authorization (can this user access specific functionality)
-> Security is very important for every web application
-> To protect our application & application data we need to implement security logic
-> Spring Security concept we can use to secure our web applications / REST APIs
-> To secure our spring boot application we need to add below starter in pom.xml file
org.springframework.boot
spring-boot-starter-security
Note: When we add this dependency in pom.xml file then by default our application will be secured with basic authentication. It will generate random password to access our application.
Note: Generated Random Password will be printed on console.
-> We need to use below credentials to access our application
Username : user
Password :
-> When we access our application url in browser then it will display "Login Form" to authenticate our request.
-> To access secured REST API from postman, we need to set Auth values in POSTMAN to send the request
Auth : Basic Auth
Username : user
Password :
=====================================================
How to override Spring Security Default Credentials
=====================================================
-> To override Default credentials we can configre security credentials in application.properties file or application.yml file like below
spring.security.user.name=ashokit
spring.security.user.password=ashokit@123
-> After configuring credentials like above, we need to give above credentials to access our application / api.
=====================================
How to secure specific URL Patterns
=====================================
-> When we add 'security-starter' in pom.xml then it will apply security filter for all the HTTP methods of our application.
-> But in reality we need to secure only few methods not all methods in our application.
##For Example##
/ login-page --> security not required
/ transfer ---> security required
/ balance ---> security required
/ about-us ---> security not required
/ contact-us ---> security not required
-> In order to achieve above requirement we need to Customize Security Configuration in our project like below
@Configuration
@EnableWebSecurity
public class SecurityConfigurer {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authorize) -> authorize
.requestMatchers("/contact", "/swagger-ui.html").permitAll()
.anyRequest().authenticated()
)
.httpBasic(withDefaults())
.formLogin(withDefaults());
return http.build();
}
}
==========================================
Spring Security In-Memory Authentication
==========================================
-> In Memory Authentication means storing user credentials in the program for Authentication Purpose.
-> This is not recommended for production.
@Bean
public InMemoryUserDetailsManager inMemoryUsers() {
UserDetails ashokUser = User.withDefaultPasswordEncoder()
.username("ashok")
.password("ashok")
.authorities("ADMIN")
.build();
UserDetails johnUser = User.withDefaultPasswordEncoder()
.username("john")
.password("john")
.authorities("USER")
.build();
return new InMemoryUserDetailsManager(ashokUser, johnUser);
}
@Bean
public SecurityFilterChain securityConfig(HttpSecurity http) throws Exception {
http.authorizeHttpRequests( (req) -> req
.antMatchers("/admin").hasRole(ADMIN)
.antMatchers("/user").hasAnyRole("ADMIN","USER")
.antMatchers("/").permitAll()
.anyRequest().authenticated()
).formLogin();
return http.build();
}
}
=======================================================
How to work with UserDetailsService in Spring Security
=======================================================
=> UserDetailsService is a predefined interface which contains loadUserByUsername(String name) method.
=> This is used to load User record for Authentication purpose in Spring Security.
=> We can implement UserDetailsService interface and we can write the logic to retrieve User record based on given username for Authentication purpose.
=> If we give UserDetailsService object to AuthenticationProvider then AuthManager will call this method for every login request.
==============================================
Login and Registration using Spring Security
==============================================
## 1) Create Boot app with required dependencies ##
a) web-starter
b) data-jpa-starter
c) mysql
d) security-starter
e) devtools
## 2) Configure Data Source properties in yml file ##
## 2) Create Entity class & Repository interface ##
@Repository
public interface CustomerRepo extends CrudRepository {
public Customer findByUname(String cuname);
}
## 3) Create UserDetailsService class ##
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private CustomerRepo crepo;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Customer c = crepo.findByUname(username);
return new User(c.getUname(), c.getPwd(), Collections.emptyList());
}
}
## 4) Create Security Config Class ##
@Configuration
@EnableWebSecurity
public class AppSecurityConfig {
@Autowired
private MyUserDetailsService userDtlsSvc;
@Bean
public PasswordEncoder pwdEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider authenticationProvider=
new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDtlsSvc);
authenticationProvider.setPasswordEncoder(pwdEncoder());
return authenticationProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain securityConfig(HttpSecurity http) throws Exception {
return http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/register", "/login").permitAll()
.and()
.build();
}
}
## 5) Create RestController with required methods
@RestController
public class CustomerRestController {
@Autowired
private CustomerRepo crepo;
@Autowired
private PasswordEncoder pwdEncoder;
@Autowired
private AuthenticationManager authManager;
@PostMapping("/login")
public ResponseEntity loginCheck(@RequestBody Customer c) {
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(c.getUname(), c.getPwd());
try {
Authentication authenticate = authManager.authenticate(token);
if (authenticate.isAuthenticated()) {
return new ResponseEntity<>("Welcome To Ashok IT", HttpStatus.OK);
}
} catch (Exception e) {
//logger
}
return new ResponseEntity("Invalid Credentials", HttpStatus.BAD_REQUEST);
}
@PostMapping("/register")
public String registerCustomer(@RequestBody Customer customer) {
// duplicate check
String encodedPwd = pwdEncoder.encode(customer.getPwd());
customer.setPwd(encodedPwd);
crepo.save(customer);
return "User registered";
}
}
## 6) Run the application and test it
##############
OAuth 2.0
##############
### 1) Create Spring Boot application with below dependencies
a) web-starter
b) security-starter
c) oauth-client
### 2) Create OAuth app in Github.com
(Login --> Profile -> Settings --> Developer Settings --> OAuth Apps --> Create App --> Copy Client ID & Client Secret)
### 3) Configure GitHub OAuth App client id & client secret in application.yml file like below
spring:
security:
oauth2:
client:
registration:
github:
clientId:
clientSecret:
### 4) Create Rest Controller with method
@RestController
public class WelcomeRestController {
@GetMapping("/")
public String welcome() {
return "Welcome to Ashok IT";
}
}
#### 5) Run the application and test it.
Assignment : Spring Boot with oAuth using google account. Get username also from google and display that in response.
#########################
Spring Boot with JWT
########################
-> JWT stands for JSON Web Tokens
-> JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
-> JWT official Website : https://jwt.io/
-> Below is the sample JWT Token
token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
-> JWT contains below 3 parts
1) Header
2) Payload
3) Signature
Note: JWT 3 parts will be seperated by using dot(.)
## Git Hub Repo : https://github.com/ashokitschool/SpringBoot_JWT_App.git
1) JWT Token generation (JwtService.java)
- generateToken(String uname)
- validateToken(String uname)
2) JWT Token validation Filter (AppFilter.java) - OncePerRequest
- check Authorization header presence
- retrieve bearer token from header
- validate token
- if token is valid, update security context to process req
3) Customize SecurityFilterChain
- permit /api/register & /api/login urls
- authenticate any other request
- set security context as stateless
============================
Authorization Token Format
============================
Key = Authorization
Value = Bearer
================================
Microservices with JWT Security
===============================
=> Auth-Service contains functionality for user registration and user login with MySQL DB.
=> If user login successfully then auth-service will generate JWT token and will send it as response to user.
=> API-Gateway contains logic to validate the token using Filter.
Note: In API-Gateway we have added routings for our microservices along with Filter.
=> When we access any microservice url through api-gateway then api-gateway will execute filter to validate the token. If token is valid then only api-gateway will route the request to particular microservice. If token is invalid then api-gateway will throw Exception.
### Git Hub Repo : https://github.com/ashokitschool/Microservices_Security.git