From 755fd78fa0ee0f2a67417a119382c63e02c1091e Mon Sep 17 00:00:00 2001
From: Alexandre Rocha Wendling <alexandrerw@celepar.pr.gov.br>
Date: Tue, 16 Jul 2024 14:15:23 +0000
Subject: [PATCH] Proxy ticket service and proxy ticket validation Proxy endpoints improvements suggested by Jacek Kowalski Add ticket type to storage key Rename isreuse to isReusable Remove "parsing" of "codeUUID" that is String, not UUID Improve error reporting in CAS ticket validation

---
 src/test/java/org/keycloak/protocol/cas/ServiceResponseTest.java |  107 +++++++++++++++++++++++++++++------------------------
 1 files changed, 58 insertions(+), 49 deletions(-)

diff --git a/src/test/java/org/keycloak/protocol/cas/ServiceResponseTest.java b/src/test/java/org/keycloak/protocol/cas/ServiceResponseTest.java
index 4e07135..29ea43a 100644
--- a/src/test/java/org/keycloak/protocol/cas/ServiceResponseTest.java
+++ b/src/test/java/org/keycloak/protocol/cas/ServiceResponseTest.java
@@ -1,59 +1,28 @@
 package org.keycloak.protocol.cas;
 
+import com.jayway.jsonpath.JsonPath;
 import org.junit.Test;
 import org.keycloak.protocol.cas.representations.CASErrorCode;
 import org.keycloak.protocol.cas.representations.CASServiceResponse;
 import org.keycloak.protocol.cas.utils.ServiceResponseHelper;
 import org.keycloak.protocol.cas.utils.ServiceResponseMarshaller;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xmlunit.xpath.JAXPXPathEngine;
+import org.xmlunit.xpath.XPathEngine;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
 
 import static org.junit.Assert.assertEquals;
+import static org.keycloak.protocol.cas.XMLValidator.parseAndValidate;
+import static org.keycloak.protocol.cas.XMLValidator.schemaFromClassPath;
 
 public class ServiceResponseTest {
-    private static final String EXPECTED_JSON_SUCCESS = "{\n" +
-            "  \"serviceResponse\" : {\n" +
-            "    \"authenticationSuccess\" : {\n" +
-            "      \"user\" : \"username\",\n" +
-            "      \"proxyGrantingTicket\" : \"PGTIOU-test\",\n" +
-            "      \"proxies\" : [ \"https://proxy1/pgtUrl\", \"https://proxy2/pgtUrl\" ],\n" +
-            "      \"attributes\" : {\n" +
-            "        \"string\" : \"abc\",\n" +
-            "        \"list\" : [ \"a\", \"b\" ],\n" +
-            "        \"int\" : 123\n" +
-            "      }\n" +
-            "    }\n" +
-            "  }\n" +
-            "}";
-    private static final String EXPECTED_XML_SUCCESS = "<cas:serviceResponse xmlns:cas=\"http://www.yale.edu/tp/cas\">\n" +
-            "    <cas:authenticationSuccess>\n" +
-            "        <cas:user>username</cas:user>\n" +
-            "        <cas:proxyGrantingTicket>PGTIOU-test</cas:proxyGrantingTicket>\n" +
-            "        <cas:proxies>\n" +
-            "            <cas:proxy>https://proxy1/pgtUrl</cas:proxy>\n" +
-            "            <cas:proxy>https://proxy2/pgtUrl</cas:proxy>\n" +
-            "        </cas:proxies>\n" +
-            "        <cas:attributes>\n" +
-            "            <cas:string>abc</cas:string>\n" +
-            "            <cas:list>a</cas:list>\n" +
-            "            <cas:list>b</cas:list>\n" +
-            "            <cas:int>123</cas:int>\n" +
-            "        </cas:attributes>\n" +
-            "    </cas:authenticationSuccess>\n" +
-            "</cas:serviceResponse>";
-    private static final String EXPECTED_JSON_FAILURE = "{\n" +
-            "  \"serviceResponse\" : {\n" +
-            "    \"authenticationFailure\" : {\n" +
-            "      \"code\" : \"INVALID_REQUEST\",\n" +
-            "      \"description\" : \"Error description\"\n" +
-            "    }\n" +
-            "  }\n" +
-            "}";
-    private static final String EXPECTED_XML_FAILURE = "<cas:serviceResponse xmlns:cas=\"http://www.yale.edu/tp/cas\">\n" +
-            "    <cas:authenticationFailure code=\"INVALID_REQUEST\">Error description</cas:authenticationFailure>\n" +
-            "</cas:serviceResponse>";
+    private final XPathEngine xpath = new JAXPXPathEngine();
+
+    public ServiceResponseTest() {
+        xpath.setNamespaceContext(Collections.singletonMap("cas", "http://www.yale.edu/tp/cas"));
+    }
 
     @Test
     public void testSuccessResponse() throws Exception {
@@ -62,18 +31,58 @@
         attributes.put("int", 123);
         attributes.put("string", "abc");
 
+        List<String> proxies = Arrays.asList("https://proxy1/pgtUrl", "https://proxy2/pgtUrl");
         CASServiceResponse response = ServiceResponseHelper.createSuccess("username", attributes, "PGTIOU-test",
-                Arrays.asList("https://proxy1/pgtUrl", "https://proxy2/pgtUrl"));
+                proxies);
 
-        assertEquals(EXPECTED_JSON_SUCCESS, ServiceResponseMarshaller.marshalJson(response));
-        assertEquals(EXPECTED_XML_SUCCESS, ServiceResponseMarshaller.marshalXml(response));
+        // Build and validate JSON response
+
+        String json = ServiceResponseMarshaller.marshalJson(response);
+        assertEquals("username", JsonPath.read(json, "$.serviceResponse.authenticationSuccess.user"));
+        assertEquals(attributes.get("list"), JsonPath.read(json, "$.serviceResponse.authenticationSuccess.attributes.list"));
+        assertEquals(attributes.get("int"), JsonPath.read(json, "$.serviceResponse.authenticationSuccess.attributes.int"));
+        assertEquals(attributes.get("string"), JsonPath.read(json, "$.serviceResponse.authenticationSuccess.attributes.string"));
+        assertEquals("PGTIOU-test", JsonPath.read(json, "$.serviceResponse.authenticationSuccess.proxyGrantingTicket"));
+        assertEquals(proxies, JsonPath.read(json, "$.serviceResponse.authenticationSuccess.proxies"));
+
+        // Build and validate XML response
+
+        String xml = ServiceResponseMarshaller.marshalXml(response);
+        Document doc = parseAndValidate(xml, schemaFromClassPath("cas-response-schema.xsd"));
+        assertEquals("username", xpath.evaluate("/cas:serviceResponse/cas:authenticationSuccess/cas:user", doc));
+        int idx = 0;
+        for (Node node : xpath.selectNodes("/cas:serviceResponse/cas:authenticationSuccess/cas:attributes/cas:list", doc)) {
+            assertEquals(((List<?>)attributes.get("list")).get(idx), node.getTextContent());
+            idx++;
+        }
+        assertEquals(((List<?>)attributes.get("list")).size(), idx);
+        assertEquals(attributes.get("int").toString(), xpath.evaluate("/cas:serviceResponse/cas:authenticationSuccess/cas:attributes/cas:int", doc));
+        assertEquals(attributes.get("string").toString(), xpath.evaluate("/cas:serviceResponse/cas:authenticationSuccess/cas:attributes/cas:string", doc));
+
+        assertEquals("PGTIOU-test", xpath.evaluate("/cas:serviceResponse/cas:authenticationSuccess/cas:proxyGrantingTicket", doc));
+        idx = 0;
+        for (Node node : xpath.selectNodes("/cas:serviceResponse/cas:authenticationSuccess/cas:proxies/cas:proxy", doc)) {
+            assertEquals(proxies.get(idx), node.getTextContent());
+            idx++;
+        }
+        assertEquals(proxies.size(), idx);
     }
 
     @Test
     public void testErrorResponse() throws Exception {
         CASServiceResponse response = ServiceResponseHelper.createFailure(CASErrorCode.INVALID_REQUEST, "Error description");
 
-        assertEquals(EXPECTED_JSON_FAILURE, ServiceResponseMarshaller.marshalJson(response));
-        assertEquals(EXPECTED_XML_FAILURE, ServiceResponseMarshaller.marshalXml(response));
+        // Build and validate JSON response
+
+        String json = ServiceResponseMarshaller.marshalJson(response);
+        assertEquals(CASErrorCode.INVALID_REQUEST.name(), JsonPath.read(json, "$.serviceResponse.authenticationFailure.code"));
+        assertEquals("Error description", JsonPath.read(json, "$.serviceResponse.authenticationFailure.description"));
+
+        // Build and validate XML response
+
+        String xml = ServiceResponseMarshaller.marshalXml(response);
+        Document doc = parseAndValidate(xml, schemaFromClassPath("cas-response-schema.xsd"));
+        assertEquals(CASErrorCode.INVALID_REQUEST.name(), xpath.evaluate("/cas:serviceResponse/cas:authenticationFailure/@code", doc));
+        assertEquals("Error description", xpath.evaluate("/cas:serviceResponse/cas:authenticationFailure", doc));
     }
 }

--
Gitblit v1.9.1