fernandopcg
fernandopcg

Reputation: 512

Complex authentication in Spring Boot

I'm trying to get authentication done from a Spring Boot app with an external provider I will need to code for a 3rd party software equipment . The app issues commands on that external software and thus a user credential is needed to connect and operate.

The authentication needs to be performed using username and password provided in a form against an Active Directory database (Checks if the user exists in the company), and then an internal database which tells the app if the user is allowed to use the app and whether he's an admin or not (For customizing the menu bar later on). Afterwards, the user is authenticated with this external software by means of a binary executable present on the server (Using ProcessBuilder). It's a bit complex but that's the way it has to be because of external contraints.

Furthermore, once the user is authenticated in this 3rd party software, he must pick a role out of a list which contains all roles available to that user. Only after this, the connection is finally set up and we have to redirect the user to the main page from where he can use the app.

The login page shows a form with username and password fields, and a button which will trigger the auth process and present the user with the list of roles, and after picking one and clicking another button the role will be selected and the user will be redirected to the home page.

The problem is that I don't have any clues to implement this in Spring Boot.

My LoginController contains:

@Inject
public LoginController(final LoginService loginService) {
    this.loginService = loginService;
}

@RequestMapping("/login.html")
public ModelAndView getLoginView() {
    LOGGER.debug("Received request to get login view");
    ModelMap model = new ModelMap();
    model.addAttribute("authenticationTypes",loginService.getAuthenticationTypes());
    model.addAttribute(loginService);
    return new ModelAndView("login", model);
}

I had working code in a LoginServiceImpl module I was using in a older JSF application which would like to reuse but don't know how.

Upvotes: 1

Views: 200

Answers (1)

melli-182
melli-182

Reputation: 1234

Like a similar answer here, you need to create your own CustomAuthenticationProvider, which must implements AuthenticationProvider.

For example:

@Component
public class CustomAuthenticationProvider
implements AuthenticationProvider {

@Autowired
private ThirdPartyClient thirdPartyClient;

public void setAtpClient(ThirdPartyClient atpClient) {
    this.thirdPartyClient = atpClient;
}

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = authentication.getCredentials().toString();


    Request3rd requestTO = new AtpAuthenticateRequestDTO();
    requestTO.setPassword(password);
    requestTO.setUsername(username);
    Response3rd authenticate = this.thirdPartyClient.authenticate(requestTO);

    if (authenticate != null) {
        List<GrantedAuthority> grantedAuths = new ArrayList<>();
        grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
        Authentication auth = new UsernamePasswordAuthenticationToken(authenticate.getUsername(), password, grantedAuths);
        return auth;
    } else {
        return null;
    }
}

@Override
public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
}

}

Then in the SecurityConfig class, which extends WebSecurityConfigurerAdapter override in this configure method:

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(this.authenticationProvider);
}

Where you can autowire the customAuthenticationProvider created before:

@Autowired
private CustomAuthenticationProvider authenticationProvider;

Upvotes: 2

Related Questions