diff --git a/README.md b/README.md index 5576b8d..3a39f8a 100644 --- a/README.md +++ b/README.md @@ -348,7 +348,8 @@ accept proxy tickets. Supports all configurations that are available for `Cas20P #### org.jasig.cas.client.validation.json.Cas30JsonProxyReceivingTicketValidationFilter Indentical to `Cas30ProxyReceivingTicketValidationFilter`, yet the filter is able to accept validation responses from CAS -that are formatted as JSON per guidelines laid out by the CAS protocol. See the [protocol documentation](https://apereo.github.io/cas/) +that are formatted as JSON per guidelines laid out by the CAS protocol. +See the [protocol documentation](https://apereo.github.io/cas/5.1.x/protocol/CAS-Protocol-Specification.html) for more info. ##### Proxy Authentication vs. Distributed Caching diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/Cas30JsonServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/Cas30JsonServiceTicketValidator.java index 6b4418d..9fee4b3 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/Cas30JsonServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/Cas30JsonServiceTicketValidator.java @@ -1,9 +1,11 @@ package org.jasig.cas.client.validation.json; +import com.fasterxml.jackson.core.JsonProcessingException; import org.jasig.cas.client.validation.Assertion; import org.jasig.cas.client.validation.Cas30ServiceTicketValidator; import org.jasig.cas.client.validation.TicketValidationException; +import java.io.IOException; import java.util.Collections; import java.util.Map; @@ -27,9 +29,11 @@ public class Cas30JsonServiceTicketValidator extends Cas30ServiceTicketValidator try { final TicketValidationJsonResponse json = new JsonValidationResponseParser().parse(response); return json.getAssertion(getProxyGrantingTicketStorage(), getProxyRetriever()); - } catch (final Exception e) { - logger.warn("Unable parse the JSON response", e); + } catch (final JsonProcessingException e) { + logger.warn("Unable parse the JSON response. Falling back to XML", e); return super.parseResponseFromServer(response); + } catch (final IOException e) { + throw new TicketValidationException(e.getMessage(), e); } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/JsonValidationResponseParser.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/JsonValidationResponseParser.java index 5dd3abd..c4b58fa 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/JsonValidationResponseParser.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/JsonValidationResponseParser.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.validation.TicketValidationException; +import java.io.IOException; + /** * This is {@link JsonValidationResponseParser}. * @@ -16,35 +18,31 @@ final class JsonValidationResponseParser { this.objectMapper = new ObjectMapper(); this.objectMapper.findAndRegisterModules(); } - - public TicketValidationJsonResponse parse(final String response) throws TicketValidationException { - try { - if (CommonUtils.isBlank(response)) { - throw new TicketValidationException("Invalid JSON response; The response is empty"); - } - final TicketValidationJsonResponse json = this.objectMapper.readValue(response, TicketValidationJsonResponse.class); - - final TicketValidationJsonResponse.CasServiceResponseAuthentication serviceResponse = json.getServiceResponse(); - if (serviceResponse.getAuthenticationFailure() != null - && serviceResponse.getAuthenticationSuccess() != null) { - throw new TicketValidationException("Invalid JSON response; It indicates both a success " - + "and a failure event, which is indicative of a server error. The actual response is " + response); - } - - if (serviceResponse.getAuthenticationFailure() != null) { - final String error = json.getServiceResponse().getAuthenticationFailure().getCode() - + " - " + serviceResponse.getAuthenticationFailure().getDescription(); - throw new TicketValidationException(error); - } - - final String principal = json.getServiceResponse().getAuthenticationSuccess().getUser(); - if (CommonUtils.isEmpty(principal)) { - throw new TicketValidationException("No principal was found in the response from the CAS server."); - } - return json; - } catch (final Exception e) { - throw new RuntimeException("Unable to parse JSON validation response", e); + public TicketValidationJsonResponse parse(final String response) throws TicketValidationException, IOException { + if (CommonUtils.isBlank(response)) { + throw new TicketValidationException("Invalid JSON response; The response is empty"); } + + final TicketValidationJsonResponse json = this.objectMapper.readValue(response, TicketValidationJsonResponse.class); + + final TicketValidationJsonResponse.CasServiceResponseAuthentication serviceResponse = json.getServiceResponse(); + if (serviceResponse.getAuthenticationFailure() != null + && serviceResponse.getAuthenticationSuccess() != null) { + throw new TicketValidationException("Invalid JSON response; It indicates both a success " + + "and a failure event, which is indicative of a server error. The actual response is " + response); + } + + if (serviceResponse.getAuthenticationFailure() != null) { + final String error = json.getServiceResponse().getAuthenticationFailure().getCode() + + " - " + serviceResponse.getAuthenticationFailure().getDescription(); + throw new TicketValidationException(error); + } + + final String principal = json.getServiceResponse().getAuthenticationSuccess().getUser(); + if (CommonUtils.isEmpty(principal)) { + throw new TicketValidationException("No principal was found in the response from the CAS server."); + } + return json; } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/TicketValidationJsonResponse.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/TicketValidationJsonResponse.java index c880667..84db6e2 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/TicketValidationJsonResponse.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/json/TicketValidationJsonResponse.java @@ -1,5 +1,7 @@ package org.jasig.cas.client.validation.json; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.jasig.cas.client.authentication.AttributePrincipal; import org.jasig.cas.client.authentication.AttributePrincipalImpl; import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; @@ -17,9 +19,11 @@ import java.util.Map; * @author Misagh Moayyed */ final class TicketValidationJsonResponse { - private CasServiceResponseAuthentication serviceResponse; + private final CasServiceResponseAuthentication serviceResponse; - public void setServiceResponse(final CasServiceResponseAuthentication serviceResponse) { + @JsonCreator + public TicketValidationJsonResponse(@JsonProperty("serviceResponse") + final CasServiceResponseAuthentication serviceResponse) { this.serviceResponse = serviceResponse; } @@ -51,24 +55,25 @@ final class TicketValidationJsonResponse { } static class CasServiceResponseAuthentication { - private CasServiceResponseAuthenticationFailure authenticationFailure; - private CasServiceResponseAuthenticationSuccess authenticationSuccess; + private final CasServiceResponseAuthenticationFailure authenticationFailure; + private final CasServiceResponseAuthenticationSuccess authenticationSuccess; + + @JsonCreator + public CasServiceResponseAuthentication(@JsonProperty("authenticationFailure") + final CasServiceResponseAuthenticationFailure authenticationFailure, + @JsonProperty("authenticationSuccess") + final CasServiceResponseAuthenticationSuccess authenticationSuccess) { + this.authenticationFailure = authenticationFailure; + this.authenticationSuccess = authenticationSuccess; + } public CasServiceResponseAuthenticationFailure getAuthenticationFailure() { return this.authenticationFailure; } - public void setAuthenticationFailure(final CasServiceResponseAuthenticationFailure authenticationFailure) { - this.authenticationFailure = authenticationFailure; - } - public CasServiceResponseAuthenticationSuccess getAuthenticationSuccess() { return this.authenticationSuccess; } - - public void setAuthenticationSuccess(final CasServiceResponseAuthenticationSuccess authenticationSuccess) { - this.authenticationSuccess = authenticationSuccess; - } } static class CasServiceResponseAuthenticationSuccess {