I need spring boot app with two different login/register endpoints one is api/user/auth/registerUser and api/node/auth/registerNode.
I write the code but now i have two authenticationManagerBean see config:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration {
@Configuration
@Order(1)
public class SecurityConfig1 extends WebSecurityConfigurerAdapter {
@Autowired
CustomUserDetailsService customUserDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean("authenticationManager")
@Qualifier("authenticationManager")
@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()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/user/auth/**")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
@Configuration
@Order(2)
public class SecurityConfig2 extends WebSecurityConfigurerAdapter {
@Autowired
CustomUser1DetailsService customUser1DetailsService;
@Autowired
private JwtAuthenticationEntryPoint1 unauthorizedHandler1;
@Bean
public JwtAuthenticationFilter1 jwtAuthenticationFilter1() {
return new JwtAuthenticationFilter1();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder1) throws Exception {
authenticationManagerBuilder1
.userDetailsService(customUser1DetailsService)
.passwordEncoder(passwordEncoder1());
}
@Bean("authenticationManager1")
@Qualifier("authenticationManager1")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder1() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler1)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/",
"/favicon.ico",
"/**/*.png",
"/**/*.gif",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js")
.permitAll()
.antMatchers("/api/node/auth/**")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter1(), UsernamePasswordAuthenticationFilter.class);
}
}
}
and i make user controler:
@RestController
@RequestMapping("/api/user/auth")
public class UserAuthController {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
@Qualifier("authenticationManager")
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenProvider tokenProvider;
public UserAuthController() {
}
@PostMapping(path = "/registerUser")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return new ResponseEntity(new ApiResponse(false, "Email Address already taken"), HttpStatus.BAD_REQUEST);
}
if (userRepository.existsByUsername(signUpRequest.getUsername())) {
return new ResponseEntity(new ApiResponse(false, "Username already taken"), HttpStatus.BAD_REQUEST);
}
// Creating User
User user = new User(signUpRequest.getUsername(), signUpRequest.getEmail(), passwordEncoder.encode(signUpRequest.getPassword()),
signUpRequest.getFirstName(), signUpRequest.getMiddleName(), signUpRequest.getLastName());
// Role userRole = roleRepo.findByName(RoleName.ROLE_USER)
// .orElseThrow(() -> new AppException("User Role not set."));
//
// Role adminRole = roleRepo.findByName(RoleName.ROLE_ADMIN)
// .orElseThrow(() -> new AppException("User Role not set."));
//
// Set<Role> rules = new HashSet<>();
// rules.add(userRole);
// rules.add(adminRole);
// user.setRoles(rules);
User result = userRepository.save(user);
return ResponseEntity.ok(result);
}
@PostMapping("/authenticateUser")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsernameOrEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String accessToken = tokenProvider.generateAccessToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(accessToken,tokenProvider.getIssuedDateFromAccessToken(accessToken),tokenProvider.getExpirationDateFromAccessToken(accessToken)));
} catch (BadCredentialsException exception) {
throw new BadRequestException("Wrong username or password!");
}
}
}
and node controler:
@RestController
@RequestMapping("/api/node/auth")
public class NodeAuthController {
@Autowired
private User1Repository user1Repository;
@Autowired
private Role1Repository role1Repository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
@Qualifier("authenticationManager1")
private AuthenticationManager authenticationManager1;
@Autowired
private JwtTokenProvider1 tokenProvider1;
@PostMapping(path = "/registerNode")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
if (user1Repository.existsByEmail(signUpRequest.getEmail())) {
return new ResponseEntity(new ApiResponse(false, "Email Address already taken"), HttpStatus.BAD_REQUEST);
}
if (user1Repository.existsByUsername(signUpRequest.getUsername())) {
return new ResponseEntity(new ApiResponse(false, "Username already taken"), HttpStatus.BAD_REQUEST);
}
// Creating User
User1 user1 = new User1(signUpRequest.getUsername(), signUpRequest.getEmail(), passwordEncoder.encode(signUpRequest.getPassword()),
signUpRequest.getFirstName(), signUpRequest.getMiddleName(), signUpRequest.getLastName());
// Role userRole = roleRepo.findByName(RoleName.ROLE_USER)
// .orElseThrow(() -> new AppException("User Role not set."));
//
// Role adminRole = roleRepo.findByName(RoleName.ROLE_ADMIN)
// .orElseThrow(() -> new AppException("User Role not set."));
//
// Set<Role> rules = new HashSet<>();
// rules.add(userRole);
// rules.add(adminRole);
// user.setRoles(rules);
User1 result = user1Repository.save(user1);
return ResponseEntity.ok(result);
}
@PostMapping("/authenticateNode")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
try {
Authentication authentication = authenticationManager1.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsernameOrEmail(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
String accessToken = tokenProvider1.generateAccessToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(accessToken,tokenProvider1.getIssuedDateFromAccessToken(accessToken),tokenProvider1.getExpirationDateFromAccessToken(accessToken)));
} catch (BadCredentialsException exception) {
throw new BadRequestException("Wrong username or password!");
}
}
}
Error is:java.lang.RuntimeException: java.lang.IllegalArgumentException: Found 2 beans for type interface org.springframework.security.authentication.AuthenticationManager, but none marked as primary
If I make one primary code is run but for controler that is not primary response is
{
"timestamp": "2020-06-04T03:45:45.638+02:00",
"status": 401,
"error": "Unauthorized",
"message": "",
"path": "/api/node/auth/registerNode"
}
How to make this work? Thanks for all your help