Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 734 Vote(s) - 3.43 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Custom Authentication Manager with Spring Security and Java Configuration

#1
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.
Reply

#2
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);
}

Reply

#3
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);
}

Reply

#4
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.
Reply

#5
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()));
}

}
Reply

#6
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();
}
```
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through