You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by je...@apache.org on 2021/12/15 20:12:20 UTC

[camel] 02/02: CAMEL-17346: camel-salesforce: expired passwords

This is an automated email from the ASF dual-hosted git repository.

jeremyross pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 58822906704efd99470aec37430a12afa86e3dbc
Author: Jeremy Ross <je...@gmail.com>
AuthorDate: Wed Dec 15 13:36:51 2021 -0600

    CAMEL-17346: camel-salesforce: expired passwords
    
    Better handling for 401 expired password.
---
 .../internal/client/SalesforceSecurityHandler.java | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/SalesforceSecurityHandler.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/SalesforceSecurityHandler.java
index 62633be..375cfda 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/SalesforceSecurityHandler.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/SalesforceSecurityHandler.java
@@ -16,10 +16,15 @@
  */
 package org.apache.camel.component.salesforce.internal.client;
 
+import java.io.IOException;
 import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.camel.component.salesforce.SalesforceHttpClient;
 import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.api.dto.RestError;
 import org.apache.camel.component.salesforce.internal.SalesforceSession;
 import org.eclipse.jetty.client.HttpContentResponse;
 import org.eclipse.jetty.client.HttpConversation;
@@ -45,12 +50,14 @@ public class SalesforceSecurityHandler implements ProtocolHandler {
     private static final Logger LOG = LoggerFactory.getLogger(SalesforceSecurityHandler.class);
 
     private static final String AUTHENTICATION_RETRIES_ATTRIBUTE = SalesforceSecurityHandler.class.getName().concat(".retries");
+    private static final String EXPIRED_PASSWORD_CODE = "INVALID_OPERATION_WITH_EXPIRED_PASSWORD";
 
     private final SalesforceHttpClient httpClient;
     private final SalesforceSession session;
     private final int maxAuthenticationRetries;
     private final int maxContentLength;
     private final ResponseNotifier notifier;
+    private final ObjectMapper objectMapper = new ObjectMapper();
 
     public SalesforceSecurityHandler(SalesforceHttpClient httpClient) {
 
@@ -159,6 +166,22 @@ public class SalesforceSecurityHandler implements ProtocolHandler {
             // request failed authentication?
             if (status == HttpStatus.UNAUTHORIZED_401) {
 
+                // Salesforce will allow successful login with an expired password, but any subsequent
+                // API calls will fail with a 401 and message about expired password.
+                // It's fatal. User must reset password.
+                List<RestError> errors = Collections.emptyList();
+                try {
+                    errors = client.readErrorsFrom(getContentAsInputStream(), objectMapper);
+                } catch (IOException e) {
+                    LOG.warn("Unable to deserialize errors from response body.");
+                }
+                if (errors.stream().anyMatch(error -> EXPIRED_PASSWORD_CODE.equals(error.getErrorCode()))) {
+                    SalesforceException salesforceException = createSalesforceException(client, status,
+                            reason);
+                    forwardFailureComplete(request, null, response, salesforceException);
+                    return;
+                }
+
                 // REST token expiry
                 LOG.warn("Retrying on Salesforce authentication error [{}]: [{}]", status, reason);
 
@@ -188,6 +211,16 @@ public class SalesforceSecurityHandler implements ProtocolHandler {
             }
         }
 
+        private SalesforceException createSalesforceException(AbstractClientBase client, int statusCode, String reason) {
+            List<RestError> restErrors = Collections.emptyList();
+            try {
+                restErrors = client.readErrorsFrom(getContentAsInputStream(), new ObjectMapper());
+            } catch (IOException e) {
+                LOG.warn("Unable to deserialize errors from response body.");
+            }
+            return new SalesforceException(restErrors, statusCode);
+        }
+
         protected void retryOnFailure(
                 SalesforceHttpRequest request, HttpConversation conversation, Integer retries, AbstractClientBase client,
                 Throwable failure) {
@@ -286,6 +319,7 @@ public class SalesforceSecurityHandler implements ProtocolHandler {
             notifier.forwardFailureComplete(conversation.getResponseListeners(), request, requestFailure, response,
                     responseFailure);
         }
+
     }
 
     // no @Override annotation here to keep it compatible with Jetty 9.2,