spring-projects / spring-projects/spring-security
Stub the call to OpenID configuration in an `oauth2Client` `@SpringBootTest`
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.6k
- Forks
- 6.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 52
Description
Expected Behavior
Easy way to avoid the call to an OP /.well-known/openid-configuration in a @SpringBootTest of an application configured with oauth2Client (or oauth2Login).
Context
When working with mocked Authentication instances (using MockMvc request post processors, WebTestClient mutators, or test annotations), no communication with the authorization server should be needed. However, in the case of a @SpringBootTest for an application configured for OAuth2 with an OP issuer URI, the OpenID configuration is fetched eagerly during application context initialisation.
I found two options, but neither is as convenient as declaring a @MockitoBean for a Spring Boot @ConditionalOnMissingBean like we can do for the (Reactive)JwtDecoder in an oauth2ResourceServer:
- Testcontainers, but this is super slow and completely overkill to provide no more than OpenID configuration
- Wiremock, lighter and faster than Testcontainers, but still requires additional dependencies, adds some overhead, and requires more configuration than a
@MockitoBean(declare astatic WireMockServer, a@DynamicPropertySourceto bind the issuer URI to this server base URL, and@BeforeAll/@AfterAllto start & stop the mocked server)
Edit
Found a @TestConfiguration that should fit most needs without faking an IDP (super fast startup):
@TestConfiguration
@Import({OAuth2ClientProperties.class})
public class MockedOAuth2ClientTestConfiguration {
@Bean
ClientRegistrationRepository clientRegistrationRepository(
OAuth2ClientProperties oauth2ClientProperties) {
return new InMemoryClientRegistrationRepository(
oauth2ClientProperties.getRegistration().entrySet().stream().map(entry -> {
var registrationId = entry.getKey();
var registration = entry.getValue();
return ClientRegistration
.withRegistrationId(registrationId)
.authorizationGrantType(
new AuthorizationGrantType(registration.getAuthorizationGrantType()))
.clientId(registration.getClientId())
.clientSecret(registration.getClientSecret())
.tokenUri("https://test.idp/token")
.authorizationUri("https://test.idp/auth")
.redirectUri("https://client/oauth2/%s/code".formatted(registrationId))
.build();
}).toList());
}
}
With this conf, the default InMemoryClientRegistrationRepository instantiation won't prevent the app from starting, and beans looking for a registration at startup will find it.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by inspecting the OAuth2 client auto-configuration and the eager OpenID configuration lookup during application context initialization; the issue names no source files or tests. Done means an @SpringBootTest using oauth2Client or oauth2Login can use mocked authentication without contacting the authorization server, while application beans can still find a client registration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring-boot
- Domain
- authentication, security, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100