I am building a user authentication micro service for learning purpose using Spring Boot. I have already developed separately 3 different user authentication methods as 3 different projects (one of using PostgreSQL database with JWT authentication, and another one is using OAuth2 and the other one is using LDAP). Now I need combine these 3 as a single service. I already have setup some steps.
At the moment I have the following:
This my SecurityConfigure.java
file:
package com.persistent.userauthentication.security;
import com.persistent.userauthentication.filters.JwtRequestFilter;
import com.persistent.userauthentication.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfigure extends WebSecurityConfigurerAdapter {
@Configuration
@Order(1)
public static class JwtWebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private AuthService authService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(authService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.requestMatchers()
.antMatchers("/jwt/**")
.and()
.authorizeRequests()
.antMatchers("/jwt/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS); //since we don't want to manage sessions
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
@Configuration
@Order(2)
public static class LdapSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/ldapauth/**")
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
.passwordEncoder(new BCryptPasswordEncoder())
.passwordAttribute("userPassword");
}
}
@Configuration
@Order(3)
public static class Oauth2SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/googleauth/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
}
This is my AuthController.java
(controller) file:
package com.persistent.userauthentication.controller;
import com.persistent.userauthentication.model.AuthenticationRequest;
import com.persistent.userauthentication.model.AuthenticationResponse;
import com.persistent.userauthentication.service.AuthService;
import com.persistent.userauthentication.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private AuthService authService;
@Autowired
private JwtUtil jwtTokenUtil;
@RequestMapping(value = "/jwt/hello", method = RequestMethod.GET)
public String Hello(){
return "basic auhentication successfull";
}
@GetMapping("/googleauth/hello")
public String GooglAauth(){
return "google authentication successful!";
}
@RequestMapping(value = "/ldapauth/hello", method = RequestMethod.GET)
public String LdapAuth(){
return "ldap authentication successful!";
}
@RequestMapping(value = "/jwt/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword())
);
} catch (BadCredentialsException e){
throw new Exception("username or password is incorrect!", e);
}
final UserDetails userDetails = authService.loadUserByUsername(authenticationRequest.getUsername());
final String jwt = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(jwt));
}
@RequestMapping(value = "/jwt/extendtoken", method = RequestMethod.POST)
public ResponseEntity<?> createNewAuthenticationToken(@RequestHeader("Authorization") String token) throws Exception {
final String jwt = jwtTokenUtil.refreshToken(token);
return ResponseEntity.ok(new AuthenticationResponse(jwt));
}
}
Currently /jwt/hello
(with Authorization
header and generated JWT code), /jwt/authenticate
and jwt/extendtoken
endpoints are working properly.
Now I need to setup OAuth2 authentication service to /googleauth/hello
endpoint and LDAP authentication service to /ldapauth/hello
.
When I call endpoint /googleauth/hello
it also redirect to the LDAP login page instead of Google account selection page.