mirror of https://github.com/jacekkow/keycloak-protocol-cas

Jacek Kowalski
2023-11-24 6fff26d1517dbcec6dfb3f181bda418577ea3b17
ContextTypeHelper: do account for the "Accept" header (per CAS specs)
3 files modified
60 ■■■■■ changed files
src/main/java/org/keycloak/protocol/cas/endpoints/ServiceValidateEndpoint.java 2 ●●● patch | view | raw | blame | history
src/main/java/org/keycloak/protocol/cas/utils/ContentTypeHelper.java 26 ●●●●● patch | view | raw | blame | history
src/test/java/org/keycloak/protocol/cas/ContentTypeHelperTest.java 32 ●●●● patch | view | raw | blame | history
src/main/java/org/keycloak/protocol/cas/endpoints/ServiceValidateEndpoint.java
@@ -37,7 +37,7 @@
    }
    private Response prepare(Response.Status status, CASServiceResponse serviceResponse) {
        MediaType responseMediaType = new ContentTypeHelper(request, restRequest, session.getContext().getUri()).selectResponseType();
        MediaType responseMediaType = new ContentTypeHelper(session.getContext().getUri()).selectResponseType();
        return ServiceResponseHelper.createResponse(status, responseMediaType, serviceResponse);
    }
}
src/main/java/org/keycloak/protocol/cas/utils/ContentTypeHelper.java
@@ -1,33 +1,27 @@
package org.keycloak.protocol.cas.utils;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.core.*;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.protocol.cas.CASLoginProtocol;
import org.keycloak.protocol.cas.representations.CASErrorCode;
public class ContentTypeHelper {
    private final HttpRequest request;
    private final Request restRequest;
    private final UriInfo uriInfo;
    public ContentTypeHelper(HttpRequest request, Request restRequest, UriInfo uriInfo) {
        this.request = request;
        this.restRequest = restRequest;
    public ContentTypeHelper(UriInfo uriInfo) {
        this.uriInfo = uriInfo;
    }
    public MediaType selectResponseType() {
        String format = uriInfo.getQueryParameters().getFirst(CASLoginProtocol.FORMAT_PARAM);
        if (format != null && !format.isEmpty()) {
            //if parameter is set, it overrides all header values (see spec section 2.5.1)
            request.getMutableHeaders().putSingle(HttpHeaders.ACCEPT, "application/" + format.toLowerCase());
            if (format.equalsIgnoreCase("json")) {
                return MediaType.APPLICATION_JSON_TYPE;
            } else if (format.equalsIgnoreCase("xml")) {
                return MediaType.APPLICATION_XML_TYPE;
            } else {
                throw new CASValidationException(CASErrorCode.INVALID_REQUEST, "Unsupported value of parameter " + CASLoginProtocol.FORMAT_PARAM, Response.Status.BAD_REQUEST);
            }
        }
        try {
            Variant variant = restRequest.selectVariant(Variant.mediaTypes(MediaType.APPLICATION_XML_TYPE, MediaType.APPLICATION_JSON_TYPE).build());
            return variant == null ? MediaType.APPLICATION_XML_TYPE : variant.getMediaType();
        } catch (BadRequestException e) {
            //the default Accept header set by java.net.HttpURLConnection is invalid (cf. RESTEASY-960)
            return MediaType.APPLICATION_XML_TYPE;
        }
        return MediaType.APPLICATION_XML_TYPE;
    }
}
src/test/java/org/keycloak/protocol/cas/ContentTypeHelperTest.java
@@ -13,33 +13,15 @@
public class ContentTypeHelperTest {
    @Test
    public void test() throws Exception {
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/", null).selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/?format=json", null).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/?format=xml", null).selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/?format=JSON", null).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/?format=XML", null).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/", MediaType.APPLICATION_XML).selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/?format=json", MediaType.APPLICATION_XML).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/?format=xml", MediaType.APPLICATION_XML).selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/", MediaType.APPLICATION_JSON).selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/?format=json", MediaType.APPLICATION_JSON).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/?format=xml", MediaType.APPLICATION_JSON).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/", MediaType.TEXT_PLAIN).selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2").selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/").selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/?format=json").selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/?format=xml").selectResponseType());
        assertEquals(MediaType.APPLICATION_JSON_TYPE, get("http://example.com/?format=JSON").selectResponseType());
        assertEquals(MediaType.APPLICATION_XML_TYPE, get("http://example.com/?format=XML").selectResponseType());
    }
    private ContentTypeHelper get(String uri, String acceptHeader) throws Exception {
    private ContentTypeHelper get(String uri) throws Exception {
        MockHttpRequest req = MockHttpRequest.get(uri);
        MockHttpResponse res = new MockHttpResponse();
        RequestImpl restReq = new RequestImpl(req, res);
        if (acceptHeader != null) {
            req = req.header(HttpHeaders.ACCEPT, acceptHeader);
        }
        return new ContentTypeHelper(req, restReq, req.getUri());
        return new ContentTypeHelper(req.getUri());
    }
}