Describe the bug

When one wants to use the Argon2PasswordEncoder which is available in Spring Security the following exception is being thrown:

java.lang.NoClassDefFoundError: org/bouncycastle/crypto/params/Argon2Parameters$Builder
    at org.springframework.security.crypto.argon2.Argon2PasswordEncoder.encode(Argon2PasswordEncoder.java:78) ~[spring-security-core-5.3.3.RELEASE.jar:5.3.3.RELEASE]
    at eu.balev.argondemo.ArgondemoApplicationInit.run(ArgondemoApplicationInit.java:18) ~[main/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) ~[spring-boot-2.3.2.BUILD-SNAPSHOT.jar:2.3.2.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) ~[spring-boot-2.3.2.BUILD-SNAPSHOT.jar:2.3.2.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.3.2.BUILD-SNAPSHOT.jar:2.3.2.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.2.BUILD-SNAPSHOT.jar:2.3.2.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.2.BUILD-SNAPSHOT.jar:2.3.2.BUILD-SNAPSHOT]
    at eu.balev.argondemo.ArgondemoApplication.main(ArgondemoApplication.java:10) ~[main/:na]
Caused by: java.lang.ClassNotFoundException: org.bouncycastle.crypto.params.Argon2Parameters$Builder
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[na:na]
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
    ... 8 common frames omitted

This can be mitigated by explicitly adding a dependency to bouncy castle, e.g. if you use gradle:

implementation 'org.bouncycastle:bcprov-jdk15on:1.64'

To Reproduce

For example you can define a bean and try to encode a pass word using this bean:

  @Bean
  public PasswordEncoder myPasswordEncoder() {
    return new Argon2PasswordEncoder();
  }
@Component
public class ArgondemoApplicationInit implements CommandLineRunner {

  final PasswordEncoder passwordEncoder;

  public ArgondemoApplicationInit(PasswordEncoder passwordEncoder) {
    this.passwordEncoder = passwordEncoder;
  }

  @Override
  public void run(String... args) throws Exception {
    System.out.println(passwordEncoder.encode("topsecret"));
  }
}

Expected behavior

No exception is thrown and no additional dependencies are needed except the dependency to the spring security.

Sample

Minimal, Reproducible sample.

To reproduce clone and run:

./gradlew bootRun

Comment From: jgrandja

@luchob This behaviour is expected since BouncyCastle is declared as an optional dependency. Not all spring security deployments require BouncyCastle hence it being optional. If you are using a feature within Spring Security that requires BouncyCastle (Argon2PasswordEncoder) then you need to explicitly declare it. I'm going to close this issue since this behaviour is expected.