diff --git a/openid-connect-client/pom.xml b/openid-connect-client/pom.xml
index b891d4e0e6..847838aa6f 100644
--- a/openid-connect-client/pom.xml
+++ b/openid-connect-client/pom.xml
@@ -1,76 +1,83 @@
-
-
-
-
- 4.0.0
-
- openid-connect-parent
- org.mitre
- 1.3.4-SNAPSHOT
- ..
-
- openid-connect-client
- OpenID Connect Client filter for Spring Security
- OpenID Connect Client
-
-
- org.mitre
- openid-connect-common
-
-
- jar
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- ${java-version}
- ${java-version}
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
-
-
- attach-sources
-
- jar-no-fork
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
-
-
- attach-sources
-
- jar
-
-
-
-
-
-
-
+
+
+
+
+ 4.0.0
+
+ openid-connect-parent
+ org.mitre
+ 1.3.4-SNAPSHOT
+ ..
+
+ openid-connect-client
+ OpenID Connect Client filter for Spring Security
+ OpenID Connect Client
+
+
+ org.mitre
+ openid-connect-common
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ 2.9.9
+ test
+
+
+ jar
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java-version}
+ ${java-version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+
+ jar-no-fork
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+
diff --git a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java
index b311a84d9c..4e67f0f242 100644
--- a/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java
+++ b/openid-connect-client/src/main/java/org/mitre/oauth2/introspectingfilter/IntrospectingTokenService.java
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.net.URI;
import java.util.Calendar;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,7 +37,11 @@
import org.mitre.oauth2.model.RegisteredClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.core.Authentication;
@@ -309,7 +314,12 @@ protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOE
form.add("token", accessToken);
try {
- validatedToken = restTemplate.postForObject(introspectionUrl, form, String.class);
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
+
+ ResponseEntity response = restTemplate.exchange(introspectionUrl, HttpMethod.POST, new HttpEntity<>(form, headers), String.class);
+ validatedToken = response.getBody();
} catch (RestClientException rce) {
logger.error("validateToken", rce);
return null;
diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java
index 5f451c2dcb..f67212dcce 100644
--- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java
+++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/DynamicServerConfigurationService.java
@@ -27,6 +27,7 @@
import static org.mitre.util.JsonUtils.getAsString;
import static org.mitre.util.JsonUtils.getAsStringList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -37,6 +38,11 @@
import org.mitre.openid.connect.config.ServerConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.client.RestTemplate;
@@ -141,7 +147,9 @@ private class OpenIDConnectServiceConfigurationFetcher extends CacheLoader response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), String.class);
+ String jsonString = response.getBody();
JsonElement parsed = parser.parse(jsonString);
if (parsed.isJsonObject()) {
diff --git a/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestIntrospectingTokenService.java b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestIntrospectingTokenService.java
new file mode 100644
index 0000000000..6c80cf4517
--- /dev/null
+++ b/openid-connect-client/src/test/java/org/mitre/oauth2/introspectingfilter/TestIntrospectingTokenService.java
@@ -0,0 +1,132 @@
+package org.mitre.oauth2.introspectingfilter;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mitre.oauth2.introspectingfilter.service.IntrospectionConfigurationService;
+import org.mitre.oauth2.introspectingfilter.service.impl.JWTParsingIntrospectionConfigurationService;
+import org.mitre.oauth2.introspectingfilter.service.impl.StaticIntrospectionConfigurationService;
+import org.mitre.oauth2.model.RegisteredClient;
+import org.mitre.openid.connect.client.service.impl.DynamicServerConfigurationService;
+import org.mitre.openid.connect.config.ServerConfiguration;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.web.client.RestTemplate;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Loic Gangloff
+ *
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TestIntrospectingTokenService {
+
+
+ private IntrospectingTokenService service;
+
+ private String introspectionUrl = "http://www.example.com";
+ private RegisteredClient client = new RegisteredClient();
+
+ private String json = "{\"active\":true,\"scope\":\"sub openid profile\",\"exp\":1591344840,\"sub\":\"test@example.com\",\"username\":\"test@example.com\",\"expires_at\":\"2020-06-05T10:14:00+0200\",\"client_id\":\"a-client-id\",\"token_type\":\"Bearer\"}";
+
+ private String xml = ""
+ + "" +
+ "true" +
+ "a-client-id" +
+ "1591344840n" +
+ "2020-06-05T10:14:00+0200" +
+ "sub openid profile" +
+ "test@example.com" +
+ "Bearer" +
+ "test@example.com"
+ + "";
+
+ @Mock
+ private HttpClient mockHttpClient;
+
+ @Before
+ public void prepare() {
+ client.setClientId("a-client-id");
+ client.setClientSecret("a-client-secret");
+
+ StaticIntrospectionConfigurationService introspectionConfig = new StaticIntrospectionConfigurationService();
+ introspectionConfig.setClientConfiguration(client);
+ introspectionConfig.setIntrospectionUrl(introspectionUrl);
+
+ service = new IntrospectingTokenService(mockHttpClient);
+ service.setIntrospectionConfigurationService(introspectionConfig);
+ }
+
+
+ @Test
+ public void resttemplate_must_have_xml_accept_header() throws IOException {
+
+ HttpResponse response = Mockito.mock(HttpResponse.class);
+ StatusLine statusLine = Mockito.mock(StatusLine.class);
+ Mockito.when(statusLine.getStatusCode()).thenReturn(200);
+ Mockito.when(response.getAllHeaders()).thenReturn(new Header[] {});
+ Mockito.when(response.getStatusLine()).thenReturn(statusLine);
+ Mockito.when(response.getEntity()).thenReturn(new StringEntity(json));
+ Mockito.when(mockHttpClient.execute(Mockito.any(), (HttpContext) Mockito.any())).thenReturn(response);
+
+ RestTemplate restemplate = Mockito.spy(new RestTemplate(new HttpComponentsClientHttpRequestFactory(mockHttpClient)));
+
+ restemplate.postForObject(introspectionUrl, "a-token", String.class);
+
+ ArgumentCaptor argument = ArgumentCaptor.forClass(HttpPost.class);
+ Mockito.verify(mockHttpClient).execute(argument.capture(), (HttpContext) Mockito.any());
+
+
+ Header acceptHeader = argument.getValue().getFirstHeader("Accept");
+ List mediaTypes = MediaType.parseMediaTypes(acceptHeader.getValue());
+
+ assertThat(mediaTypes, hasItem(MediaType.APPLICATION_JSON));
+ assertThat(mediaTypes, hasItem(MediaType.APPLICATION_XML));
+
+ }
+
+ @Test
+ public void introspectingtokenservice_must_not_have_xml_accept_header() throws IOException {
+
+ HttpResponse response = Mockito.mock(HttpResponse.class);
+ StatusLine statusLine = Mockito.mock(StatusLine.class);
+ Mockito.when(statusLine.getStatusCode()).thenReturn(200);
+ Mockito.when(response.getAllHeaders()).thenReturn(new Header[] {});
+ Mockito.when(response.getStatusLine()).thenReturn(statusLine);
+ Mockito.when(response.getEntity()).thenReturn(new StringEntity(json));
+ Mockito.when(mockHttpClient.execute(Mockito.any(), (HttpContext) Mockito.any())).thenReturn(response);
+
+ OAuth2Authentication result = service.loadAuthentication("a-token");
+
+ ArgumentCaptor argument = ArgumentCaptor.forClass(HttpPost.class);
+ Mockito.verify(mockHttpClient).execute(argument.capture(), (HttpContext) Mockito.any());
+
+
+ Header acceptHeader = argument.getValue().getFirstHeader("Accept");
+ List mediaTypes = MediaType.parseMediaTypes(acceptHeader.getValue());
+
+ assertThat(mediaTypes, hasItem(MediaType.APPLICATION_JSON));
+ assertThat(mediaTypes, not(hasItem(MediaType.APPLICATION_XML)));
+
+ }
+
+}
diff --git a/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestDynamicServerConfigurationService.java b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestDynamicServerConfigurationService.java
new file mode 100644
index 0000000000..a6dd1bcd8d
--- /dev/null
+++ b/openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestDynamicServerConfigurationService.java
@@ -0,0 +1,114 @@
+package org.mitre.openid.connect.client.service.impl;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.StatusLine;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mitre.openid.connect.config.ServerConfiguration;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Loic Gangloff
+ *
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TestDynamicServerConfigurationService {
+
+
+ private DynamicServerConfigurationService service;
+
+ private String issuer = "https://www.example.com/";
+
+
+ private String json = "{\"issuer\": \"https://www.example.com/\"}";
+
+ private String xml = ""
+ + ""
+ + "https://www.example.com/"
+ + "";
+
+ @Mock
+ private HttpClient mockHttpClient;
+
+ @Before
+ public void prepare() {
+ service = new DynamicServerConfigurationService(mockHttpClient);
+ }
+
+
+ @Test
+ public void resttemplate_must_have_xml_accept_header() throws ClientProtocolException, IOException {
+
+ HttpResponse response = Mockito.mock(HttpResponse.class);
+ StatusLine statusLine = Mockito.mock(StatusLine.class);
+ Mockito.when(statusLine.getStatusCode()).thenReturn(200);
+ Mockito.when(response.getAllHeaders()).thenReturn(new Header[] {});
+ Mockito.when(response.getStatusLine()).thenReturn(statusLine);
+ Mockito.when(response.getEntity()).thenReturn(new StringEntity(json));
+ Mockito.when(mockHttpClient.execute(Mockito.any(), (HttpContext) Mockito.any())).thenReturn(response);
+
+ RestTemplate restemplate = Mockito.spy(new RestTemplate(new HttpComponentsClientHttpRequestFactory(mockHttpClient)));
+
+ restemplate.getForObject(issuer, String.class);
+
+ ArgumentCaptor argument = ArgumentCaptor.forClass(HttpGet.class);
+ Mockito.verify(mockHttpClient).execute(argument.capture(), (HttpContext) Mockito.any());
+
+
+ Header acceptHeader = argument.getValue().getFirstHeader("Accept");
+ List mediaTypes = MediaType.parseMediaTypes(acceptHeader.getValue());
+
+ assertThat(mediaTypes, hasItem(MediaType.APPLICATION_JSON));
+ assertThat(mediaTypes, hasItem(MediaType.APPLICATION_XML));
+
+ }
+
+ @Test
+ public void serverconfiguration_must_not_have_xml_accept_header() throws ClientProtocolException, IOException {
+
+ HttpResponse response = Mockito.mock(HttpResponse.class);
+ StatusLine statusLine = Mockito.mock(StatusLine.class);
+ Mockito.when(statusLine.getStatusCode()).thenReturn(200);
+ Mockito.when(response.getAllHeaders()).thenReturn(new Header[] {});
+ Mockito.when(response.getStatusLine()).thenReturn(statusLine);
+ Mockito.when(response.getEntity()).thenReturn(new StringEntity(json));
+ Mockito.when(mockHttpClient.execute(Mockito.any(), (HttpContext) Mockito.any())).thenReturn(response);
+
+ ServerConfiguration result = service.getServerConfiguration(issuer);
+
+ ArgumentCaptor argument = ArgumentCaptor.forClass(HttpGet.class);
+ Mockito.verify(mockHttpClient).execute(argument.capture(), (HttpContext) Mockito.any());
+
+
+ Header acceptHeader = argument.getValue().getFirstHeader("Accept");
+ List mediaTypes = MediaType.parseMediaTypes(acceptHeader.getValue());
+
+ assertThat(mediaTypes, hasItem(MediaType.APPLICATION_JSON));
+ assertThat(mediaTypes, not(hasItem(MediaType.APPLICATION_XML)));
+
+ assertThat(result.getIssuer(), is(equalTo(issuer)));
+ }
+
+}