Repository: mulesoft/mule-spring-module
Pull request #266: W-17849656 | [add] code changes for FIPS compliance
Author: login: mule-niraj
Created: 2025-02-18T06:29:03Z | Merged: 2025-03-19T14:44:41Z

_Hi, thank you for your work. We understand that you want to merge your changes and move on from this issue, but we also want to maintain the safety, readability, and testability of our code. Because of this, we kindly ask that you confirm that you have fulfilled the prerequisites for each category of activity before merging your changes._

### If the Pull Request has a dependency update:

- [ ] I have read the Release Notes for the new version (and intermediate versions if the jump would include more than one). _Don't blindly trust that the dependency will honor SEMVER, always read carefully the release notes_
- [ ] Java 8+ support is maintained
- [ ] The new version has no vulnerabilities
- [ ] A team member reviewed the Pull Request.
- [ ] No backward compatibility is broken.
- [ ] If it is a "provided" dependency, it has been checked that if it is suggested, the version number is the same.

### For ALL the Releases:

- [ ] There is a task in GUS for this change.
- [ ] The corresponding Release Notes have been written and shared with the documentation team.
- [ ] The new code has tests and they have before and after methods to be sure that you are working with a clean environment and that you are leaving the environment clean after they finish.
- [ ] If you are using reflection, create a test to call the methods you are invoking, this way, if there is a change in the API, the test will be able to detect it.
- [ ] If the project has a parent pom and modules, the release pipeline only uploads the modules, so, please, make sure that the parent was deployed in the repositories before considering this release finished.
- [ ] Notify in the Slack Channel that the release is complete, so the Docs team can merge the Documentation and Release Notes PR. The docs team always checks in Anypoint Exchange that the connector is released before merging the release notes.
- [ ] Add the connector build to GUS, and assign that build to the GUS ticket.
- [ ] Create a change case request, based on the Change Case Management doc https://docs.google.com/document/d/1tMJlTTZLaXMLiYwxlMBFY1yJwBmejhc4-IP8HAXgDfY/edit#

**NOTE**: _(applies only for Core-Connectors connectors and modules) The release process ends when you merge the pull request that updates the support branch to the new snapshot, please don't forget to do this._

### Patch Version:

- [ ] The Pull Request has been peer-reviewed.
- [ ] No backward compatibility is broken.
- [ ] Documentation: (Required) Release Notes PR with compatibility table. Share it with the Docs team.

### Minor Version:

- [ ] Have a document with the specification of the release.
- [ ] Create a slack channel (eg: rl-conninfra-sftp-1.1.1-new-chiper) to coordinate the release of this version with the documentation team and the architects of our team (at least one week before the release). Share the spec doc with the docs team.
- [ ] The documentation fork has been done and has been updated with the changes related to the new functionalities.
- [ ] The pull request has been reviewed by a peer and the team leader.
- [ ] No backward compatibility is broken.
- [ ] Public Documentation: Minor releases nearly always require a revision of the documentation because the release usually includes new features as well as bug fixes. Even if there are no user-facing changes, documentation has to be versioned for every minor release.
  - [ ] (Required) Release Notes PR with compatibility table. Share it with the Docs team.
  - [ ] (Likely required) Reference guide. Run the script and share the file with the Docs team.
  - [ ] (Assess) Often a minor release impacts UI and examples, so the documentation (user guides, examples, troubleshooting guides) should be reviewed and updated accordingly. Notify the docs team if any updates are needed.

### Major Version:

- [ ] Have a document with the specification of the release.
- [ ] Create a slack channel (eg: rl-conninfra-sftp-2.0.0) to coordinate the release of this version with the documentation team and the architects of our team (at least one month before the release). Share the spec doc with the docs team.
- [ ] The documentation fork has been made and updated with the changes related to the new functionalities and possible compatibility problems with the previous version.
- [ ] The systems properties have been removed, detailing in the documentation the changes in the default behavior of the product.
- [ ] The TODO comments of the code have been reviewed.
- [ ] A colleague, the team leader, and the team architect have reviewed the Pull Request.
- [ ] Public Documentation: Major releases break backward compatibility and should never be released without documentation, as this breaks the user experience.
  - [ ] (Required) Upgrade and Migration Guide: Every major release must have a detailed upgrade guide (template) with information about what was changed and what steps the user has to take to ensure the connector works as expected. Share the details with the Docs team so they can update the guide.
  - [ ] (Required) Release Notes PR with compatibility table. Share it with the docs team.
  - [ ] (Required) Reference guide. Run the script and share the file with the Docs team.
  - [ ] User guide updates, new screenshots or examples (if applicable), share the updates with the docs team.



Diff:
diff --git a/module/pom.xml b/module/pom.xml
index 14226de9..2db01881 100644
--- a/module/pom.xml
+++ b/module/pom.xml
@@ -17,16 +17,16 @@
     <munit.output.directory>${basedir}/target/test-mule/munit</munit.output.directory>
 
     <munit.extensions.maven.plugin.version>1.4.0</munit.extensions.maven.plugin.version>
-    <munit.version>3.3.2</munit.version>
+    <munit.version>3.4.0</munit.version>
     <mtf.tools.version>1.2.0</mtf.tools.version>
 
     <mavenResourcesVersion>3.0.2</mavenResourcesVersion>
 
-    <jacoco.version>0.8.10</jacoco.version>
+    <jacoco.version>0.8.12</jacoco.version>
     <sdk.api.version>0.7.0</sdk.api.version>
-    <http.connector.version>1.8.1</http.connector.version>
-    <mule.java.module.version>1.2.12</mule.java.module.version>
-    <mule.sockets.connector.version>1.2.3</mule.sockets.connector.version>
+    <http.connector.version>1.9.3</http.connector.version>
+    <mule.java.module.version>1.2.13</mule.java.module.version>
+    <mule.sockets.connector.version>1.2.5</mule.sockets.connector.version>
   </properties>
 
   <build>
diff --git a/module/src/main/java/org/mule/extension/spring/api/SpringConfig.java b/module/src/main/java/org/mule/extension/spring/api/SpringConfig.java
index e52c552b..821e79eb 100644
--- a/module/src/main/java/org/mule/extension/spring/api/SpringConfig.java
+++ b/module/src/main/java/org/mule/extension/spring/api/SpringConfig.java
@@ -163,7 +163,7 @@ public <T> Map<String, T> getObjectsByType(Class<T> type) {
   @Override
   public void dispose() {
     if (applicationContext != null) {
-      applicationContext.destroy();
+      applicationContext.close();
       applicationContext = null;
     }
   }
diff --git a/module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java b/module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
index 4f6accb7..810ed5e7 100644
--- a/module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
+++ b/module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
@@ -6,6 +6,16 @@
  */
 package org.mule.extension.spring.internal.beanfactory;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.apache.commons.logging.LogFactory;
+import org.mule.extension.spring.internal.util.CustomPostAuthenticationChecks;
+import org.mule.extension.spring.internal.util.CustomPreAuthenticationChecks;
+import org.mule.runtime.api.exception.MuleRuntimeException;
 import org.mule.runtime.api.ioc.ObjectProvider;
 import org.mule.runtime.api.lifecycle.Disposable;
 import org.mule.runtime.api.lifecycle.Initialisable;
@@ -19,13 +29,24 @@
 import java.util.Set;
 
 import org.springframework.beans.BeansException;
+import org.springframework.beans.PropertyValue;
 import org.springframework.beans.TypeConverter;
 import org.springframework.beans.factory.BeanDefinitionStoreException;
 import org.springframework.beans.factory.BeanFactory;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.DependencyDescriptor;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.cache.NullUserCache;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
 
 /**
  * {@link DefaultListableBeanFactory} implementation that takes into account the objects provided by the mule artifact for
@@ -84,6 +105,11 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        return (T) authenticationProvider(getUserDetailService(name));
+      }
+    }
     if (containsBean(name) || !artifactObjectProvider.containsObject(name) || destroying) {
       return super.doGetBean(name, requiredType, args, typeCheckOnly);
     } else {
@@ -134,4 +160,59 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new MuleRuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
+    return new DelegatingPasswordEncoder(encodingId, encoders);
+  }
+
+  private UserDetailsService getUserDetailService(String name) {
+    List<PropertyValue> propertyValues = super.getBeanDefinition(name).getPropertyValues().getPropertyValueList();
+    String userServiceName = propertyValues.stream()
+        .filter(propertyValue -> "userDetailsService".equals(propertyValue.getName()))
+        .map(propertyValue -> ((RuntimeBeanReference) propertyValue.getValue()).getBeanName())
+        .findFirst()
+        .orElse(null);
+    return (UserDetailsService) super.getBean(userServiceName != null ? userServiceName : "userService");
+  }
 }
diff --git a/module/src/main/java/org/mule/extension/spring/internal/util/CustomPostAuthenticationChecks.java b/module/src/main/java/org/mule/extension/spring/internal/util/CustomPostAuthenticationChecks.java
new file mode 100644
index 00000000..a6810d22
--- /dev/null
+++ b/module/src/main/java/org/mule/extension/spring/internal/util/CustomPostAuthenticationChecks.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
+ * The software in this package is published under the terms of the CPAL v1.0
+ * license, a copy of which has been included with this distribution in the
+ * LICENSE.txt file.
+ */
+package org.mule.extension.spring.internal.util;
+
+import org.springframework.security.authentication.CredentialsExpiredException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsChecker;
+
+public class CustomPostAuthenticationChecks implements UserDetailsChecker {
+
+  @Override
+  public void check(UserDetails user) {
+    if (!user.isCredentialsNonExpired()) {
+      throw new CredentialsExpiredException("User credentials have expired");
+    }
+  }
+}
diff --git a/module/src/main/java/org/mule/extension/spring/internal/util/CustomPreAuthenticationChecks.java b/module/src/main/java/org/mule/extension/spring/internal/util/CustomPreAuthenticationChecks.java
new file mode 100644
index 00000000..c65e8575
--- /dev/null
+++ b/module/src/main/java/org/mule/extension/spring/internal/util/CustomPreAuthenticationChecks.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
+ * The software in this package is published under the terms of the CPAL v1.0
+ * license, a copy of which has been included with this distribution in the
+ * LICENSE.txt file.
+ */
+package org.mule.extension.spring.internal.util;
+
+import org.springframework.security.authentication.AccountExpiredException;
+import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.authentication.LockedException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsChecker;
+
+public class CustomPreAuthenticationChecks implements UserDetailsChecker {
+
+  @Override
+  public void check(UserDetails user) {
+    if (!user.isAccountNonLocked()) {
+      throw new LockedException("User account is locked");
+    }
+    if (!user.isEnabled()) {
+      throw new DisabledException("User is disabled");
+    }
+    if (!user.isAccountNonExpired()) {
+      throw new AccountExpiredException("User account has expired");
+    }
+  }
+}
diff --git a/module/src/test/resources/beans.xml b/module/src/test/resources/beans.xml
index 915702af..57448628 100644
--- a/module/src/test/resources/beans.xml
+++ b/module/src/test/resources/beans.xml
@@ -14,8 +14,8 @@
     <ss:authentication-manager alias="authenticationManager">
         <ss:authentication-provider>
             <ss:user-service id="userService">
-                <ss:user name="admin" password="{noop}admin" authorities="ROLE_ADMIN" />
-                <ss:user name="anon" password="{noop}anon" authorities="ROLE_ANON" />
+                <ss:user name="admin" password="{bcrypt}$2y$10$L7nVRlI9TswnzbbRJ0XtH.nEgR9ZMbcVK6rGZKt6rBqRUUGc/cIaq" authorities="ROLE_ADMIN" />
+                <ss:user name="anon" password="{bcrypt}$2y$10$yMGo.D9jbFXQ5qSwy2HtpeOLA5CvWybydInz2z8iYpbpU9JMLLjf6" authorities="ROLE_ANON" />
             </ss:user-service>
         </ss:authentication-provider>
     </ss:authentication-manager>
diff --git a/src/test/munit/.gitkeep b/src/test/munit/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/src/test/resources/.gitkeep b/src/test/resources/.gitkeep
new file mode 100644
index 00000000..e69de29b


Reviews:
user: login: ChkuSalesforce
state: CHANGES_REQUESTED
author_association: NONE
submitted_at: 2025-02-18T10:21:41Z
user: login: acurci-at-mulesoft
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T19:32:55Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T20:21:49Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T20:25:22Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T20:48:56Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T20:55:19Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T08:59:39Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T09:00:56Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T09:04:27Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T09:13:46Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T09:16:31Z
user: login: acurci-at-mulesoft
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T21:47:27Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T22:01:03Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T08:36:21Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T08:36:53Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T08:38:08Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T08:39:49Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T15:43:03Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T16:01:46Z
user: login: elcoya
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-13T18:52:17Z
user: login: elcoya
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-13T20:11:24Z
user: login: acurci-at-mulesoft
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T20:18:05Z
user: login: mule-niraj
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T12:05:39Z
user: login: elcoya
state: APPROVED
author_association: NONE
submitted_at: 2025-03-18T15:02:06Z
user: login: acurci-at-mulesoft
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T20:51:52Z
user: login: ChkuSalesforce
state: APPROVED
author_association: NONE
submitted_at: 2025-03-19T12:31:21Z

Review comments:
diff_hunk: @@ -134,4 +165,51 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: ChkuSalesforce
body: Why not now ? Create a backlog item and mention here. 
created_at: 2025-02-18T10:12:12Z
author_association: NONE
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
+        return (T) authenticationProvider(userDetailsService);
+      }
+    }
     if (containsBean(name) || !artifactObjectProvider.containsObject(name) || destroying) {
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: ChkuSalesforce
body: if (!containsBean(name) && artifactObjectProvider.containsObject(name) && !destroying) {
    return (T) artifactObjectProvider.getObject(name);
} else {
    return super.doGetBean(name, requiredType, args, typeCheckOnly);
}

This will ensure beans from artifactObjectProvider are only used when Spring does not contain them.
created_at: 2025-02-18T10:18:48Z
author_association: NONE
diff_hunk: @@ -134,4 +165,51 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(MyCustomLogger.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: ChkuSalesforce
body: catch (ClassNotFoundException e) {
    log.error("Unsafe class not found, falling back to normal instance creation.", e);
    return new DaoAuthenticationProvider();
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    throw new SecurityException("Reflection-based authentication provider creation failed!", e);
}

Logs missing classes instead of crashing.
created_at: 2025-02-18T10:21:07Z
author_association: NONE
diff_hunk: @@ -24,7 +24,7 @@
 
     <jacoco.version>0.8.10</jacoco.version>
path: module/pom.xml
user: login: acurci-at-mulesoft
body: Please, could you also check for other updates like jacoco 0.8.12, munit 3.4.0, socket-connector 1.2.5, java-module 1.2.13, etc?
created_at: 2025-03-10T14:39:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -26,6 +36,21 @@
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.config.DependencyDescriptor;
 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.cache.NullUserCache;
+import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
+import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Please remove unused imports.
created_at: 2025-03-10T15:16:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Normally this wouldn't be valid on java 17, but I think there is an exception regarding the sun.misc.Unsafe class, could you add a comment to clarify that issue for future developers?
created_at: 2025-03-10T16:22:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Will this work on Java 17?
created_at: 2025-03-10T16:28:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(MyCustomLogger.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("noop", NoOpPasswordEncoder.getInstance());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Are we sure about this list? 
I have checked the first one and I found this:
<img width="701" alt="image" src="https://github.com/user-attachments/assets/919de774-619b-4a0f-89bc-bee8a60cc069" />

*Deprecated This PasswordEncoder is not secure...*

Are These the encoders that we want to use on a FIPS-compliance enviroment?
created_at: 2025-03-10T19:32:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(MyCustomLogger.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap();
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: ```suggestion
    Map<String, PasswordEncoder> encoders = new HashMap<>();
```
created_at: 2025-03-10T20:21:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: ```suggestion
      Class<?> c = Class.forName("sun.misc.Unsafe");
```
created_at: 2025-03-10T20:25:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: I am not sure about this hardcoded name, where this bean name come from?
created_at: 2025-03-10T20:48:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(MyCustomLogger.class));
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Is MyCustomLogger needeed? Couldn't you create the log with the right class?
loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
created_at: 2025-03-10T20:55:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: sure, will add comment over the method.
created_at: 2025-03-11T08:59:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: I verified the changes on runtime 4.9.0 and used Java 17 to run the MUnit, and it worked perfectly.
created_at: 2025-03-11T09:00:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(MyCustomLogger.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("noop", NoOpPasswordEncoder.getInstance());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: The NoOpPasswordEncoder was used in beans.xml and to prevent the test failures I kept it in the list. However, I have now updated the test to use the BCryptPasswordEncoder and removed NoOpPasswordEncoder from the configuration.
created_at: 2025-03-11T09:04:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: When the user defines the authenticationManager in beans.xml [like this](https://github.com/mulesoft/mule-spring-module/blob/47728877ba2765221203a7ad4042db80b4b575b0/module/src/test/resources/beans.xml), they provide an ID for user-service. I haven't found a way to parameterise this, which could be a limitation for customers who need to use a different name for the ID instead of userService.
created_at: 2025-03-11T09:13:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +165,48 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  //TODO improve this code error check
+  //ugly hack to bypass non FIPS compliant security algorithms
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(MyCustomLogger.class));
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: No, I believe `MyCustomLogger` is unnecessary. I'll use the appropriate class as per your suggestion.
created_at: 2025-03-11T09:16:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: shouldn't it be a MuleRuntimeException?
created_at: 2025-03-11T17:23:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: I think this algorithm is not FIPS compliance since it is using SHA-1
<img width="762" alt="image" src="https://github.com/user-attachments/assets/255951e9-9629-44ae-bb61-963305fcba7d" />

created_at: 2025-03-11T17:28:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: I think we can use defaultsForSpringSecurity_v5_8 since it uses SHA-256, don't you think?
<img width="886" alt="image" src="https://github.com/user-attachments/assets/452789d6-1cf0-4fa7-983b-bede57b17fd1" />

created_at: 2025-03-11T17:30:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
+    encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: The [Bouncy Castle FIPS document](https://downloads.bouncycastle.org/fips-java/docs/BC-FJA-UserGuide-1.0.2.pdf) states:

> "A version of Scrypt which is built directly on the FIPS implementation of PBKDF2 using HmacSHA-256 is also available in approved mode."

However, it is unclear whether the SCryptPasswordEncoder implementations in Spring Security (defaultsForSpringSecurity_v4_1() and defaultsForSpringSecurity_v5_8()) meet FIPS requirements.

Could you investigate and confirm if these implementations rely on a FIPS-validated version of Scrypt, or if they use a general (non-FIPS) implementation?
created_at: 2025-03-11T21:41:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
+    encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
+    encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
+    encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
+    encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
+    return new DelegatingPasswordEncoder(encodingId, encoders);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: I think Argon2 is not FIPS compliance.
created_at: 2025-03-11T21:46:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Please tell me if these statements are correct:

1. If we are running in a non-FIPS environment, the user is free to configure the bean with the name he wants
2. In FIPS environments, we need to configure that bean and that is why we are expecting it with a specific name.

Now my questions:
1. Does the name that the method receives correspond to the name of that same bean?
2. Is it not possible to search for the bean by type and in the case that there is only one, use it independently of the name?

I am not convinced by the hardcoded name....
created_at: 2025-03-11T22:01:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: Yes, the above depiction is correct. In a non-FIPS environment, the customer is free to name it anything, but the same does not apply in FIPS.

1. The method receives the name org.springframework.security.authentication.dao.DaoAuthenticationProvider, which is different.
2. I tried searching by type, and it works fine when only one bean is configured. However, it throws an error if multiple beans are configured. Even if we get a list of bean names for a UserDetailService type, we can never be certain which one to use.
created_at: 2025-03-12T08:36:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: Updated to use defaultsForSpringSecurity_v5_8 instead of defaultsForSpringSecurity_v5_5.
created_at: 2025-03-12T08:36:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
+    encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: Couldn't find any concrete document suggesting that spring security uses the FIPS compliant implementation of Scrypt. We can remove this.
created_at: 2025-03-12T08:38:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
+    encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
+    encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
+    encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
+    encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
+    return new DelegatingPasswordEncoder(encodingId, encoders);
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: You're right, Argon2 is not FIPS compliant. I copied the entire list and only removed the SHA-1 and MD5 implementations without properly investigating the others. That was my mistake, and I'll remove Argon2 as well.
created_at: 2025-03-12T08:39:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: @elcoya , what do you think about this? Should we try searching for the bean by type if only one exists, and if not, default to a hardcoded name?

Should we use a fixed hardcoded name, or should we define a default one and allow it to be modified in some way (e.g., through parameterization or a system property)?
created_at: 2025-03-13T15:43:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,4 +160,53 @@ private boolean implementsLifecycle(BeanDefinition beanDefinition) {
   public void markForDestroy() {
     this.destroying = true;
   }
+
+  /**
+   * TODO improve this code error check, ugly hack to bypass non FIPS compliant security algorithms
+   *
+   * The use of sun.misc.Unsafe API is discouraged. For the time being, using sun.misc.Unsafe to instantiate
+   * DaoAuthenticationProvider is a necessary workaround to avoid FIPS compliance issues caused by MD5 and SHA1.
+   * However, once we upgrade to Spring 6.x, we can switch to using the new constructor, passing a compliant PasswordEncoder.
+   * This will allow us to address the compliance issue more cleanly and avoid reliance on unsafe practices.
+   */
+  static DaoAuthenticationProvider authenticationProvider(UserDetailsService userDetailsService) {
+    try {
+      Class<?> c = Class.forName("sun.misc.Unsafe");
+      Field field = Arrays.stream(c.getDeclaredFields()).filter(f -> f.getName().equals("theUnsafe"))
+          .findFirst().orElseThrow(() -> new RuntimeException("Field not found"));
+      field.setAccessible(true);
+      Method allocateInstance = c.getDeclaredMethod("allocateInstance", Class.class);
+      DaoAuthenticationProvider authProvider =
+          (DaoAuthenticationProvider) allocateInstance.invoke(field.get(null), DaoAuthenticationProvider.class);
+      authProvider.setPasswordEncoder(createDelegatingPasswordEncoder());
+      authProvider.setUserDetailsService(userDetailsService);
+      authProvider.setUserCache(new NullUserCache());
+      authProvider.setAuthoritiesMapper(new NullAuthoritiesMapper());
+
+      // Setting custom pre and post authentication checks
+      authProvider.setPreAuthenticationChecks(new CustomPreAuthenticationChecks());
+      authProvider.setPostAuthenticationChecks(new CustomPostAuthenticationChecks());
+
+      Field loggerField = AbstractUserDetailsAuthenticationProvider.class.getDeclaredField("logger");
+      loggerField.setAccessible(true);
+      loggerField.set(authProvider, LogFactory.getLog(AbstractUserDetailsAuthenticationProvider.class));
+
+      return authProvider;
+    } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException
+        | NoSuchFieldException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  static PasswordEncoder createDelegatingPasswordEncoder() {
+    String encodingId = "bcrypt";
+    Map<String, PasswordEncoder> encoders = new HashMap<>();
+    encoders.put(encodingId, new BCryptPasswordEncoder());
+    encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: I was reviewing the [Encoders](https://docs.spring.io/spring-security/reference/features/authentication/password-storage.html#authentication-password-storage-pbkdf2) and it looks like we only have one choice for FIPS.
created_at: 2025-03-13T16:01:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: elcoya
body: @mule-niraj if possible, this constant value (now hardcoded) should be override-able. Is there any scenario where we can turn this into a value that is resolved based on a more flexible criteria? Can we have this as default but allow for a system property to define another?
created_at: 2025-03-13T18:49:50Z
author_association: NONE
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: elcoya
body: Just to make the idea a little more concrete, leave this value as the default, but allow for an override with a system property. For the time being, we don't even need to document this system property, but let's plan for contingencies.
created_at: 2025-03-13T20:11:24Z
author_association: NONE
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: acurci-at-mulesoft
body: Hi, @mule-niraj ,
I’ve been discussing this with @elcoya, and we believe the best approach is to have a default name (userService) while also allowing it to be overridden via a system property.
For now, we can leave this out of the documentation—at least until a customer requests this capability.
Could you add the system property and include a test to cover it?
Thanks!
created_at: 2025-03-13T20:18:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +109,12 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
    */
   @Override
   protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) throws BeansException {
+    if ("fips140-2".equals(System.getProperty("mule.security.model"))) {
+      if (name.contains(DaoAuthenticationProvider.class.getName()) || DaoAuthenticationProvider.class.equals(requiredType)) {
+        UserDetailsService userDetailsService = (UserDetailsService) super.getBean("userService");
path: module/src/main/java/org/mule/extension/spring/internal/beanfactory/ArtifactObjectsAwareBeanFactory.java
user: login: mule-niraj
body: @acurci-at-mulesoft and @elcoya, I've continued debugging the code and found a solution where we no longer need to use the system property to override the userService name. Instead, we can use `getBeanDefinition()` to retrieve the `DaoAuthenticationProvider` instance and access the userDetailsService from the `propertyValue` list provided by the user. I've implemented this change in the code. Could you both please review it? Thanks!
created_at: 2025-03-18T12:05:39Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqube-as-a-service[bot]
created_at: 2025-03-18T12:57:07Z
body: **SonarQube Quality Gate**

[![Quality Gate failed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonarqube.sfcq.buildndeliver-s.aws-esvc1-useast2.aws.sfdc.cl/dashboard?id=mulesoft.mule-core-extensions-mule-spring-module.gec&pullRequest=266)

[![Failed condition](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v97/checks/FailedConditionIcon-16px.png 'Failed condition')](https://sonarqube.sfcq.buildndeliver-s.aws-esvc1-useast2.aws.sfdc.cl/dashboard?id=mulesoft.mule-core-extensions-mule-spring-module.gec&pullRequest=266) 2.1% Line Coverage on New Code (is less than 80%)  

[See analysis details on SonarQube](https://sonarqube.sfcq.buildndeliver-s.aws-esvc1-useast2.aws.sfdc.cl/dashboard?id=mulesoft.mule-core-extensions-mule-spring-module.gec&pullRequest=266)


author_association: NONE