I just encountered a problem with property overriding when I tried to override the client-id of the opaque-token property of the resourceserver configuration in Spring Security.
In my code I am loading the value as following via an @Value annotation, in one of my configuration classes:
@Value("${spring.security.oauth2.resourceserver.opaque-token.client-id}")
This is in accordance with the documented naming convention for the key as can be seen here: https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/opaque-token.html#oauth2resourceserver-opaque-introspectionuri
Please observe, that both opaque-token and client-id use a hyphen in their name.
If I place the correct value for this key directly into the application.yaml file then everything works as expected. However, I wanted to override this value using the relaxed binding rules for environment variables and used the following variable name:
SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUE_TOKEN_CLIENT_ID
However this did now work, and after some debugging I found that specifically the ReactiveOAuth2ResourceServerOpaqueTokenConfiguration (see https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerOpaqueTokenConfiguration.java) was not receiving the overwritten value, and it appears that the reason is, that this class is using a different key format for loading the resource server properties, which is:
@ConditionalOnProperty(name = "spring.security.oauth2.resourceserver.opaquetoken.introspection-uri")
Observe, that there the opaquetoken is not using a hyphen. I then realized, that according to the relaxed binding convention, I should maybe remove the underscores in placed where a hyphen is used and I changed the environment variable name to the following:
SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTID
This did not work for two reasons:
1. The client-id was no longer correctly bound, since I removed the underscore also from CLIENT_ID.
2. My own annotation was still using the opaque-token format (with a hyphen).
After some experiments with different placements of underscores and hyphens, I found that the only working configuration for me was the following:
- In my
application.yamlfile I had to remove the hyphen fromopaque-tokenand define it asopaquetoken(which is different from the documented format in the link at the top). - In my own configuration classes I had to adjust the value annotation and load the client id via
@Value("${spring.security.oauth2.resourceserver.opaquetoken.client-id}") - I had to change the environment variable and use the following format:
SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID(not that theOPAQUETOKENpart is without underscore, but theCLIENT_IDpart uses an underscore, which strictly speaking is not how the relaxed binding convention for environment variables is documented.
The original reason, why I had to look into this, is because I was being hit by the same error as described in this issue, since the client-id was not correctly configured in my resource server: https://github.com/spring-projects/spring-security/issues/7858
To Reproduce 1. Configure a resource server with spring security. 2. Define a default opaque-token.client-id in the application.yaml for the resource server 3. Then try to override the client-id of the opaque-token.client-id using an environment variable 5. Observer that the old client-id is being used.
Expected behavior
1. Overriding works correctly
2. Consistent use of opaque-token vs. opaquetoken in documentation and internal implementation.
May I request a clarification on the following items:
- If the use of
opaquetokenoveropaque-tokenin theReactiveOAuth2ResourceServerOpaqueTokenConfigurationis considered correct. - If the recommended format of the relaxed binding environment variable name should be:
a)
SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTIDor b)SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_IDor c)SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUE_TOKEN_CLIENT_IDor Only b) worked for me. - If I should follow the documentation and use
opaque-tokenin theapplication.yamlor if ratheropaquetokenshould be used.
Comment From: sjohnr
@s-geiger-si thanks for reaching out!
It appears that the change from opaque-token to opaquetoken in Spring Boot was intentional, see this commit. Further, this was done after the documentation in Spring Security (a separate project) was written, and a corresponding change in our docs wasn't made.
I can't comment authoritatively on why this was done, but I believe the Boot team has a convention to not include hyphens in any properties namespaces, only property value keys are allowed to have hyphens. You'll need to confirm that with the Boot team if you have questions. If you have further questions about relaxed binding, please also consult with the Boot team by opening a question on stackoverflow.
The only actionable takeaway from this ticket that I see is to update the documentation to remove the hyphen in opaque-token. Would you by chance be interested in submitting a PR?