|
|
|
|
@ -581,6 +581,39 @@ public class ClientRegistrationsTests {
@@ -581,6 +581,39 @@ public class ClientRegistrationsTests {
|
|
|
|
|
assertThat(oidcRfc8414.getHost()).isEqualTo("elated_sutherland"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void issuerWhenOidcHtmlThenFallbackToOAuth2ThenSuccess() throws Exception { |
|
|
|
|
ClientRegistration registration = registrationOAuth2WithOidcHtml("issuer1", null).build(); |
|
|
|
|
ClientRegistration.ProviderDetails provider = registration.getProviderDetails(); |
|
|
|
|
assertThat(provider.getAuthorizationUri()).isEqualTo("https://example.com/o/oauth2/v2/auth"); |
|
|
|
|
assertThat(provider.getTokenUri()).isEqualTo("https://example.com/oauth2/v4/token"); |
|
|
|
|
assertThat(provider.getIssuerUri()).isEqualTo(this.issuer); |
|
|
|
|
|
|
|
|
|
// order: OIDC(issuer-prefixed) -> OIDC(host-prefixed) -> OAuth
|
|
|
|
|
RecordedRequest request1 = this.server.takeRequest(); |
|
|
|
|
assertThat(request1.getPath()).isEqualTo("/issuer1/.well-known/openid-configuration"); |
|
|
|
|
RecordedRequest request2 = this.server.takeRequest(); |
|
|
|
|
assertThat(request2.getPath()).isEqualTo("/.well-known/openid-configuration/issuer1"); |
|
|
|
|
RecordedRequest request3 = this.server.takeRequest(); |
|
|
|
|
assertThat(request3.getPath()).isEqualTo("/.well-known/oauth-authorization-server/issuer1"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void issuerWhenFirstEndpoint5xxThenThrowsIllegalArgumentException() throws Exception { |
|
|
|
|
this.issuer = createIssuerFromServer("issuer1"); |
|
|
|
|
this.server.setDispatcher(new Dispatcher() { |
|
|
|
|
@Override |
|
|
|
|
public MockResponse dispatch(RecordedRequest req) { |
|
|
|
|
return switch (req.getPath()) { |
|
|
|
|
case "/issuer1/.well-known/openid-configuration" -> new MockResponse().setResponseCode(500); |
|
|
|
|
default -> new MockResponse().setResponseCode(404); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
assertThatIllegalArgumentException() |
|
|
|
|
.isThrownBy(() -> ClientRegistrations.fromIssuerLocation(this.issuer).build()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
public void issuerWhenAllEndpointsFailedThenExceptionIncludesFailureInformation() { |
|
|
|
|
this.issuer = createIssuerFromServer("issuer1"); |
|
|
|
|
@ -673,6 +706,41 @@ public class ClientRegistrationsTests {
@@ -673,6 +706,41 @@ public class ClientRegistrationsTests {
|
|
|
|
|
return ClientRegistrations.fromIssuerLocation(this.issuer).clientId("client-id").clientSecret("client-secret"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Simulates a situation when the OIDC discovery endpoints |
|
|
|
|
* "/issuer1/.well-known/openid-configuration" and |
|
|
|
|
* "/.well-known/openid-configuration/issuer1" respond with HTTP 200 and text/html |
|
|
|
|
* (non-JSON), so discovery falls back to |
|
|
|
|
* "/.well-known/oauth-authorization-server/issuer1", which responds with HTTP 200 and |
|
|
|
|
* JSON. |
|
|
|
|
* |
|
|
|
|
* @see <a href="https://tools.ietf.org/html/rfc8414#section-3.1">Section 3.1</a> |
|
|
|
|
* @see <a href="https://tools.ietf.org/html/rfc8414#section-5">Section 5</a> |
|
|
|
|
*/ |
|
|
|
|
private ClientRegistration.Builder registrationOAuth2WithOidcHtml(String path, String body) throws Exception { |
|
|
|
|
this.issuer = createIssuerFromServer(path); |
|
|
|
|
this.response.put("issuer", this.issuer); |
|
|
|
|
String responseBody = (body != null) ? body : this.mapper.writeValueAsString(this.response); |
|
|
|
|
final Dispatcher dispatcher = new Dispatcher() { |
|
|
|
|
@Override |
|
|
|
|
public MockResponse dispatch(RecordedRequest request) { |
|
|
|
|
return switch (request.getPath()) { |
|
|
|
|
case "/issuer1/.well-known/openid-configuration", "/.well-known/openid-configuration/issuer1", |
|
|
|
|
"/.well-known/openid-configuration/" -> |
|
|
|
|
new MockResponse().setResponseCode(200) |
|
|
|
|
.setBody("<html>not json</html>") |
|
|
|
|
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE); |
|
|
|
|
case "/.well-known/oauth-authorization-server/issuer1", |
|
|
|
|
"/.well-known/oauth-authorization-server/" -> |
|
|
|
|
buildSuccessMockResponse(responseBody); |
|
|
|
|
default -> new MockResponse().setResponseCode(404); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
this.server.setDispatcher(dispatcher); |
|
|
|
|
return ClientRegistrations.fromIssuerLocation(this.issuer).clientId("client-id").clientSecret("client-secret"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private MockResponse buildSuccessMockResponse(String body) { |
|
|
|
|
// @formatter:off
|
|
|
|
|
return new MockResponse().setResponseCode(200) |
|
|
|
|
|