I am trying to implement RBAC authentication in my application where it should interface with an LDAP server for authentication. I have separate code for logging in using a local database and logging in using LDAP. I am trying to merge the two codes so that when the LDAP server is unavailable, the application switches to authentication using local backup accounts. In my controller, I have the following code snippet:
@GetMapping("/login")
public String login(Model model) {
if (ldapService.isLdapAvailable()) {
System.out.println("Inside login method. LDAP is available.");
return "redirect:/login"; // Redirect to success page if LDAP connection is successful
} else {
System.out.println("Inside login method. LDAP is unavailable.");
model.addAttribute("ldapUnavailableMessage", "LDAP service is currently unavailable. Do you want to continue with local backup authentication?");
return "login"; // Return login page with an LDAP error message
}
}
@PostMapping("/login")
public String handleLogin(@RequestParam Map<String, String> credentials, HttpSession session, Model model) {
String username = credentials.get("username");
String password = credentials.get("password");
if (ldapService.isLdapAvailable()) {
// Handle LDAP authentication (not provided in this example)
System.out.println("LDAP is available and handling login via LDAP.");
// Assuming LDAP authentication success here for now
session.setAttribute("username", username); // Set whatever attributes are needed here
return "redirect:/dashboard"; // Redirect to dashboard
} else {
boolean isAuthenticated = localAuthService.authenticate(username, password);
if (isAuthenticated) {
session.setAttribute("username", username);
System.out.println("Authenticated using local DB.");
return "redirect:/dashboard"; // Redirect to dashboard or another page
} else {
model.addAttribute("error", "Authentication failed. Please check your username and password.");
System.out.println("Local DB authentication failed.");
return "login"; // Stay on login page and show error
}
}
}
In my login.html page I am trying something like
<div th:if="${ldapUnavailableMessage}">
<script>
alert([[${ldapUnavailableMessage}]]);
if (confirm("Do you want to continue with local backup authentication?")) {
window.location.href = "/localLogin"; // Redirect to local login page
}
</script>
</div>
But this isn’t working. Code is able to check whether LDAP is available or not. If it is not available it is throwing error
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainController': Unsatisfied dependency expressed through field 'ldapService'
Could someone please help me troubleshoot this issue and provide guidance on how to implement the pop-up message for the user in this scenario? Thank you in advance for your help.
2
I have modified my LdapConfig class as below and then I was able to check at application startup only whether LdapServer is up or not. Sharing here so that it helps other too!
@Configuration
public class LdapConfig {
@Value("${ldap.url}")
private String ldapUrl;
@Value("${ldap.admin.dn}")
private String adminDn;
@Value("${ldap.admin.password}")
private String adminPassword;
@Value("${ldap.enabled}")
private boolean ldapEnabled; // to check the property directly
@Bean
@Lazy
@ConditionalOnProperty(name = "ldap.enabled", havingValue = "true", matchIfMissing = true)
public DirContext ldapContext() throws NamingException {
if(!ldapEnabled) {
System.out.println("LDAP is not enabled");
return null;
}
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, adminDn);
env.put(Context.SECURITY_CREDENTIALS, adminPassword);
try {
DirContext context = new InitialDirContext(env);
System.out.println("LDAP connection successful.");
return context;
} catch (NamingException e) {
System.out.println("LDAP connection failed: ");
return null; // Rethrow exception to indicate bean creation failed
}
}
}
Thank you!
Kailash