Skip to content

Fake UserDetailsService if none is specified is unnecessary #14632

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

Closed
NadChel opened this issue Feb 17, 2024 · 2 comments
Closed

Fake UserDetailsService if none is specified is unnecessary #14632

NadChel opened this issue Feb 17, 2024 · 2 comments
Assignees
Labels
in: config An issue in spring-security-config status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@NadChel
Copy link

NadChel commented Feb 17, 2024

If I have a security application that doesn't actually perform any authentication and just parses an Authorization header for a JWT token (a separate service that issues them may, on the other hand, perform some authentication), I'm unlikly to actually register any AuthenticationManagers or UserDetailsServices. As a result, I will likely trigger all these conditionals and have a pointless UserDetailsService that matches against its in-memory map of one fake user in my context

@AutoConfiguration(before = ReactiveSecurityAutoConfiguration.class, after = RSocketMessagingAutoConfiguration.class)
@ConditionalOnClass({ ReactiveAuthenticationManager.class })
@ConditionalOnMissingClass({ "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
		"org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector" })
@ConditionalOnMissingBean(
		value = { ReactiveAuthenticationManager.class, ReactiveUserDetailsService.class,
				ReactiveAuthenticationManagerResolver.class },
		type = { "org.springframework.security.oauth2.jwt.ReactiveJwtDecoder" })
@Conditional(ReactiveUserDetailsServiceAutoConfiguration.ReactiveUserDetailsServiceCondition.class)
@EnableConfigurationProperties(SecurityProperties.class)
public class ReactiveUserDetailsServiceAutoConfiguration {
// SecurityProperties

	public static class User {

		/**
		 * Default user name.
		 */
		private String name = "user";

		/**
		 * Password for the default user name.
		 */
		private String password = UUID.randomUUID().toString();

Besides, it reflects on my console output (in case the password stays a random UUID, the config prints this info message):

INFO 4528 --- [dynamic-gateway] [           main] ctiveUserDetailsServiceAutoConfiguration : 

Using generated security password: 1d4b62fc-c703-4df9-a35f-8de5d5c7baab

It's not a tragedy since I don't inject it anywhere, but it feels wrong. I could register some stub AuthenticationManager to avoid a match, but it's a kludge. Frankly, I don't see any purpose in extending Spring's autoconfiguration magic to UserDetailsService. Even when you only start learning Spring Security, you can easily register some simple implementation, as you showed in your tutorial. In fact, it's even less straightforward for a beginner to go looking in their console output for the default password for their default user (which they may never suspect about)

@NadChel NadChel added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Feb 17, 2024
@jzheaux
Copy link
Contributor

jzheaux commented Mar 4, 2024

If I have a security application that doesn't actually perform any authentication and just parses an Authorization header for a JWT token (a separate service that issues them may, on the other hand, perform some authentication), I'm unlikly to actually register any AuthenticationManagers or UserDetailsServices.

I'm not sure I agree with this, at least not as I've understood you so far.

I do not recommend simply parsing a token and not validating it (checking its signature, its expiry, etc.). It's important to validate the token you've received and not simply trust the client. In your case outlined above, I'd recommend you configure a ReactiveJwtDecoder which would remove the default UserDetailsService.

That said, if you have neither an AuthenticationManager, UserDetailsService, or any other Spring Security authentication mechanism, then you are correct that Spring Security will add a reasonable default in case any of its filters are used at runtime. We don't want Spring Security filters' OOTB configuration to allow for issuing an authentication result on no grounds at all.

However, if you want to remove that protection, you can disable the auto-configuration in the following way:

@SpringBootApplication(exclude=ReactiveUserDetailsServiceAutoConfiguration.class)

In fact, it's even less straightforward for a beginner to go looking in their console output for the default password for their default user (which they may never suspect about)

I think this is a fair point. Perhaps we should consider it as part of #14663 to further demystify the configuration choices Spring Security makes.

I'll close this for now. Please add more information as needed and we can continue chatting.

@jzheaux jzheaux closed this as completed Mar 4, 2024
@jzheaux jzheaux added in: config An issue in spring-security-config status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged labels Mar 4, 2024
@jzheaux jzheaux self-assigned this Mar 4, 2024
@NadChel
Copy link
Author

NadChel commented Mar 5, 2024

I do not recommend simply parsing a token and not validating it (checking its signature, its expiry, etc.). It's important to validate the token you've received and not simply trust the client. In your case outlined above, I'd recommend you configure a ReactiveJwtDecoder which would remove the default UserDetailsService.

I'm not sure token validation counts as authentication. The parser I use (supplied by Jwts) automatically validates the claims and throws if the token is expired, not properly signed, etc. As I see it, extraction of claims and authentication of claims are two separate things (which, btw, should probably be performed by separate filters when authentication does occur in a given app)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: config An issue in spring-security-config status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants