Skip to content

Commit f3d38b2

Browse files
authored
Merge pull request #61 from data-integrations/feature/CDAP-17611-oauth
(CDAP-17611) Added OAuth function support
2 parents 93aadd0 + 7769c1e commit f3d38b2

22 files changed

+283
-103
lines changed

pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,12 @@
439439
<version>1.1.0</version>
440440
<configuration>
441441
<cdapArtifacts>
442-
<parent>system:cdap-data-pipeline[6.1.0-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
443-
<parent>system:cdap-data-streams[6.1.0-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
442+
<!--
443+
Plugins use the new macro substitution that supports object, which is introduced in 6.4.0.
444+
The cdap API version that this project depends on is still 6.2.0 since there is no new API needed.
445+
-->
446+
<parent>system:cdap-data-pipeline[6.4.0-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
447+
<parent>system:cdap-data-streams[6.4.0-SNAPSHOT,7.0.0-SNAPSHOT)</parent>
444448
</cdapArtifacts>
445449
</configuration>
446450
<executions>

src/main/java/io/cdap/plugin/salesforce/SalesforceConnectionUtil.java

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.sforce.ws.ConnectorConfig;
2121
import io.cdap.plugin.salesforce.authenticator.Authenticator;
2222
import io.cdap.plugin.salesforce.authenticator.AuthenticatorCredentials;
23+
import io.cdap.plugin.salesforce.plugin.OAuthInfo;
2324
import org.apache.hadoop.conf.Configuration;
2425

2526
/**
@@ -41,33 +42,23 @@ public static PartnerConnection getPartnerConnection(AuthenticatorCredentials cr
4142
return new PartnerConnection(connectorConfig);
4243
}
4344

44-
/**
45-
* Creates {@link AuthenticatorCredentials} instance based on given parameters.
46-
*
47-
* @param username Salesforce username
48-
* @param password Salesforce password
49-
* @param consumerKey Salesforce consumer key
50-
* @param consumerSecret Salesforce consumer secret
51-
* @param loginUrl Salesforce authentication url
52-
* @return authenticator credentials
53-
*/
54-
public static AuthenticatorCredentials getAuthenticatorCredentials(String username, String password,
55-
String consumerKey, String consumerSecret,
56-
String loginUrl) {
57-
return new AuthenticatorCredentials(username, password, consumerKey, consumerSecret, loginUrl);
58-
}
59-
6045
/**
6146
* Creates {@link AuthenticatorCredentials} instance based on given {@link Configuration}.
6247
*
6348
* @param conf hadoop job configuration
6449
* @return authenticator credentials
6550
*/
6651
public static AuthenticatorCredentials getAuthenticatorCredentials(Configuration conf) {
67-
return getAuthenticatorCredentials(conf.get(SalesforceConstants.CONFIG_USERNAME),
68-
conf.get(SalesforceConstants.CONFIG_PASSWORD),
69-
conf.get(SalesforceConstants.CONFIG_CONSUMER_KEY),
70-
conf.get(SalesforceConstants.CONFIG_CONSUMER_SECRET),
71-
conf.get(SalesforceConstants.CONFIG_LOGIN_URL));
52+
String oAuthToken = conf.get(SalesforceConstants.CONFIG_OAUTH_TOKEN);
53+
String instanceURL = conf.get(SalesforceConstants.CONFIG_OAUTH_INSTANCE_URL);
54+
if (oAuthToken != null && instanceURL != null) {
55+
return new AuthenticatorCredentials(new OAuthInfo(oAuthToken, instanceURL));
56+
}
57+
58+
return new AuthenticatorCredentials(conf.get(SalesforceConstants.CONFIG_USERNAME),
59+
conf.get(SalesforceConstants.CONFIG_PASSWORD),
60+
conf.get(SalesforceConstants.CONFIG_CONSUMER_KEY),
61+
conf.get(SalesforceConstants.CONFIG_CONSUMER_SECRET),
62+
conf.get(SalesforceConstants.CONFIG_LOGIN_URL));
7263
}
7364
}

src/main/java/io/cdap/plugin/salesforce/SalesforceConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ public class SalesforceConstants {
2929
public static final String PROPERTY_PASSWORD = "password";
3030
public static final String PROPERTY_SECURITY_TOKEN = "securityToken";
3131
public static final String PROPERTY_LOGIN_URL = "loginUrl";
32+
public static final String PROPERTY_OAUTH_INFO = "oAuthInfo";
3233

34+
public static final String CONFIG_OAUTH_TOKEN = "mapred.salesforce.oauth.token";
35+
public static final String CONFIG_OAUTH_INSTANCE_URL = "mapred.salesforce.oauth.instance.url";
3336
public static final String CONFIG_CONSUMER_KEY = "mapred.salesforce.consumer.key";
3437
public static final String CONFIG_PASSWORD = "mapred.salesforce.password";
3538
public static final String CONFIG_USERNAME = "mapred.salesforce.user";

src/main/java/io/cdap/plugin/salesforce/authenticator/Authenticator.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.gson.Gson;
2121
import com.sforce.ws.ConnectorConfig;
2222
import io.cdap.plugin.salesforce.SalesforceConstants;
23+
import io.cdap.plugin.salesforce.plugin.OAuthInfo;
2324
import org.eclipse.jetty.client.HttpClient;
2425
import org.eclipse.jetty.util.ssl.SslContextFactory;
2526

@@ -39,12 +40,12 @@ public class Authenticator {
3940
*/
4041
public static ConnectorConfig createConnectorConfig(AuthenticatorCredentials credentials) {
4142
try {
42-
AuthResponse authResponse = oauthLogin(credentials);
43+
OAuthInfo oAuthInfo = getOAuthInfo(credentials);
4344
ConnectorConfig connectorConfig = new ConnectorConfig();
44-
connectorConfig.setSessionId(authResponse.getAccessToken());
45+
connectorConfig.setSessionId(oAuthInfo.getAccessToken());
4546
String apiVersion = SalesforceConstants.API_VERSION;
46-
String restEndpoint = String.format("%s/services/async/%s", authResponse.getInstanceUrl(), apiVersion);
47-
String serviceEndPoint = String.format("%s/services/Soap/u/%s", authResponse.getInstanceUrl(), apiVersion);
47+
String restEndpoint = String.format("%s/services/async/%s", oAuthInfo.getInstanceURL(), apiVersion);
48+
String serviceEndPoint = String.format("%s/services/Soap/u/%s", oAuthInfo.getInstanceURL(), apiVersion);
4849
connectorConfig.setRestEndpoint(restEndpoint);
4950
connectorConfig.setServiceEndpoint(serviceEndPoint);
5051
// This should only be false when doing debugging.
@@ -65,7 +66,12 @@ public static ConnectorConfig createConnectorConfig(AuthenticatorCredentials cre
6566
*
6667
* @return AuthResponse response to http request
6768
*/
68-
public static AuthResponse oauthLogin(AuthenticatorCredentials credentials) throws Exception {
69+
public static OAuthInfo getOAuthInfo(AuthenticatorCredentials credentials) throws Exception {
70+
OAuthInfo oAuthInfo = credentials.getOAuthInfo();
71+
if (oAuthInfo != null) {
72+
return oAuthInfo;
73+
}
74+
6975
SslContextFactory sslContextFactory = new SslContextFactory();
7076
HttpClient httpClient = new HttpClient(sslContextFactory);
7177
try {
@@ -83,7 +89,7 @@ public static AuthResponse oauthLogin(AuthenticatorCredentials credentials) thro
8389
String.format("Cannot authenticate to Salesforce with given credentials. ServerResponse='%s'", response));
8490
}
8591

86-
return authResponse;
92+
return new OAuthInfo(authResponse.getAccessToken(), authResponse.getInstanceUrl());
8793
} finally {
8894
httpClient.stop();
8995
}

src/main/java/io/cdap/plugin/salesforce/authenticator/AuthenticatorCredentials.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,74 @@
1616

1717
package io.cdap.plugin.salesforce.authenticator;
1818

19+
import io.cdap.plugin.salesforce.plugin.OAuthInfo;
20+
1921
import java.io.Serializable;
2022
import java.util.Objects;
23+
import javax.annotation.Nullable;
2124

2225
/**
2326
* Stores information to connect to salesforce via oauth2
2427
*/
2528
public class AuthenticatorCredentials implements Serializable {
29+
30+
private final OAuthInfo oAuthInfo;
2631
private final String username;
2732
private final String password;
2833
private final String consumerKey;
2934
private final String consumerSecret;
3035
private final String loginUrl;
3136

37+
public AuthenticatorCredentials(OAuthInfo oAuthInfo) {
38+
this(Objects.requireNonNull(oAuthInfo), null, null, null, null, null);
39+
}
40+
3241
public AuthenticatorCredentials(String username, String password,
3342
String consumerKey, String consumerSecret, String loginUrl) {
43+
this(null, Objects.requireNonNull(username), Objects.requireNonNull(password), Objects.requireNonNull(consumerKey),
44+
Objects.requireNonNull(consumerSecret), Objects.requireNonNull(loginUrl));
45+
}
46+
47+
private AuthenticatorCredentials(@Nullable OAuthInfo oAuthInfo,
48+
@Nullable String username,
49+
@Nullable String password,
50+
@Nullable String consumerKey,
51+
@Nullable String consumerSecret,
52+
@Nullable String loginUrl) {
53+
this.oAuthInfo = oAuthInfo;
3454
this.username = username;
3555
this.password = password;
3656
this.consumerKey = consumerKey;
3757
this.consumerSecret = consumerSecret;
3858
this.loginUrl = loginUrl;
3959
}
4060

61+
@Nullable
62+
public OAuthInfo getOAuthInfo() {
63+
return oAuthInfo;
64+
}
65+
66+
@Nullable
4167
public String getUsername() {
4268
return username;
4369
}
4470

71+
@Nullable
4572
public String getPassword() {
4673
return password;
4774
}
4875

76+
@Nullable
4977
public String getConsumerKey() {
5078
return consumerKey;
5179
}
5280

81+
@Nullable
5382
public String getConsumerSecret() {
5483
return consumerSecret;
5584
}
5685

86+
@Nullable
5787
public String getLoginUrl() {
5888
return loginUrl;
5989
}

src/main/java/io/cdap/plugin/salesforce/plugin/BaseSalesforceConfig.java

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,65 +32,95 @@
3232
*/
3333
public class BaseSalesforceConfig extends ReferencePluginConfig {
3434

35+
@Name(SalesforceConstants.PROPERTY_OAUTH_INFO)
36+
@Description("OAuth information for connecting to Salesforce. " +
37+
"It is expected to be an json string containing two properties, \"accessToken\" and \"instanceURL\", " +
38+
"which carry the OAuth access token and the URL to connect to respectively. " +
39+
"Use the ${oauth(provider, credentialId)} macro function for acquiring OAuth information dynamically. ")
40+
@Macro
41+
@Nullable
42+
private OAuthInfo oAuthInfo;
43+
3544
@Name(SalesforceConstants.PROPERTY_CONSUMER_KEY)
3645
@Description("Salesforce connected app's consumer key")
3746
@Macro
47+
@Nullable
3848
private String consumerKey;
3949

4050
@Name(SalesforceConstants.PROPERTY_CONSUMER_SECRET)
4151
@Description("Salesforce connected app's client secret key")
4252
@Macro
53+
@Nullable
4354
private String consumerSecret;
4455

4556
@Name(SalesforceConstants.PROPERTY_USERNAME)
4657
@Description("Salesforce username")
4758
@Macro
59+
@Nullable
4860
private String username;
4961

5062
@Name(SalesforceConstants.PROPERTY_PASSWORD)
5163
@Description("Salesforce password")
5264
@Macro
65+
@Nullable
5366
private String password;
5467

5568
@Name(SalesforceConstants.PROPERTY_SECURITY_TOKEN)
5669
@Description("Salesforce security token")
57-
@Nullable
5870
@Macro
71+
@Nullable
5972
private String securityToken;
6073

6174
@Name(SalesforceConstants.PROPERTY_LOGIN_URL)
6275
@Description("Endpoint to authenticate to")
6376
@Macro
77+
@Nullable
6478
private String loginUrl;
6579

66-
public BaseSalesforceConfig(String referenceName, String consumerKey, String consumerSecret,
67-
String username, String password, String loginUrl,
68-
@Nullable String securityToken) {
80+
public BaseSalesforceConfig(String referenceName,
81+
@Nullable String consumerKey,
82+
@Nullable String consumerSecret,
83+
@Nullable String username,
84+
@Nullable String password,
85+
@Nullable String loginUrl,
86+
@Nullable String securityToken,
87+
@Nullable OAuthInfo oAuthInfo) {
6988
super(referenceName);
7089
this.consumerKey = consumerKey;
7190
this.consumerSecret = consumerSecret;
7291
this.username = username;
7392
this.password = password;
7493
this.loginUrl = loginUrl;
7594
this.securityToken = securityToken;
95+
this.oAuthInfo = oAuthInfo;
96+
}
97+
98+
@Nullable
99+
public OAuthInfo getOAuthInfo() {
100+
return oAuthInfo;
76101
}
77102

103+
@Nullable
78104
public String getConsumerKey() {
79105
return consumerKey;
80106
}
81107

108+
@Nullable
82109
public String getConsumerSecret() {
83110
return consumerSecret;
84111
}
85112

113+
@Nullable
86114
public String getUsername() {
87115
return username;
88116
}
89117

118+
@Nullable
90119
public String getPassword() {
91120
return constructPasswordWithToken(password, securityToken);
92121
}
93122

123+
@Nullable
94124
public String getLoginUrl() {
95125
return loginUrl;
96126
}
@@ -99,15 +129,21 @@ public void validate(FailureCollector collector) {
99129
try {
100130
validateConnection();
101131
} catch (Exception e) {
102-
collector.addFailure("Error encountered while establishing connection: " + e.getMessage(), null)
132+
collector.addFailure("Error encountered while establishing connection: " + e.getMessage(),
133+
"Please verify authentication properties are provided correctly")
103134
.withStacktrace(e.getStackTrace());
104135
}
105136
collector.getOrThrowException();
106137
}
107138

108139
public AuthenticatorCredentials getAuthenticatorCredentials() {
109-
return SalesforceConnectionUtil.getAuthenticatorCredentials(username, getPassword(),
110-
consumerKey, consumerSecret, loginUrl);
140+
OAuthInfo oAuthInfo = getOAuthInfo();
141+
if (oAuthInfo != null) {
142+
return new AuthenticatorCredentials(oAuthInfo);
143+
}
144+
145+
return new AuthenticatorCredentials(getUsername(), getPassword(), getConsumerKey(),
146+
getConsumerSecret(), getLoginUrl());
111147
}
112148

113149
/**
@@ -117,6 +153,16 @@ public AuthenticatorCredentials getAuthenticatorCredentials() {
117153
* @return true if none of the connection properties contains macro, false otherwise
118154
*/
119155
public boolean canAttemptToEstablishConnection() {
156+
// If OAuth token is configured, use it to establish connection
157+
if (getOAuthInfo() != null) {
158+
return true;
159+
}
160+
161+
// At configurePipeline time, macro is not resolved, hence the OAuth field will be null.
162+
if (containsMacro(SalesforceConstants.PROPERTY_OAUTH_INFO)) {
163+
return false;
164+
}
165+
120166
return !(containsMacro(SalesforceConstants.PROPERTY_CONSUMER_KEY)
121167
|| containsMacro(SalesforceConstants.PROPERTY_CONSUMER_SECRET)
122168
|| containsMacro(SalesforceConstants.PROPERTY_USERNAME)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright © 2021 Cask Data, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
17+
package io.cdap.plugin.salesforce.plugin;
18+
19+
/**
20+
* Class to carry OAuth information returned by the {@code ${oauth}} macro function.
21+
*/
22+
public final class OAuthInfo {
23+
24+
private final String accessToken;
25+
private final String instanceURL;
26+
27+
public OAuthInfo(String accessToken, String instanceURL) {
28+
this.accessToken = accessToken;
29+
this.instanceURL = instanceURL;
30+
}
31+
32+
public String getAccessToken() {
33+
return accessToken;
34+
}
35+
36+
public String getInstanceURL() {
37+
return instanceURL;
38+
}
39+
}

0 commit comments

Comments
 (0)