Repository: camel Updated Branches: refs/heads/master 7c1045283 -> d4c9a3da4
CAMEL-11013 Support OAuth 2.0 JWT Bearer Token ... ...Flow This gives the users ability to use OAuth 2.0 JWT Bearer Token Flow[1] to gain access tokens from Salesforce using JWT token signed by a certificate defined on the Salesforce connected application. [1] https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/032047c3 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/032047c3 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/032047c3 Branch: refs/heads/master Commit: 032047c3df3df1d6db52b28f56f41daa5733c5bb Parents: 7c10452 Author: Zoran Regvart <zregv...@apache.org> Authored: Wed Mar 15 12:51:55 2017 +0100 Committer: Zoran Regvart <zregv...@apache.org> Committed: Wed Mar 15 13:02:08 2017 +0100 ---------------------------------------------------------------------- .../src/main/docs/salesforce-component.adoc | 3 +- .../salesforce/SalesforceComponent.java | 47 +++-- .../salesforce/SalesforceComponentVerifier.java | 2 +- .../salesforce/SalesforceLoginConfig.java | 99 +++++++-- .../salesforce/internal/SalesforceSession.java | 131 +++++++++--- .../component/salesforce/LoginConfigHelper.java | 105 +++++----- ...sforceJwtBearerTokenFlowIntegrationTest.java | 56 +++++ .../internal/SalesforceSessionTest.java | 54 +++++ .../internal/SessionIntegrationTest.java | 3 +- .../src/test/resources/test.p12 | Bin 0 -> 2416 bytes .../apache/camel/maven/CamelSalesforceMojo.java | 3 +- ...CamelSalesforceIntegrationTests.connectedApp | 1 + .../SalesforceComponentConfiguration.java | 208 +++++++++++-------- 13 files changed, 499 insertions(+), 213 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc index c99a68b..28d6567 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc +++ b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc @@ -427,7 +427,7 @@ link:salesforce.html[Salesforce]. // component options: START -The Salesforce component supports 24 options which are listed below. +The Salesforce component supports 25 options which are listed below. @@ -438,6 +438,7 @@ The Salesforce component supports 24 options which are listed below. | loginUrl | security | https://login.salesforce.com | String | Salesforce login URL defaults to https://login.salesforce.com | clientId | security | | String | Salesforce connected application Consumer Key | clientSecret | security | | String | Salesforce connected application Consumer Secret +| keystore | security | | KeyStoreParameters | KeyStoreParameters to use in OAuth 2.0 JWT Bearer Token Flow. | refreshToken | security | | String | Salesforce connected application Consumer token | userName | security | | String | Salesforce account user name | password | security | | String | Salesforce account password http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java index 9696207..80fdf8a 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java @@ -46,6 +46,7 @@ import org.apache.camel.util.IntrospectionSupport; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.ReflectionHelper; import org.apache.camel.util.ServiceHelper; +import org.apache.camel.util.jsse.KeyStoreParameters; import org.apache.camel.util.jsse.SSLContextParameters; import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Origin; @@ -88,6 +89,8 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin private String userName; @Metadata(label = "security", secret = true) private String password; + @Metadata(label = "security", secret = true) + private KeyStoreParameters keystore; @Metadata(label = "security") private boolean lazyLogin; @@ -220,26 +223,18 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin @Override protected void doStart() throws Exception { if (loginConfig == null) { - loginConfig = new SalesforceLoginConfig(); - if (loginUrl != null) { - loginConfig.setLoginUrl(loginUrl); - } - if (refreshToken != null) { - loginConfig.setRefreshToken(refreshToken); - } - if (clientId != null) { - loginConfig.setClientId(clientId); - } - if (clientSecret != null) { - loginConfig.setClientSecret(clientSecret); - } - if (userName != null) { - loginConfig.setUserName(userName); - } - if (password != null) { - loginConfig.setPassword(password); + if (ObjectHelper.isNotEmpty(password)) { + loginConfig = new SalesforceLoginConfig(loginUrl, clientId, clientSecret, userName, password, lazyLogin); + } else if (ObjectHelper.isNotEmpty(refreshToken)) { + loginConfig = new SalesforceLoginConfig(loginUrl, clientId, clientSecret, refreshToken, lazyLogin); + } else if (ObjectHelper.isNotEmpty(keystore)) { + loginConfig = new SalesforceLoginConfig(loginUrl, clientId, userName, keystore, lazyLogin); + } else { + throw new IllegalArgumentException("Cannot define a login configuration, the component configuration" + + " does not contain `password`, `refreshToken` or `keystore` parameters. Specifying one of those" + + " determines the type of authentication performed."); } - loginConfig.setLazyLogin(lazyLogin); + LOG.debug("Created login configuration: {}", loginConfig); } else { LOG.debug("Using shared login configuration: {}", loginConfig); @@ -303,7 +298,7 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin // support restarts if (this.session == null) { - this.session = new SalesforceSession(httpClient, httpClient.getTimeout(), loginConfig); + this.session = new SalesforceSession(getCamelContext(), httpClient, httpClient.getTimeout(), loginConfig); } // set session before calling start() httpClient.setSession(this.session); @@ -470,6 +465,7 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin public String getClientSecret() { return clientSecret; + } /** @@ -479,6 +475,17 @@ public class SalesforceComponent extends UriEndpointComponent implements Endpoin this.clientSecret = clientSecret; } + /** + * {@link KeyStoreParameters} to use in OAuth 2.0 JWT Bearer Token Flow. + */ + public void setKeystore(final KeyStoreParameters keystore) { + this.keystore = keystore; + } + + public KeyStoreParameters getKeystore() { + return keystore; + } + public String getRefreshToken() { return refreshToken; } http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java index f7ce00a..7d6df25 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java @@ -90,7 +90,7 @@ public class SalesforceComponentVerifier extends DefaultComponentVerifier { httpClient.setConnectTimeout(SalesforceComponent.CONNECTION_TIMEOUT); configureHttpProxy(httpClient, parameters); - SalesforceSession session = new SalesforceSession(httpClient, httpClient.getTimeout(), loginConfig); + SalesforceSession session = new SalesforceSession(getCamelContext(), httpClient, httpClient.getTimeout(), loginConfig); DefaultRestClient client = new DefaultRestClient(httpClient, configuration.getApiVersion(), configuration.getFormat(), session); httpClient.setSession(session); http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java index 14dc0ed..d703d9f 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceLoginConfig.java @@ -16,13 +16,21 @@ */ package org.apache.camel.component.salesforce; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.jsse.KeyStoreParameters; + /** * Configuration object for Salesforce login properties */ public class SalesforceLoginConfig { + public enum Type { + USERNAME_PASSWORD, REFRESH_TOKEN, JWT + } + public static final String DEFAULT_LOGIN_URL = "https://login.salesforce.com"; + private Type type; private String loginUrl; private String clientId; private String clientSecret; @@ -33,30 +41,38 @@ public class SalesforceLoginConfig { // note that login issues may not surface until a message needs to be processed private boolean lazyLogin; + private KeyStoreParameters keystore; + public SalesforceLoginConfig() { loginUrl = DEFAULT_LOGIN_URL; lazyLogin = false; } - public SalesforceLoginConfig(String loginUrl, - String clientId, String clientSecret, - String userName, String password, boolean lazyLogin) { + private SalesforceLoginConfig(Type type, String loginUrl, String clientId, String clientSecret, String refreshToken, + String userName, String password, boolean lazyLogin, KeyStoreParameters keystore) { + this.type = type; this.loginUrl = loginUrl; this.clientId = clientId; this.clientSecret = clientSecret; + this.refreshToken = refreshToken; this.userName = userName; this.password = password; this.lazyLogin = lazyLogin; + this.keystore = keystore; } - public SalesforceLoginConfig(String loginUrl, - String clientId, String clientSecret, - String refreshToken, boolean lazyLogin) { - this.loginUrl = loginUrl; - this.clientId = clientId; - this.clientSecret = clientSecret; - this.refreshToken = refreshToken; - this.lazyLogin = lazyLogin; + public SalesforceLoginConfig(String loginUrl, String clientId, String clientSecret, String userName, + String password, boolean lazyLogin) { + this(Type.USERNAME_PASSWORD, loginUrl, clientId, clientSecret, null, userName, password, lazyLogin, null); + } + + public SalesforceLoginConfig(String loginUrl, String clientId, String clientSecret, String refreshToken, + boolean lazyLogin) { + this(Type.REFRESH_TOKEN, loginUrl, clientId, clientSecret, refreshToken, null, null, lazyLogin, null); + } + + public SalesforceLoginConfig(String loginUrl, String clientId, String userName, KeyStoreParameters keystore, boolean lazyLogin) { + this(Type.JWT, loginUrl, clientId, null, null, userName, null, lazyLogin, keystore); } public String getLoginUrl() { @@ -92,6 +108,18 @@ public class SalesforceLoginConfig { this.clientSecret = clientSecret; } + /** + * Keystore parameters for keystore containing certificate and private key needed for OAuth 2.0 JWT Bearer Token + * Flow. + */ + public void setKeystore(final KeyStoreParameters keystore) { + this.keystore = keystore; + this.type = Type.JWT; + } + + public KeyStoreParameters getKeystore() { + return keystore; + } public String getRefreshToken() { return refreshToken; @@ -102,6 +130,11 @@ public class SalesforceLoginConfig { */ public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; + this.type = Type.REFRESH_TOKEN; + } + + public Type getType() { + return type; } public String getUserName() { @@ -124,6 +157,7 @@ public class SalesforceLoginConfig { */ public void setPassword(String password) { this.password = password; + this.type = Type.USERNAME_PASSWORD; } public boolean isLazyLogin() { @@ -131,21 +165,46 @@ public class SalesforceLoginConfig { } /** - * Flag to enable/disable lazy OAuth, default is false. When enabled, OAuth token retrieval or generation is not done until the first API call + * Flag to enable/disable lazy OAuth, default is false. When enabled, OAuth token retrieval or generation is not + * done until the first API call */ public void setLazyLogin(boolean lazyLogin) { this.lazyLogin = lazyLogin; } + public void validate() { + ObjectHelper.notNull(loginUrl, "loginUrl"); + ObjectHelper.notNull(clientId, "clientId"); + + final boolean hasRefreshToken = ObjectHelper.isEmpty(refreshToken); + + if (hasRefreshToken && keystore == null) { + ObjectHelper.notNull(userName, "userName (username/password authentication)"); + ObjectHelper.notNull(password, "password (username/password authentication)"); + ObjectHelper.notNull(clientSecret, "clientSecret (username/password authentication)"); + type = Type.USERNAME_PASSWORD; + } else if (hasRefreshToken && keystore == null) { + ObjectHelper.notNull(refreshToken, "refreshToken (authentication with refresh token)"); + ObjectHelper.notNull(clientSecret, "clientSecret (authentication with refresh token)"); + type = Type.REFRESH_TOKEN; + } else if (keystore != null) { + ObjectHelper.notNull(userName, "userName (JWT authentication)"); + ObjectHelper.notNull(keystore, "keystore (JWT authentication)"); + type = Type.JWT; + } else { + throw new IllegalArgumentException( + "You must specify parameters aligned with one of the supported authentication methods:" + + " for username and password authentication: userName, password, clientSecret;" + + " for refresh token authentication: refreshToken, clientSecret;" + + " for JWT: userName, keystore. And for every one of those loginUrl and clientId must be specified also."); + } + } + @Override public String toString() { - return "SalesforceLoginConfig[" - + "loginUrl='" + loginUrl + '\'' - + ", clientId='" + clientId + '\'' - + ", clientSecret='********'" - + ", refreshToken='" + refreshToken + '\'' - + ", userName='" + userName + '\'' - + ", password=********'" + password + '\'' - + ", lazyLogin=" + lazyLogin + ']'; + return "SalesforceLoginConfig[" + "loginUrl='" + loginUrl + '\'' + ", clientId='" + clientId + '\'' + + ", clientSecret='********'" + ", refreshToken='" + refreshToken + '\'' + ", userName='" + userName + '\'' + + ", password=********'" + password + '\'' + ", keystore=********'" + keystore + '\'' + ", lazyLogin=" + + lazyLogin + ']'; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java index f3047f7..33d8ddf 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/SalesforceSession.java @@ -18,7 +18,15 @@ package org.apache.camel.component.salesforce.internal; import java.io.IOException; import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.Signature; +import java.time.Clock; import java.util.ArrayList; +import java.util.Base64; +import java.util.Enumeration; import java.util.List; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; @@ -28,15 +36,18 @@ import java.util.concurrent.TimeoutException; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.camel.CamelContext; import org.apache.camel.Service; import org.apache.camel.component.salesforce.SalesforceHttpClient; import org.apache.camel.component.salesforce.SalesforceLoginConfig; +import org.apache.camel.component.salesforce.SalesforceLoginConfig.Type; import org.apache.camel.component.salesforce.api.SalesforceException; import org.apache.camel.component.salesforce.api.dto.RestError; import org.apache.camel.component.salesforce.api.utils.JsonUtils; import org.apache.camel.component.salesforce.internal.dto.LoginError; import org.apache.camel.component.salesforce.internal.dto.LoginToken; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.jsse.KeyStoreParameters; import org.eclipse.jetty.client.HttpConversation; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; @@ -49,6 +60,13 @@ import org.slf4j.LoggerFactory; public class SalesforceSession implements Service { + private static final String JWT_SIGNATURE_ALGORITHM = "SHA256withRSA"; + + private static final int JWT_CLAIM_WINDOW = 270; // 4.5 min + + private static final String JWT_HEADER = Base64.getUrlEncoder() + .encodeToString("{\"alg\":\"RS256\"}".getBytes(StandardCharsets.UTF_8)); + private static final String OAUTH2_REVOKE_PATH = "/services/oauth2/revoke?token="; private static final String OAUTH2_TOKEN_PATH = "/services/oauth2/token"; @@ -65,20 +83,14 @@ public class SalesforceSession implements Service { private volatile String accessToken; private volatile String instanceUrl; - public SalesforceSession(SalesforceHttpClient httpClient, long timeout, SalesforceLoginConfig config) { + private CamelContext camelContext; + + public SalesforceSession(CamelContext camelContext, SalesforceHttpClient httpClient, long timeout, SalesforceLoginConfig config) { + this.camelContext = camelContext; // validate parameters ObjectHelper.notNull(httpClient, "httpClient"); ObjectHelper.notNull(config, "SalesforceLoginConfig"); - ObjectHelper.notNull(config.getLoginUrl(), "loginUrl"); - ObjectHelper.notNull(config.getClientId(), "clientId"); - ObjectHelper.notNull(config.getClientSecret(), "clientSecret"); - - if (ObjectHelper.isEmpty(config.getRefreshToken())) { - ObjectHelper.notNull(config.getUserName(), "userName"); - ObjectHelper.notNull(config.getPassword(), "password"); - } else { - ObjectHelper.notNull(config.getRefreshToken(), "refreshToken"); - } + config.validate(); this.httpClient = httpClient; this.timeout = timeout; @@ -129,7 +141,9 @@ public class SalesforceSession implements Service { } /** - * Creates login request, allows SalesforceSecurityHandler to create a login request for a failed authentication conversation + * Creates login request, allows SalesforceSecurityHandler to create a login request for a failed authentication + * conversation + * * @return login POST request. */ public Request getLoginRequest(HttpConversation conversation) { @@ -138,34 +152,90 @@ public class SalesforceSession implements Service { final Fields fields = new Fields(true); fields.put("client_id", config.getClientId()); - fields.put("client_secret", config.getClientSecret()); fields.put("format", "json"); - if (ObjectHelper.isEmpty(config.getRefreshToken())) { + final Type type = config.getType(); + switch (type) { + case USERNAME_PASSWORD: + fields.put("client_secret", config.getClientSecret()); fields.put("grant_type", "password"); fields.put("username", config.getUserName()); fields.put("password", config.getPassword()); - } else { + break; + case REFRESH_TOKEN: + fields.put("client_secret", config.getClientSecret()); fields.put("grant_type", "refresh_token"); fields.put("refresh_token", config.getRefreshToken()); + break; + case JWT: + fields.put("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"); + fields.put("assertion", generateJwtAssertion()); + break; + default: + throw new IllegalArgumentException("Unsupported login configuration type: " + type); } final Request post; if (conversation == null) { post = httpClient.POST(loginUrl); } else { - post = httpClient.newHttpRequest(conversation, URI.create(loginUrl)) - .method(HttpMethod.POST); + post = httpClient.newHttpRequest(conversation, URI.create(loginUrl)).method(HttpMethod.POST); + } + + return post.content(new FormContentProvider(fields)).timeout(timeout, TimeUnit.MILLISECONDS); + } + + String generateJwtAssertion() { + final long utcPlusWindow = Clock.systemUTC().millis() / 1000 + JWT_CLAIM_WINDOW; + + final StringBuilder claim = new StringBuilder().append("{\"iss\":\"").append(config.getClientId()) + .append("\",\"sub\":\"").append(config.getUserName()).append("\",\"aud\":\"").append(config.getLoginUrl()) + .append("\",\"exp\":\"").append(utcPlusWindow).append("\"}"); + + final StringBuilder token = new StringBuilder(JWT_HEADER).append('.') + .append(Base64.getUrlEncoder().encodeToString(claim.toString().getBytes(StandardCharsets.UTF_8))); + + final KeyStoreParameters keyStoreParameters = config.getKeystore(); + keyStoreParameters.setCamelContext(camelContext); + + try { + final KeyStore keystore = keyStoreParameters.createKeyStore(); + + final Enumeration<String> aliases = keystore.aliases(); + String alias = null; + while (aliases.hasMoreElements()) { + String tmp = aliases.nextElement(); + if (keystore.isKeyEntry(tmp)) { + if (alias == null) { + alias = tmp; + } else { + throw new IllegalArgumentException("The given keystore `" + keyStoreParameters.getResource() + + "` contains more than one key entry, expecting only one"); + } + } + } + + PrivateKey key = (PrivateKey) keystore.getKey(alias, keyStoreParameters.getPassword().toCharArray()); + + Signature signature = Signature.getInstance(JWT_SIGNATURE_ALGORITHM); + signature.initSign(key); + signature.update(token.toString().getBytes(StandardCharsets.UTF_8)); + byte[] signed = signature.sign(); + + token.append('.').append(Base64.getUrlEncoder().encodeToString(signed)); + } catch (IOException | GeneralSecurityException e) { + throw new IllegalStateException(e); } - return post.content(new FormContentProvider(fields)) - .timeout(timeout, TimeUnit.MILLISECONDS); + return token.toString(); } /** - * Parses login response, allows SalesforceSecurityHandler to parse a login request for a failed authentication conversation. + * Parses login response, allows SalesforceSecurityHandler to parse a login request for a failed authentication + * conversation. */ - public synchronized void parseLoginResponse(ContentResponse loginResponse, String responseContent) throws SalesforceException { + public synchronized void parseLoginResponse(ContentResponse loginResponse, String responseContent) + throws SalesforceException { final int responseStatus = loginResponse.getStatus(); try { @@ -193,15 +263,16 @@ public class SalesforceSession implements Service { case HttpStatus.BAD_REQUEST_400: // parse the response to get error final LoginError error = objectMapper.readValue(responseContent, LoginError.class); - final String msg = String.format("Login error code:[%s] description:[%s]", - error.getError(), error.getErrorDescription()); + final String msg = String.format("Login error code:[%s] description:[%s]", error.getError(), + error.getErrorDescription()); final List<RestError> errors = new ArrayList<RestError>(); errors.add(new RestError(msg, error.getErrorDescription())); throw new SalesforceException(errors, HttpStatus.BAD_REQUEST_400); default: - throw new SalesforceException(String.format("Login error status:[%s] reason:[%s]", - responseStatus, loginResponse.getReason()), responseStatus); + throw new SalesforceException( + String.format("Login error status:[%s] reason:[%s]", responseStatus, loginResponse.getReason()), + responseStatus); } } catch (IOException e) { String msg = "Login error: response parse exception " + e.getMessage(); @@ -215,9 +286,9 @@ public class SalesforceSession implements Service { } try { - String logoutUrl = (instanceUrl == null ? config.getLoginUrl() : instanceUrl) + OAUTH2_REVOKE_PATH + accessToken; - final Request logoutGet = httpClient.newRequest(logoutUrl) - .timeout(timeout, TimeUnit.MILLISECONDS); + String logoutUrl = (instanceUrl == null ? config.getLoginUrl() : instanceUrl) + OAUTH2_REVOKE_PATH + + accessToken; + final Request logoutGet = httpClient.newRequest(logoutUrl).timeout(timeout, TimeUnit.MILLISECONDS); final ContentResponse logoutResponse = logoutGet.send(); final int statusCode = logoutResponse.getStatus(); @@ -227,9 +298,7 @@ public class SalesforceSession implements Service { LOG.info("Logout successful"); } else { throw new SalesforceException( - String.format("Logout error, code: [%s] reason: [%s]", - statusCode, reason), - statusCode); + String.format("Logout error, code: [%s] reason: [%s]", statusCode, reason), statusCode); } } catch (InterruptedException e) { http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java index 0f65a6a..987f7e1 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/LoginConfigHelper.java @@ -23,65 +23,74 @@ import java.io.InputStream; import java.util.Properties; import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.jsse.KeyStoreParameters; import org.junit.Assert; public class LoginConfigHelper extends Assert { protected static final String TEST_LOGIN_PROPERTIES = "../test-salesforce-login.properties"; - public static SalesforceLoginConfig getLoginConfig() throws IOException { + private static final LoginConfigHelper INSTANCE; - // load test-salesforce-login properties - Properties properties = new Properties(); - InputStream stream = null; + static { try { - final SalesforceLoginConfig config; - stream = new FileInputStream(TEST_LOGIN_PROPERTIES); - properties.load(stream); + INSTANCE = new LoginConfigHelper(); + } catch (final IOException e) { + throw new ExceptionInInitializerError(e); + } + } + + private SalesforceLoginConfig config; - if (ObjectHelper.isEmpty(properties.getProperty("refreshToken"))) { - config = new SalesforceLoginConfig( - properties.getProperty("loginUrl", SalesforceLoginConfig.DEFAULT_LOGIN_URL), - properties.getProperty("clientId"), - properties.getProperty("clientSecret"), - properties.getProperty("userName"), - properties.getProperty("password"), - Boolean.parseBoolean(properties.getProperty("lazyLogin", "false"))); - } else { - config = new SalesforceLoginConfig( - properties.getProperty("loginUrl", SalesforceLoginConfig.DEFAULT_LOGIN_URL), - properties.getProperty("clientId"), // - properties.getProperty("clientSecret"), // - properties.getProperty("refreshToken"), // - Boolean.parseBoolean(properties.getProperty("lazyLogin", "false"))); - } - - - assertNotNull("Null loginUrl", config.getLoginUrl()); - assertNotNull("Null clientId", config.getClientId()); - assertNotNull("Null clientSecret", config.getClientSecret()); - if (ObjectHelper.isEmpty(properties.getProperty("refreshToken"))) { - assertNotNull("Null userName", config.getUserName()); - assertNotNull("Null password", config.getPassword()); - } else { - assertNotNull("Null refreshToken", config.getRefreshToken()); - } - - - return config; - - } catch (FileNotFoundException e) { - throw new FileNotFoundException("Create a properties file named " - + TEST_LOGIN_PROPERTIES + " with clientId, clientSecret, userName, and password or with clientId, clientSecret and refreshToken" + private final Properties properties; + + public LoginConfigHelper() throws IOException { + // load test-salesforce-login properties + try (InputStream stream = new FileInputStream(TEST_LOGIN_PROPERTIES);) { + properties = new Properties(); + properties.load(stream); + } catch (final FileNotFoundException ignored) { + throw new FileNotFoundException("Create a properties file named " + TEST_LOGIN_PROPERTIES + + " with clientId, clientSecret, userName, and password or with clientId, clientSecret and refreshToken" + " for a Salesforce account with Merchandise and Invoice objects from Salesforce Guides."); - } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException ignore) { - } - } } + + final boolean hasPassword = ObjectHelper.isNotEmpty(properties.getProperty("password")); + final boolean hasRefreshToken = ObjectHelper.isNotEmpty(properties.getProperty("refreshToken")); + final boolean hasKeystore = ObjectHelper.isNotEmpty(properties.getProperty("keystore.resource")); + + final boolean lazyLogin = Boolean.parseBoolean(properties.getProperty("lazyLogin", "false")); + final String loginUrl = properties.getProperty("loginUrl", SalesforceLoginConfig.DEFAULT_LOGIN_URL); + final String clientId = properties.getProperty("clientId"); + final String clientSecret = properties.getProperty("clientSecret"); + final String username = properties.getProperty("userName"); + + if (hasPassword) { + config = new SalesforceLoginConfig(loginUrl, clientId, clientSecret, username, + properties.getProperty("password"), lazyLogin); + } else if (hasRefreshToken) { + config = new SalesforceLoginConfig(loginUrl, clientId, // + clientSecret, // + properties.getProperty("refreshToken"), // + lazyLogin); + } else if (hasKeystore) { + final KeyStoreParameters keystore = new KeyStoreParameters(); + keystore.setResource(properties.getProperty("keystore.resource")); + keystore.setType(properties.getProperty("keystore.type")); + keystore.setPassword(properties.getProperty("keystore.password")); + config = new SalesforceLoginConfig(loginUrl, clientId, username, keystore, lazyLogin); + } else { + throw new IllegalArgumentException("Must specifiy parameters in " + TEST_LOGIN_PROPERTIES); + } + + } + + public static SalesforceLoginConfig getLoginConfig() { + return INSTANCE.config; + } + + public static Properties testLoginProperties() { + return INSTANCE.properties; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceJwtBearerTokenFlowIntegrationTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceJwtBearerTokenFlowIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceJwtBearerTokenFlowIntegrationTest.java new file mode 100644 index 0000000..5a799c9 --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceJwtBearerTokenFlowIntegrationTest.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.salesforce; + +import java.util.Properties; + +import org.apache.camel.CamelContext; +import org.apache.camel.component.salesforce.api.dto.Limits; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.apache.camel.util.jsse.KeyStoreParameters; +import org.junit.Test; + +public class SalesforceJwtBearerTokenFlowIntegrationTest extends CamelTestSupport { + + @Test + public void shouldLoginUsingJwtBearerToken() { + final Limits limits = template.requestBody("salesforce:limits", null, Limits.class); + + assertNotNull(limits); + } + + @Override + protected CamelContext createCamelContext() throws Exception { + final CamelContext camelContext = super.createCamelContext(); + + final SalesforceComponent salesforce = new SalesforceComponent(); + final Properties properties = LoginConfigHelper.testLoginProperties(); + salesforce.setClientId(properties.getProperty("clientId")); + salesforce.setUserName(properties.getProperty("userName")); + salesforce.setLoginUrl(properties.getProperty("loginUrl")); + + KeyStoreParameters keystore = new KeyStoreParameters(); + keystore.setResource(properties.getProperty("keystore.resource")); + keystore.setType(properties.getProperty("keystore.type")); + keystore.setPassword(properties.getProperty("keystore.password")); + salesforce.setKeystore(keystore); + + camelContext.addComponent("salesforce", salesforce); + + return camelContext; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SalesforceSessionTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SalesforceSessionTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SalesforceSessionTest.java new file mode 100644 index 0000000..d59961a --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SalesforceSessionTest.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.salesforce.internal; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +import org.apache.camel.component.salesforce.SalesforceHttpClient; +import org.apache.camel.component.salesforce.SalesforceLoginConfig; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.util.jsse.KeyStoreParameters; +import org.junit.Assert; +import org.junit.Test; + +import static org.mockito.Mockito.mock; + +public class SalesforceSessionTest { + + private KeyStoreParameters parameters; + + public SalesforceSessionTest() { + parameters = new KeyStoreParameters(); + parameters.setResource("test.p12"); + parameters.setType("PKCS12"); + parameters.setPassword("password"); + } + + @Test + public void shouldGenerateJwtTokens() throws GeneralSecurityException, IOException { + SalesforceLoginConfig config = new SalesforceLoginConfig("https://login.salesforce.com", "ABCD", "username", + parameters, true); + + SalesforceSession session = new SalesforceSession(new DefaultCamelContext(), mock(SalesforceHttpClient.class), + 1, config); + + String jwtAssertion = session.generateJwtAssertion(); + + Assert.assertNotNull(jwtAssertion); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SessionIntegrationTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SessionIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SessionIntegrationTest.java index c78720a..81396c2 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SessionIntegrationTest.java +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/internal/SessionIntegrationTest.java @@ -18,6 +18,7 @@ package org.apache.camel.component.salesforce.internal; import org.apache.camel.component.salesforce.LoginConfigHelper; import org.apache.camel.component.salesforce.SalesforceHttpClient; +import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.jsse.SSLContextParameters; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.Assert; @@ -43,7 +44,7 @@ public class SessionIntegrationTest extends Assert implements SalesforceSession. final SalesforceHttpClient httpClient = new SalesforceHttpClient(sslContextFactory); httpClient.setConnectTimeout(TIMEOUT); - final SalesforceSession session = new SalesforceSession( + final SalesforceSession session = new SalesforceSession(new DefaultCamelContext(), httpClient, TIMEOUT, LoginConfigHelper.getLoginConfig()); session.addListener(this); httpClient.setSession(session); http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-component/src/test/resources/test.p12 ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/resources/test.p12 b/components/camel-salesforce/camel-salesforce-component/src/test/resources/test.p12 new file mode 100644 index 0000000..976157a Binary files /dev/null and b/components/camel-salesforce/camel-salesforce-component/src/test/resources/test.p12 differ http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java b/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java index 38ec8ab..08ee1ab 100644 --- a/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java +++ b/components/camel-salesforce/camel-salesforce-maven-plugin/src/main/java/org/apache/camel/maven/CamelSalesforceMojo.java @@ -61,6 +61,7 @@ import org.apache.camel.component.salesforce.internal.SalesforceSession; import org.apache.camel.component.salesforce.internal.client.DefaultRestClient; import org.apache.camel.component.salesforce.internal.client.RestClient; import org.apache.camel.component.salesforce.internal.client.SyncResponseCallback; +import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.util.IntrospectionSupport; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.jsse.SSLContextParameters; @@ -576,7 +577,7 @@ public class CamelSalesforceMojo extends AbstractMojo { } // set session before calling start() - final SalesforceSession session = new SalesforceSession(httpClient, + final SalesforceSession session = new SalesforceSession(new DefaultCamelContext(), httpClient, httpClient.getTimeout(), new SalesforceLoginConfig(loginUrl, clientId, clientSecret, userName, password, false)); httpClient.setSession(session); http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/components/camel-salesforce/it/resources/salesforce/connectedApps/CamelSalesforceIntegrationTests.connectedApp ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/it/resources/salesforce/connectedApps/CamelSalesforceIntegrationTests.connectedApp b/components/camel-salesforce/it/resources/salesforce/connectedApps/CamelSalesforceIntegrationTests.connectedApp index 4afdf5d..59105f1 100644 --- a/components/camel-salesforce/it/resources/salesforce/connectedApps/CamelSalesforceIntegrationTests.connectedApp +++ b/components/camel-salesforce/it/resources/salesforce/connectedApps/CamelSalesforceIntegrationTests.connectedApp @@ -20,6 +20,7 @@ <label>CamelSalesforceIntegrationTests</label> <oauthConfig> <callbackUrl>https://login.salesforce.com/services/oauth2/success</callbackUrl> + <certificate>MIIC1TCCAb2gAwIBAgIEM3ZMGjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9TYWxlc2ZvcmNlIHRlc3QwIBcNMTcwMzE0MjIxMjU0WhgPMjExNzAyMTgyMjEyNTRaMBoxGDAWBgNVBAMTD1NhbGVzZm9yY2UgdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbZinVCZerzZvyyQlfE6nMpEQRfVsjpcfT01UTG/bwzWorP7YRpGkDW7Q4eu6IPrHtohkhM3JtsSVka5jfS1iEguMXLdNkEyMjMiBrWJeyGfcISF1yazgqLxxwcwGjMn3C9xV5tBxiRSqtMrV1iRx3fxmLue1UnZjSyUaG+Vi+FcKxqre5ixApeDCZHLONxBy3mjWK4GIeBBbUqQqy3LNrT6B34WdNX8vTslpTKOlmLyycEI/Rx+A4lNaultrJHdnRhGBrPwYinlV/wdramaQFL+ltqxQw6A5FBg9VjDEEd8JGv6OZ7aA/3mvjTbX5MaLj+aLJQyT2+XzDSAtDgOhMCAwEAAaMhMB8wHQYDVR0OBBYEFDM0jGtarY5uTVLThBEnXMUqDlyDMA0GCSqGSIb3DQEBCwUAA4IBAQCJtIsP5foO84sNwVMGwPiaoQUPE+cN73Tg63FSef36FEei6B3UnsFZnlcz9WGIL0G4PUjQro5z7/gMAHGehPQjoUEzKihdoNncbvKa9Yfuw4eO98YIp2t5OnOGQpDQWN9JO0On0tu+4rsgkJn8fZtzTPViS2Vhssi65DpWYydKWvEbbYw6oiPMH9T2mQy11lxSwNBngBy4ZF4hCyEVpvSe6Mr2q+jxgjCwMAqX+XofmEpfHaJXGy8lgtzow0oT8X4ymsV1JR0erw0dsbch9pTsG7YXcNFIEm50DctQEikoWxkAvIsZIHgujWkrjQlEsXZp/MS4OuNj6yWWlCaK/QM3</ce rtificate> <consumerKey>3MVG9HxRZv05HarQ5D2to.ylPaUg7uaFqGqE2wN6_RRaHM9PTa3SWT8UwKJzXAyCujHrfObkUy7oZqiBUyfGl</consumerKey> <scopes>Api</scopes> <scopes>RefreshToken</scopes> http://git-wip-us.apache.org/repos/asf/camel/blob/032047c3/platforms/spring-boot/components-starter/camel-salesforce-starter/src/main/java/org/apache/camel/component/salesforce/springboot/SalesforceComponentConfiguration.java ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-salesforce-starter/src/main/java/org/apache/camel/component/salesforce/springboot/SalesforceComponentConfiguration.java b/platforms/spring-boot/components-starter/camel-salesforce-starter/src/main/java/org/apache/camel/component/salesforce/springboot/SalesforceComponentConfiguration.java index dbff830..c70fb66 100644 --- a/platforms/spring-boot/components-starter/camel-salesforce-starter/src/main/java/org/apache/camel/component/salesforce/springboot/SalesforceComponentConfiguration.java +++ b/platforms/spring-boot/components-starter/camel-salesforce-starter/src/main/java/org/apache/camel/component/salesforce/springboot/SalesforceComponentConfiguration.java @@ -28,6 +28,7 @@ import org.apache.camel.component.salesforce.api.dto.bulk.ContentType; import org.apache.camel.component.salesforce.internal.PayloadFormat; import org.apache.camel.component.salesforce.internal.dto.NotifyForFieldsEnum; import org.apache.camel.component.salesforce.internal.dto.NotifyForOperationsEnum; +import org.apache.camel.util.jsse.KeyStoreParameters; import org.apache.camel.util.jsse.SSLContextParameters; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; @@ -58,6 +59,11 @@ public class SalesforceComponentConfiguration { */ private String clientSecret; /** + * KeyStoreParameters to use in OAuth 2.0 JWT Bearer Token Flow. + */ + @NestedConfigurationProperty + private KeyStoreParameters keystore; + /** * Salesforce connected application Consumer token */ private String refreshToken; @@ -176,6 +182,14 @@ public class SalesforceComponentConfiguration { this.clientSecret = clientSecret; } + public KeyStoreParameters getKeystore() { + return keystore; + } + + public void setKeystore(KeyStoreParameters keystore) { + this.keystore = keystore; + } + public String getRefreshToken() { return refreshToken; } @@ -340,96 +354,6 @@ public class SalesforceComponentConfiguration { this.resolvePropertyPlaceholders = resolvePropertyPlaceholders; } - public static class SalesforceLoginConfigNestedConfiguration { - public static final Class CAMEL_NESTED_CLASS = org.apache.camel.component.salesforce.SalesforceLoginConfig.class; - /** - * Salesforce login URL, defaults to https://login.salesforce.com - */ - private String loginUrl; - /** - * Salesforce connected application Consumer Key - */ - private String clientId; - /** - * Salesforce connected application Consumer Secret - */ - private String clientSecret; - /** - * Salesforce connected application Consumer token - */ - private String refreshToken; - /** - * Salesforce account user name - */ - private String userName; - /** - * Salesforce account password - */ - private String password; - /** - * Flag to enable/disable lazy OAuth, default is false. When enabled, - * OAuth token retrieval or generation is not done until the first API - * call - */ - private Boolean lazyLogin; - - public String getLoginUrl() { - return loginUrl; - } - - public void setLoginUrl(String loginUrl) { - this.loginUrl = loginUrl; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getClientSecret() { - return clientSecret; - } - - public void setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - } - - public String getRefreshToken() { - return refreshToken; - } - - public void setRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Boolean getLazyLogin() { - return lazyLogin; - } - - public void setLazyLogin(Boolean lazyLogin) { - this.lazyLogin = lazyLogin; - } - } - public static class SalesforceEndpointConfigNestedConfiguration { public static final Class CAMEL_NESTED_CLASS = org.apache.camel.component.salesforce.SalesforceEndpointConfig.class; /** @@ -1006,4 +930,108 @@ public class SalesforceComponentConfiguration { this.approvalSkipEntryCriteria = approvalSkipEntryCriteria; } } + + public static class SalesforceLoginConfigNestedConfiguration { + public static final Class CAMEL_NESTED_CLASS = org.apache.camel.component.salesforce.SalesforceLoginConfig.class; + /** + * Salesforce login URL, defaults to https://login.salesforce.com + */ + private String loginUrl; + /** + * Salesforce connected application Consumer Key + */ + private String clientId; + /** + * Salesforce connected application Consumer Secret + */ + private String clientSecret; + /** + * Keystore parameters for keystore containing certificate and private + * key needed for OAuth 2.0 JWT Bearer Token Flow. + */ + @NestedConfigurationProperty + private KeyStoreParameters keystore; + /** + * Salesforce connected application Consumer token + */ + private String refreshToken; + /** + * Salesforce account user name + */ + private String userName; + /** + * Salesforce account password + */ + private String password; + /** + * Flag to enable/disable lazy OAuth, default is false. When enabled, + * OAuth token retrieval or generation is not done until the first API + * call + */ + private Boolean lazyLogin; + + public String getLoginUrl() { + return loginUrl; + } + + public void setLoginUrl(String loginUrl) { + this.loginUrl = loginUrl; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public KeyStoreParameters getKeystore() { + return keystore; + } + + public void setKeystore(KeyStoreParameters keystore) { + this.keystore = keystore; + } + + public String getRefreshToken() { + return refreshToken; + } + + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Boolean getLazyLogin() { + return lazyLogin; + } + + public void setLazyLogin(Boolean lazyLogin) { + this.lazyLogin = lazyLogin; + } + } } \ No newline at end of file