Custom Authentication Manager with Spring Security and Java Configuration - Printable Version +- 0Day Forums (https://zeroday.vip) +-- Forum: Coding (https://zeroday.vip/Forum-Coding) +--- Forum: FrameWork (https://zeroday.vip/Forum-FrameWork) +---- Forum: Spring (https://zeroday.vip/Forum-Spring) +---- Thread: Custom Authentication Manager with Spring Security and Java Configuration (/Thread-Custom-Authentication-Manager-with-Spring-Security-and-Java-Configuration) |
Custom Authentication Manager with Spring Security and Java Configuration - ungamboling327182 - 08-02-2023 I am using Spring Security with SpringMVC to create a web application (I will refer to this as the WebApp for clarity) that speaks to an existing application (I will refer to this as BackendApp). I want to delegate authentication responsibilities to the BackendApp (so that I don't need to synchronise the two applications). To implement this, I would like the WebApp (running spring security) to communicate to the BackendApp via REST with the username and password provided by the user in a form and authenticate based on whether the BackendApp's response is 200 OK or 401 Unauthorised. I understand I will need to write a custom Authentication Manager to do this however I am very new to spring and can't find any information on how to implement it. I believe I will need to do something like this: public class CustomAuthenticationManager implements AuthenticationManager{ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String pw = authentication.getCredentials().toString(); // Code to make rest call here and check for OK or Unauthorised. // What do I return? } } Do I set authentication.setAuthenticated(true) if successful and false if otherwise and thats it? Once this is written, how do I configure spring security to use this authentication manager using a java configuration file? Thanks in advance for any assistance. RE: Custom Authentication Manager with Spring Security and Java Configuration - limey383594 - 08-02-2023 First you must configure Spring security to use your custom AuthenticationProvider. So, in your spring-security.xml (or equivalent config file) you must define wich class is implementing this feature. For example: <authentication-manager alias="authenticationManager"> <authentication-provider ref="myAuthenticationProvider" /> </authentication-manager> <!-- Bean implementing AuthenticationProvider of Spring Security --> <beans:bean id="myAuthenticationProvider" class="com.teimas.MyAutenticationProvider"> </beans:bean> Secondly you must implement AuthenticationProvider as in your example. Specially the method authenticate(Authentication authentication) in which your rest call must be. For example: public Authentication authenticate(Authentication authentication) throws AuthenticationException { User user = null; try { //use a rest service to find the user. //Spring security provides user login name in authentication.getPrincipal() user = userRestService.loadUserByUsername(authentication.getPrincipal().toString()); } catch (Exception e) { log.error("Error loading user, not found: " + e.getMessage(), e); } if (user == null) { throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal())); } else if (!user.isEnabled()) { throw new UsernameNotFoundException(String.format("Not found enabled user for username ", user.getUsername())); } //check user password stored in authentication.getCredentials() against stored password hash if (StringUtils.isBlank(authentication.getCredentials().toString()) || !passwordEncoder.isPasswordValid(user.getPasswordHash(), authentication.getCredentials().toString()) { throw new BadCredentialsException("Invalid credentials"); } //doLogin makes whatever is necesary when login is made (put info in session, load other data etc..) return doLogin(user); } RE: Custom Authentication Manager with Spring Security and Java Configuration - tubiflorales664388 - 08-02-2023 In its most simplest: @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { String username = auth.getName(); String password = auth.getCredentials().toString(); // to add more logic List<GrantedAuthority> grantedAuths = new ArrayList<>(); grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER")); return new UsernamePasswordAuthenticationToken(username, password, grantedAuths); } RE: Custom Authentication Manager with Spring Security and Java Configuration - boer134 - 08-02-2023 My solution is almost the same as the first answer: 1) You need a class which implements the Authentication Provider @Service @Configurable public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // Your code of custom Authentication } } 2) Opposite to the first answer you **don't** need to have following code in your WebSecurityConfiguration if you have only this custom provider. @Override protected AuthenticationManager authenticationManager() throws Exception { return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider())); } The issue is that Spring looks for available providers and use the default if nothing else is found. But as you have the implementation of the AuthenticationProvider - your implementation will be used. RE: Custom Authentication Manager with Spring Security and Java Configuration - animism742616 - 08-02-2023 Take a look at my sample below. You have to return an UsernamePasswordAuthenticationToken. It contains the principal and the GrantedAuthorities. Hope I could help :) public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getPrincipal() + ""; String password = authentication.getCredentials() + ""; User user = userRepo.findOne(username); if (user == null) { throw new BadCredentialsException("1000"); } if (!encoder.matches(password, user.getPassword())) { throw new BadCredentialsException("1000"); } if (user.isDisabled()) { throw new DisabledException("1001"); } List<Right> userRights = rightRepo.getUserRights(username); return new UsernamePasswordAuthenticationToken(username, null, userRights.stream().map(x -> new SimpleGrantedAuthority(x.getName())).collect(Collectors.toList())); } PS: userRepo and rightRepo are Spring-Data-JPA Repositories which access my custom User-DB SpringSecurity JavaConfig: @Configuration @EnableWebMvcSecurity public class MySecurityConfiguration extends WebSecurityConfigurerAdapter { public MySecurityConfiguration() { super(false); } @Override protected AuthenticationManager authenticationManager() throws Exception { return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider())); } } RE: Custom Authentication Manager with Spring Security and Java Configuration - chemotropism992 - 08-02-2023 This is how I did using component-based configuration (SecurityFilterChain) and new `authorizeHttpRequests` ```java @Bean protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity .authorizeHttpRequests(auth -> auth .antMatchers(UNPROTECTED_URLS).permitAll() .oauth2ResourceServer() .accessDeniedHandler(restAccessDeniedHandler) .authenticationEntryPoint(authenticationEntryPoint) .jwt() .authenticationManager(new ProviderManager(authenticationProvider)); // this is custom authenticationProvider return httpSecurity.build(); } ``` |