Skip to content

Commit

Permalink
LDAP cahcing
Browse files Browse the repository at this point in the history
  • Loading branch information
Piyush Sadangi (EXT) committed Mar 25, 2024
1 parent b6f644f commit a7f0ae9
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 6 deletions.
32 changes: 32 additions & 0 deletions publish-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,38 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>5.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>5.7.4</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.7.4</version>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>${springboot.version}</version>
</dependency>

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.ericsson.eiffel.remrem.publish.config;

import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.cache.NullUserCache;
import org.springframework.security.core.userdetails.cache.SpringCacheBasedUserCache;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.security.ldap.authentication.LdapAuthenticator;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

public class CachingLdapAuthenticationProvider extends LdapAuthenticationProvider {

private UserCache userCache = new NullUserCache();

/**
* Create an instance with the supplied authenticator and authorities populator
* implementations.
*
* @param authenticator the authentication strategy (bind, password comparison, etc)
* to be used by this provider for authenticating users.
* @param authoritiesPopulator the strategy for obtaining the authorities for a given
*/

public CachingLdapAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
super(authenticator, authoritiesPopulator);
}

public void setUserCache(UserCache userCache) {
this.userCache = userCache;
}


@Override
public Authentication authenticate(Authentication authentication) {
String userName = authentication.getName();
UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken) authentication;
UserDetails userDetailsFromCache = userCache.getUserFromCache(userName);
if (userDetailsFromCache != null) {
additionalAuthenticationChecks(userDetailsFromCache, userToken);
return createSuccessfulAuthentication(userToken, userDetailsFromCache);
} else {
Authentication authenticationFromProvider = super.authenticate(authentication);
userCache.putUserInCache((UserDetails)authenticationFromProvider.getPrincipal());
return authenticationFromProvider;
}

}

protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) {
if (StringUtils.isEmpty(authentication.getCredentials())) {

throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
if (!StringUtils.isEmpty(userDetails.getPassword()) && (!presentedPassword.equals(userDetails.getPassword()))) {
System.out.println("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,37 @@
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ldap.core.support.BaseLdapPathContextSource;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.cache.SpringCacheBasedUserCache;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.ldap.authentication.BindAuthenticator;
import org.springframework.security.ldap.authentication.LdapAuthenticator;
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;

/**
* This class is used to enable the ldap authentication based on property
Expand Down Expand Up @@ -74,20 +105,54 @@ public Integer getTimeOut() {
@Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
@Bean
public UserCache userCache() {
// Adjust cache settings as necessary
return new SpringCacheBasedUserCache(cacheManager().getCache("authenticationCache"));
}

@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(1000));
return cacheManager;
}


@Bean
public LdapAuthoritiesPopulator ldapAuthoritiesPopulator() {
return new DefaultLdapAuthoritiesPopulator(ldapContextSource(), null); // Adjust the second parameter based on your group search base
// Additional configuration can be set here if necessary
}


@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
final String jasyptKey = RabbitMqPropertiesConfig.readJasyptKeyFile(jasyptKeyFilePath);
if (managerPassword.startsWith("{ENC(") && managerPassword.endsWith("}")) {
managerPassword = DecryptionUtils.decryptString(
managerPassword.substring(1, managerPassword.length() - 1), jasyptKey);
}
LOGGER.debug("LDAP server url: " + ldapUrl);
auth.ldapAuthentication()
.userSearchFilter(userSearchFilter)
.contextSource(ldapContextSource());

BindAuthenticator bindAuthenticator = new BindAuthenticator(ldapContextSource());
bindAuthenticator.setUserSearch(new FilterBasedLdapUserSearch("", userSearchFilter, ldapContextSource()));


LdapAuthoritiesPopulator ldapAuthoritiesPopulator = ldapAuthoritiesPopulator();

// Create and use the caching LDAP authentication provider
CachingLdapAuthenticationProvider cachingProvider =
new CachingLdapAuthenticationProvider(bindAuthenticator, ldapAuthoritiesPopulator);

cachingProvider.setUserCache(userCache());
auth.authenticationProvider(cachingProvider);

}

public BaseLdapPathContextSource ldapContextSource() {
public LdapContextSource ldapContextSource() {
LdapContextSource ldap = new LdapContextSource();
ldap.setUrl(ldapUrl);
ldap.setBase(rootDn);
Expand Down

0 comments on commit a7f0ae9

Please sign in to comment.