From 2112668751844c1ccc255a235cd7ab8c167c6b53 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Date: Mon, 27 Apr 2026 18:36:05 +0200 Subject: [PATCH 1/5] Propagate error info to caller --- .../gateway/impl/ApiDataRequestHandler.java | 128 +++++++++--------- .../ReversibleTokenizationStrategy.java | 29 +++- .../AESReversibleTokenizationStrategy.java | 39 +++--- 3 files changed, 112 insertions(+), 84 deletions(-) diff --git a/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java b/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java index f2361fac61..8234a13336 100644 --- a/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java +++ b/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java @@ -1,61 +1,5 @@ package co.worklytics.psoxy.gateway.impl; -import java.io.IOException; -import java.net.ConnectException; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Provider; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.classic.methods.HttpHead; -import org.apache.hc.core5.http.ContentType; -import org.apache.hc.core5.http.HttpHeaders; -import org.apache.hc.core5.http.NameValuePair; -import org.apache.hc.core5.http.message.BasicNameValuePair; -import org.apache.hc.core5.net.WWWFormCodec; -import org.apache.http.HttpStatus; -import org.apache.http.client.utils.URIBuilder; -import com.avaulta.gateway.pseudonyms.PseudonymImplementation; -import com.avaulta.gateway.pseudonyms.impl.UrlSafeTokenPseudonymEncoder; -import com.avaulta.gateway.tokens.ReversibleTokenizationStrategy; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.api.client.http.ByteArrayContent; -import com.google.api.client.http.GenericUrl; -import com.google.api.client.http.HttpContent; -import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpRequestFactory; -import com.google.api.client.http.HttpResponse; -import com.google.api.client.http.HttpTransport; -import com.google.auth.Credentials; -import com.google.auth.http.HttpCredentialsAdapter; -import com.google.auth.http.HttpTransportFactory; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; import co.worklytics.psoxy.ControlHeader; import co.worklytics.psoxy.ErrorCauses; import co.worklytics.psoxy.ProcessedDataMetadataFields; @@ -69,6 +13,7 @@ import co.worklytics.psoxy.gateway.HttpEventRequest; import co.worklytics.psoxy.gateway.HttpEventResponse; import co.worklytics.psoxy.gateway.ProcessedContent; +import co.worklytics.psoxy.gateway.ProxyConstants; import co.worklytics.psoxy.gateway.SecretStore; import co.worklytics.psoxy.gateway.SourceAuthStrategy; import co.worklytics.psoxy.gateway.impl.output.OutputUtils; @@ -81,6 +26,28 @@ import co.worklytics.psoxy.utils.ComposedHttpRequestInitializer; import co.worklytics.psoxy.utils.GzipedContentHttpRequestInitializer; import co.worklytics.psoxy.utils.URLUtils; +import com.avaulta.gateway.pseudonyms.PseudonymImplementation; +import com.avaulta.gateway.pseudonyms.impl.UrlSafeTokenPseudonymEncoder; +import com.avaulta.gateway.tokens.ReversibleTokenizationStrategy; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.api.client.http.ByteArrayContent; +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpContent; +import com.google.api.client.http.HttpRequest; +import com.google.api.client.http.HttpRequestFactory; +import com.google.api.client.http.HttpResponse; +import com.google.api.client.http.HttpTransport; +import com.google.auth.Credentials; +import com.google.auth.http.HttpCredentialsAdapter; +import com.google.auth.http.HttpTransportFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; import dagger.Lazy; import lombok.AllArgsConstructor; import lombok.Builder; @@ -90,7 +57,32 @@ import lombok.SneakyThrows; import lombok.Value; import lombok.extern.java.Log; -import co.worklytics.psoxy.gateway.ProxyConstants; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpHead; +import org.apache.hc.core5.http.ContentType; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.NameValuePair; +import org.apache.hc.core5.http.message.BasicNameValuePair; +import org.apache.hc.core5.net.WWWFormCodec; +import org.apache.http.HttpStatus; +import org.apache.http.client.utils.URIBuilder; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import java.io.IOException; +import java.net.ConnectException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.regex.Pattern; +import java.util.stream.Collectors; @NoArgsConstructor(onConstructor_ = @Inject) @Log @@ -241,6 +233,17 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, // our canonicalization code for this to go wrong log.log(Level.WARNING, "Error parsing / building request URL", e); + // InvalidTokenException extends RuntimeException + if (e instanceof ReversibleTokenizationStrategy.InvalidTokenException ite) { + return HttpEventResponse.builder() + // should this be a 500? Maybe 422 Unprocessable Content? + .statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR) + .header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), + ErrorCauses.FAILED_TO_BUILD_URL.name()) + .body("Error parsing request URL. Error " + ite.getErrorCode().getCode()) + .build(); + } + return HttpEventResponse.builder() .statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR) .header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), @@ -375,7 +378,7 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, if (isSocketTimeoutException(e)) { return buildNetworkTimeoutErrorResponse(builder, e); } - + builder.statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR); builder.body("Failed to parse request; review logs"); builder.header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), @@ -394,9 +397,10 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, log.log(Level.WARNING, e.getMessage(), e); return builder.build(); } catch (ReversibleTokenizationStrategy.InvalidTokenException e) { + // should this be 422 Unprocessable Content, rather than conflict? builder.statusCode(HttpStatus.SC_CONFLICT); builder.header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), - ErrorCauses.TOKENIZED_REQUEST_PARAMETER_INVALID.name()); + ErrorCauses.TOKENIZED_REQUEST_PARAMETER_INVALID.name() + ":" + e.getErrorCode().getCode()); log.log(Level.WARNING, e.getMessage(), e); return builder.build(); } @@ -1045,7 +1049,7 @@ private boolean isSocketTimeoutException(Throwable throwable) { */ private HttpEventResponse buildNetworkTimeoutErrorResponse( HttpEventResponse.HttpEventResponseBuilder builder, Throwable e) { - + builder.statusCode(HttpStatus.SC_BAD_GATEWAY); builder.body("Network timeout: unable to connect to target API. " + "This could indicate: " + @@ -1054,12 +1058,12 @@ private HttpEventResponse buildNetworkTimeoutErrorResponse( "If using VPC connector, verify: VPC connector is active, CIDR range is correct, firewall allows egress, Cloud NAT is configured."); builder.header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), ErrorCauses.NETWORK_EGRESS_BLOCKED.name()); - + log.log(Level.SEVERE, "SocketTimeoutException: Network timeout connecting to target API", e); log.log(Level.SEVERE, "Possible causes: " + "1) Proxy network egress blocked - check VPC connector configuration, firewall rules, Cloud NAT; " + "2) Target API unreachable or slow - check API status, DNS resolution"); - + return builder.build(); } diff --git a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java index 77ff73bd61..09f2b2582d 100644 --- a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java +++ b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java @@ -1,5 +1,7 @@ package com.avaulta.gateway.tokens; +import lombok.Getter; + import java.util.function.Function; /** @@ -41,11 +43,32 @@ default byte[] getReversibleToken(String originalDatum) { /** * Indicates that the token could not be reversed, likely because invalid - * */ class InvalidTokenException extends RuntimeException { - public InvalidTokenException(String message, Throwable cause) { - super(message, cause); + + @Getter + public enum ErrorCode { + ALGORITHM_PARAMETER_ERROR("ITE01", "Failed to decrypt token; some algorithm parameter, such as iv, is wrong"), + BAD_PADDING("ITE02", "Failed to decrypt token; token appears to be corrupted or invalid, due to mismatch between token's padding and the padding expected by the cipher mode"), + ILLEGAL_BLOCK_SIZE("ITE003", "Failed to decrypt token; token appears to be corrupted or invalid, as block size seems to differ from expected"), + DECRYPTION_FAILED("ITE004", "Failed to decrypt token; most likely because encryption key has been rotated"); + + private final String code; + private final String message; + + ErrorCode(String code, String message) { + this.code = code; + this.message = message; + } + + } + + @Getter + private final ErrorCode errorCode; + + public InvalidTokenException(ErrorCode errorCode, Throwable cause) { + super("[" + errorCode.getCode() + "] " + errorCode.getMessage(), cause); + this.errorCode = errorCode; } } } diff --git a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/impl/AESReversibleTokenizationStrategy.java b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/impl/AESReversibleTokenizationStrategy.java index f2e3d87025..41df37974b 100644 --- a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/impl/AESReversibleTokenizationStrategy.java +++ b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/impl/AESReversibleTokenizationStrategy.java @@ -1,12 +1,14 @@ package com.avaulta.gateway.tokens.impl; -import java.nio.charset.StandardCharsets; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.KeySpec; -import java.util.Arrays; -import java.util.function.Function; +import com.avaulta.gateway.tokens.DeterministicTokenizationStrategy; +import com.avaulta.gateway.tokens.ReversibleTokenizationStrategy; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.Value; + import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; @@ -16,14 +18,13 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; -import com.avaulta.gateway.tokens.DeterministicTokenizationStrategy; -import com.avaulta.gateway.tokens.ReversibleTokenizationStrategy; -import lombok.Builder; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.Value; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.KeySpec; +import java.util.Arrays; +import java.util.function.Function; @Builder @RequiredArgsConstructor @@ -130,13 +131,13 @@ public String getOriginalDatum(@NonNull byte[] reversibleToken) throws Reversibl } catch (InvalidKeyException e) { throw new RuntimeException("Invalid encryption key configuration", e); } catch (InvalidAlgorithmParameterException e) { - throw new InvalidTokenException("Failed to decrypt token; some algorithm parameter, such as iv, is wrong", e); + throw new InvalidTokenException(InvalidTokenException.ErrorCode.ALGORITHM_PARAMETER_ERROR, e); } catch (BadPaddingException e) { - throw new InvalidTokenException("Failed to decrypt token; token appears to be corrupted or invalid, due to mismatch between token's padding and the padding expected by the cipher mode", e); + throw new InvalidTokenException(InvalidTokenException.ErrorCode.BAD_PADDING, e); } catch (IllegalBlockSizeException e) { - throw new InvalidTokenException("Failed to decrypt token; token appears to be corrupted or invalid, as block size seems to differ from expected", e); + throw new InvalidTokenException(InvalidTokenException.ErrorCode.ILLEGAL_BLOCK_SIZE, e); } catch (RuntimeException e) { - throw new InvalidTokenException("Failed to decrypt token; most likely because encryption key has been rotated", e); + throw new InvalidTokenException(InvalidTokenException.ErrorCode.DECRYPTION_FAILED, e); } } From 41313db3a0c4fec5c8d9ba7ee2fbd52d591ebe46 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Date: Mon, 27 Apr 2026 19:00:00 +0200 Subject: [PATCH 2/5] Add a x-psoxy-error-code response header --- .../co/worklytics/psoxy/ProcessedDataMetadataFields.java | 5 +++++ .../psoxy/gateway/impl/ApiDataRequestHandler.java | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java b/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java index 4af44fa3d3..ca1f305448 100644 --- a/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java +++ b/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java @@ -24,6 +24,11 @@ public enum ProcessedDataMetadataFields { */ ERROR("Error"), + /** + * a specific error code while processing the request, complements ERROR (optional) + */ + ERROR_CODE("Error-Code"), + /** * a warning code while processing the request */ diff --git a/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java b/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java index 8234a13336..6eeb795fa8 100644 --- a/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java +++ b/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java @@ -240,7 +240,7 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, .statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR) .header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), ErrorCauses.FAILED_TO_BUILD_URL.name()) - .body("Error parsing request URL. Error " + ite.getErrorCode().getCode()) + .header(ProcessedDataMetadataFields.ERROR_CODE.getHttpHeader(), ite.getErrorCode().getCode()) .build(); } @@ -400,7 +400,9 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, // should this be 422 Unprocessable Content, rather than conflict? builder.statusCode(HttpStatus.SC_CONFLICT); builder.header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), - ErrorCauses.TOKENIZED_REQUEST_PARAMETER_INVALID.name() + ":" + e.getErrorCode().getCode()); + ErrorCauses.TOKENIZED_REQUEST_PARAMETER_INVALID.name()); + builder.header(ProcessedDataMetadataFields.ERROR_CODE.getHttpHeader(), e.getErrorCode().getCode()); + log.log(Level.WARNING, e.getMessage(), e); return builder.build(); } From 408f312e307257a6020f149ad7405c1f3766de4e Mon Sep 17 00:00:00 2001 From: Erik Schultink Date: Sun, 24 May 2026 15:24:04 -0700 Subject: [PATCH 3/5] Update java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../avaulta/gateway/tokens/ReversibleTokenizationStrategy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java index 09f2b2582d..d4cfde5155 100644 --- a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java +++ b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java @@ -42,7 +42,7 @@ default byte[] getReversibleToken(String originalDatum) { /** - * Indicates that the token could not be reversed, likely because invalid + * Indicates that the token could not be reversed, likely because it is invalid. */ class InvalidTokenException extends RuntimeException { From b83bb522333fe99a6339b8d6028b123aa44e1af8 Mon Sep 17 00:00:00 2001 From: Erik Schultink Date: Mon, 25 May 2026 17:36:18 -0700 Subject: [PATCH 4/5] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../gateway/tokens/ReversibleTokenizationStrategy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java index d4cfde5155..3b4d2ed902 100644 --- a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java +++ b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java @@ -48,8 +48,8 @@ class InvalidTokenException extends RuntimeException { @Getter public enum ErrorCode { - ALGORITHM_PARAMETER_ERROR("ITE01", "Failed to decrypt token; some algorithm parameter, such as iv, is wrong"), - BAD_PADDING("ITE02", "Failed to decrypt token; token appears to be corrupted or invalid, due to mismatch between token's padding and the padding expected by the cipher mode"), + ALGORITHM_PARAMETER_ERROR("ITE001", "Failed to decrypt token; some algorithm parameter, such as iv, is wrong"), + BAD_PADDING("ITE002", "Failed to decrypt token; token appears to be corrupted or invalid, due to mismatch between token's padding and the padding expected by the cipher mode"), ILLEGAL_BLOCK_SIZE("ITE003", "Failed to decrypt token; token appears to be corrupted or invalid, as block size seems to differ from expected"), DECRYPTION_FAILED("ITE004", "Failed to decrypt token; most likely because encryption key has been rotated"); From e991e154562deb5465722b5a677c9a31a05e012c Mon Sep 17 00:00:00 2001 From: Erik Schultink Date: Mon, 25 May 2026 17:42:02 -0700 Subject: [PATCH 5/5] Address PR review feedback on error propagation Use X-Psoxy-Error with full InvalidTokenException.ErrorCode enum names, return 422 for invalid token failures, and remove the redundant Error-Code header. Co-authored-by: Cursor --- .../psoxy/ProcessedDataMetadataFields.java | 5 ----- .../psoxy/gateway/impl/ApiDataRequestHandler.java | 12 ++++-------- .../tokens/ReversibleTokenizationStrategy.java | 14 ++++++-------- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java b/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java index ca1f305448..4af44fa3d3 100644 --- a/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java +++ b/java/core/src/main/java/co/worklytics/psoxy/ProcessedDataMetadataFields.java @@ -24,11 +24,6 @@ public enum ProcessedDataMetadataFields { */ ERROR("Error"), - /** - * a specific error code while processing the request, complements ERROR (optional) - */ - ERROR_CODE("Error-Code"), - /** * a warning code while processing the request */ diff --git a/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java b/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java index 6eeb795fa8..14aad1fe48 100644 --- a/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java +++ b/java/core/src/main/java/co/worklytics/psoxy/gateway/impl/ApiDataRequestHandler.java @@ -236,11 +236,9 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, // InvalidTokenException extends RuntimeException if (e instanceof ReversibleTokenizationStrategy.InvalidTokenException ite) { return HttpEventResponse.builder() - // should this be a 500? Maybe 422 Unprocessable Content? - .statusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR) + .statusCode(HttpStatus.SC_UNPROCESSABLE_ENTITY) .header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), - ErrorCauses.FAILED_TO_BUILD_URL.name()) - .header(ProcessedDataMetadataFields.ERROR_CODE.getHttpHeader(), ite.getErrorCode().getCode()) + ite.getErrorCode().name()) .build(); } @@ -397,11 +395,9 @@ public HttpEventResponse handle(HttpEventRequest requestToProxy, log.log(Level.WARNING, e.getMessage(), e); return builder.build(); } catch (ReversibleTokenizationStrategy.InvalidTokenException e) { - // should this be 422 Unprocessable Content, rather than conflict? - builder.statusCode(HttpStatus.SC_CONFLICT); + builder.statusCode(HttpStatus.SC_UNPROCESSABLE_ENTITY); builder.header(ProcessedDataMetadataFields.ERROR.getHttpHeader(), - ErrorCauses.TOKENIZED_REQUEST_PARAMETER_INVALID.name()); - builder.header(ProcessedDataMetadataFields.ERROR_CODE.getHttpHeader(), e.getErrorCode().getCode()); + e.getErrorCode().name()); log.log(Level.WARNING, e.getMessage(), e); return builder.build(); diff --git a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java index 3b4d2ed902..9a22d0254c 100644 --- a/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java +++ b/java/gateway-core/src/main/java/com/avaulta/gateway/tokens/ReversibleTokenizationStrategy.java @@ -48,16 +48,14 @@ class InvalidTokenException extends RuntimeException { @Getter public enum ErrorCode { - ALGORITHM_PARAMETER_ERROR("ITE001", "Failed to decrypt token; some algorithm parameter, such as iv, is wrong"), - BAD_PADDING("ITE002", "Failed to decrypt token; token appears to be corrupted or invalid, due to mismatch between token's padding and the padding expected by the cipher mode"), - ILLEGAL_BLOCK_SIZE("ITE003", "Failed to decrypt token; token appears to be corrupted or invalid, as block size seems to differ from expected"), - DECRYPTION_FAILED("ITE004", "Failed to decrypt token; most likely because encryption key has been rotated"); + ALGORITHM_PARAMETER_ERROR("Failed to decrypt token; some algorithm parameter, such as iv, is wrong"), + BAD_PADDING("Failed to decrypt token; token appears to be corrupted or invalid, due to mismatch between token's padding and the padding expected by the cipher mode"), + ILLEGAL_BLOCK_SIZE("Failed to decrypt token; token appears to be corrupted or invalid, as block size seems to differ from expected"), + DECRYPTION_FAILED("Failed to decrypt token; most likely because encryption key has been rotated"); - private final String code; private final String message; - ErrorCode(String code, String message) { - this.code = code; + ErrorCode(String message) { this.message = message; } @@ -67,7 +65,7 @@ public enum ErrorCode { private final ErrorCode errorCode; public InvalidTokenException(ErrorCode errorCode, Throwable cause) { - super("[" + errorCode.getCode() + "] " + errorCode.getMessage(), cause); + super(errorCode.name() + ": " + errorCode.getMessage(), cause); this.errorCode = errorCode; } }