spring-projects/spring-security · warning

User.withDefaultPasswordEncoder() is considered unsafe for…

Error message

User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications.

What it means

User.withDefaultPasswordEncoder() is a deprecated convenience factory that builds a User with a delegating password encoder. Because a plain-text default password encoding is insecure, calling it logs this warning; it is intended only for demos and samples.

Solutions

  1. Use User.withUsername(...).password(encoder.encode(rawPassword)) with an explicitly configured PasswordEncoder (e.g. BCryptPasswordEncoder or DelegatingPasswordEncoder)
  2. Use PasswordEncoderFactories.createDelegatingPasswordEncoder() and store {bcrypt}-prefixed hashes
  3. Keep withDefaultPasswordEncoder only in non-production sample code

Example fix

// before
User user = User.withDefaultPasswordEncoder()
    .username("user").password("password").roles("USER").build();
// after
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
User user = User.withUsername("user")
    .password(encoder.encode("password")).roles("USER").build();
Defensive patterns

Strategy: validation

Validate before calling

// Reject the insecure builder in your own code via an ArchUnit/checkstyle rule or review gate
if (stackContains("withDefaultPasswordEncoder")) {
  throw new IllegalStateException("User.withDefaultPasswordEncoder() is not allowed in production code");
}

Prevention

When it happens

Trigger: Any invocation of User.withDefaultPasswordEncoder(), typically in test/demo code such as User.withDefaultPasswordEncoder().username("user").password("pass").roles("USER").build().

Common situations: Copy-pasted sample configs copied into production; tutorials using the convenience builder; quick local prototypes.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/4e49b1290b2d537d. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/springframework/security/core/userdetails/User.java:283

	 *
	 * <pre>
	 * <code>
	 * UserDetails user = User.withUsername("user")
	 *     .password("{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG")
	 *     .roles("USER")
	 *     .build();
	 * </code> </pre>
	 * @return a UserBuilder that automatically encodes the password with the default
	 * PasswordEncoder
	 * @deprecated Using this method is not considered safe for production, but is
	 * acceptable for demos and getting started. For production purposes, ensure the
	 * password is encoded externally. See the method Javadoc for additional details.
	 * There are no plans to remove this support. It is deprecated to indicate that this
	 * is considered insecure for production purposes.
	 */
	@Deprecated
	public static UserBuilder withDefaultPasswordEncoder() {
		logger.warn("User.withDefaultPasswordEncoder() is considered unsafe for production "
				+ "and is only intended for sample applications.");
		PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
		return builder().passwordEncoder(encoder::encode);
	}

	public static UserBuilder withUserDetails(UserDetails userDetails) {
		// @formatter:off
		UserBuilder result = withUsername(userDetails.getUsername())
				.accountExpired(!userDetails.isAccountNonExpired())
				.accountLocked(!userDetails.isAccountNonLocked())
				.authorities(userDetails.getAuthorities())
				.credentialsExpired(!userDetails.isCredentialsNonExpired())
				.disabled(!userDetails.isEnabled());
		// @formatter:on
		if (userDetails.getPassword() != null) {
			result.password(userDetails.getPassword());
		}
		return result;

View on GitHub (pinned to 96852e8860)