-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow configuring the ActiveDirectoryLdapAuthenticationProvider in AuthenticationManagerBuilder #11448
Comments
@petrdvorak, I agree that the hierarchy could likely use some cleanup, and I feel like Option 3 would be ideal. With the introduction of Option 1: Introduce an authentication manager factory for Active Directory |
Previously, we'd just pass an authentication provider (either AbstractLdapAuthenticationProvider authenticationProvider;
if (!isActiveDirectory) {
authenticationProvider = new LdapAuthenticationProvider(bindAuthenticator);
} else {
authenticationProvider = new ActiveDirectoryLdapAuthenticationProvider(activeDirectoryDomain, ldapUrl);
}
AuthenticationManager authManager = new ProviderManager(List.of(authenticationProvider)); Now, with
To my knowledge, that's not achievable without doing some network stuff, even if we have the host URL, as AD is basically an implementation of LDAP with some overhead.
This would probably be almost 100% copy-paste of the same factory, as it seems to be enough just to pass the AD authentication provider (which is configurable itself) into the authentication manager. My suggestion is to allow setting an instance of an authentication provider within the aforementioned factory. If that works, I could raise a PR with the change. |
…n AbstractLdapAuthenticationManagerFactory. Resolves spring-projects#11448
@Haarolean your existing approach still works: @Bean
AuthenticationManager authenticationManager() {
AbstractLdapAuthenticationProvider authenticationProvider;
if (!isActiveDirectory) {
authenticationProvider = new LdapAuthenticationProvider(bindAuthenticator);
} else {
authenticationProvider = new ActiveDirectoryLdapAuthenticationProvider(activeDirectoryDomain, ldapUrl);
}
return new ProviderManager(List.of(authenticationProvider));
} So I'm not sure why you are looking for something different?
I don't really see the point, since someone could do: @Bean
AuthenticationManager authenticationManager() {
ActiveDirectoryLdapAuthenticationProvider activeDirectory = // ... construct
return new ProviderManager(activeDirectory);
} |
@Haarolean, thanks very much for raising the PR and pointing out some of the limitations with further simplifying At this point, I think we should close this issue; what do you think? |
Yes, that's possible, but that neglects the convenience of using Here are two examples, with and without With the factory: @Bean
ReactiveAuthenticationManager ldapAuthenticationManager(BaseLdapPathContextSource contextSource, ApplicationContext context,
@Nullable AccessControlService acs) {
var factory = new LdapBindAuthenticationManagerFactory(contextSource);
factory.setLdapAuthoritiesPopulator(new DefaultLdapAuthoritiesPopulator(contextSource, "null"));
factory.setUserDetailsContextMapper(new UserDetailsMapper());
factory.setUserSearchFilter("userSearchFilter");
factory.setUserDnPatterns("uid={0},ou=people");
factory.setUserSearchBase("userSearchBase");
var authenticationManager = factory.createAuthenticationManager();
return new ReactiveAuthenticationManagerAdapter(authenticationManager);
} Without one: @Bean
public ReactiveAuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource,
LdapAuthoritiesPopulator ldapAuthoritiesPopulator,
@Nullable AccessControlService acs) {
var bindAuthenticator = new BindAuthenticator(contextSource);
bindAuthenticator.setUserDnPatterns(new String[] {props.getBase()});
if (props.getUserFilterSearchFilter() != null) {
LdapUserSearch userSearch =
new FilterBasedLdapUserSearch("searchBase", "searchFilter", contextSource);
bindAuthenticator.setUserSearch(userSearch);
}
AbstractLdapAuthenticationProvider authenticationProvider;
if (!props.isActiveDirectory()) {
authenticationProvider = new LdapAuthenticationProvider(bindAuthenticator, ldapAuthoritiesPopulator);
} else {
authenticationProvider = new ActiveDirectoryLdapAuthenticationProvider(props.getActiveDirectoryDomain(), props.getUrls());
authenticationProvider.setUseAuthenticationRequestCredentials(true);
}
authenticationProvider.setUserDetailsContextMapper(new UserDetailsMapper());
AuthenticationManager am = new ProviderManager(List.of(authenticationProvider));
return new ReactiveAuthenticationManagerAdapter(am);
} As you can see, without using the factory we have to write a lot more code to create things like bindAuthenticator, authenticationProvider. Let me know what you think. |
I think I see what you are saying now. I think some of this is a slight mismatch between What if you did this instead: @Bean
public ReactiveAuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource)
if (props.isActiveDirectory()) {
var provider = new ActiveDirectoryLdapAuthenticationProvider(props.getActiveDirectoryDomain(), props.getUrls());
provider.setUseAuthenticationRequestCredentials(true);
return new ReactiveAuthenticationManagerAdapter(new ProviderManager(provider));
} else {
var factory = new LdapBindAuthenticationManagerFactory(contextSource);
factory.setLdapAuthoritiesPopulator(new DefaultLdapAuthoritiesPopulator(contextSource, "null"));
factory.setUserDetailsContextMapper(new UserDetailsMapper());
factory.setUserSearchFilter("userSearchFilter");
factory.setUserDnPatterns("uid={0},ou=people");
factory.setUserSearchBase("userSearchBase");
return new ReactiveAuthenticationManagerAdapter(factory.createAuthenticationManager());
}
} |
Currently, we are able to set standard LDAP provider via:
However, the
LdapAuthenticationProviderConfigurer
is hardcoded to createLdapAuthenticationProvider
in thebuild
method (here).There is no way to setup the configurer to build the
ActiveDirectoryLdapAuthenticationProvider
, which uses a different internal logic on top of the same baseAbstractLdapAuthenticationProvider
class.To be able to configure Active Directory the same way we currently can configure classic LDAP, we would like to see either of these options:
Option 1: Own configurer for Active Directory
... providing the following new method:
Option 2: Picking the right class from a registered bean
... instead of creating the class, the configurer could automatically detect a bean:
Option 3: Consolidation of LDAP authentication providers
... so that we do not need to handle different providers.
Having
ActiveDirectoryLdapAuthenticationProvider
andLdapAuthenticationProvider
that do not inherit from each other seems a bit unexpected. Maybe there could be a strategy pattern used instead to configure behavior of oneLdapAuthenticationProvider
class?Option 4: Allow Builder to construct the abstract class instance
... and probably many more options framework could support it?
The text was updated successfully, but these errors were encountered: