Skip to content
This repository was archived by the owner on Jan 19, 2024. It is now read-only.

Commit f6b7ad9

Browse files
sfcbetiucmanivinesh
authored andcommitted
Refresh token public app support (#108)
* Removed commented lines of code from ETClientTest.java * Started implementing RefreshToken, Public and Web App support for OAuth2.0 * Finished implementing the support for RefreshToken, Public/Web App * Fixed a bug * Refactored the name of the input parameter of the isNullOrBlankOrEmpty function * Minor refactor in ETClient.java Extracted the multiple usages of configuration.get(applicationType) into a variable
1 parent 1062511 commit f6b7ad9

6 files changed

Lines changed: 268 additions & 133 deletions

File tree

README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,32 @@ Java platform. Among other things, the SDK:
2525
For more information about the Java SDK and how to use it, please see
2626
the Javadocs at http://salesforce-marketingcloud.github.io/FuelSDK-Java/.
2727

28+
New Features in Version 1.5.0
29+
------------
30+
* Added Refresh Token support for OAuth2 authentication
31+
* Added Web/Public App support for OAuth2 authentication
32+
33+
More details on Access Tokens for Web/Public Apps can be found [here](https://developer.salesforce.com/docs/atlas.en-us.mc-app-development.meta/mc-app-development/access-token-app.htm)
34+
35+
Sample Config for OAuth2:
36+
37+
```
38+
clientId=<CLIENT_ID>
39+
clientSecret=<CLIENT_SECRET>
40+
authEndpoint=<AUTH TENANT SPECIFIC ENDPOINT>
41+
endpoint=<REST TENANT SPECIFIC ENDPOINT>
42+
soapEndpoint=<SOAP TENANT SPECIFIC ENDPOINT>
43+
useOAuth2Authentication=true
44+
accountId=<TARGET_ACCOUNT_ID>
45+
scope=<PERMISSION_LIST>
46+
applicationType=<APPLICATION_TYPE>
47+
redirectURI=<REDIRECT_URI_FOR_PUBLIC/WEB_APP>
48+
authorizationCode=<AUTHORIZATION_CODE_FOR_PUBLIC/WEB_APP>
49+
```
50+
51+
* applicationType can have one of the following values: `server`, `public`, `web`. The default value of applicationType is `server`.
52+
53+
2854
New Features in Version 1.4.0
2955
------------
3056
* Added support for OAuth2 authentication - [More Details](https://developer.salesforce.com/docs/atlas.en-us.mc-app-development.meta/mc-app-development/integration-considerations.htm)
@@ -51,7 +77,7 @@ The easiest way to install the Java SDK is via Maven&mdash;simply add the follow
5177
<dependency>
5278
<groupId>com.github.salesforce-marketingcloud</groupId>
5379
<artifactId>fuelsdk</artifactId>
54-
<version>1.4.0</version>
80+
<version>1.5.0</version>
5581
</dependency>
5682

5783
Maven will automatically resolve, download, and install all dependencies for you.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.github.salesforce-marketingcloud</groupId>
55
<artifactId>fuelsdk</artifactId>
6-
<version>1.4.0</version>
6+
<version>1.5.0</version>
77
<name>Salesforce Marketing Cloud Java SDK</name>
88
<description>Salesforce Marketing Cloud Java SDK</description>
99
<url>https://github.com/salesforce-marketingcloud/FuelSDK-Java</url>

src/main/java/com/exacttarget/fuelsdk/ETClient.java

Lines changed: 96 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.google.gson.JsonObject;
4949
import com.google.gson.JsonParser;
5050

51+
import org.apache.commons.lang.StringUtils;
5152
import org.apache.log4j.Logger;
5253

5354
/**
@@ -78,9 +79,6 @@ public class ETClient {
7879
private String clientId = null;
7980
private String clientSecret = null;
8081

81-
private String username = null;
82-
private String password = null;
83-
8482
private String endpoint = null;
8583
private String authEndpoint = null;
8684
private String soapEndpoint = null;
@@ -96,17 +94,28 @@ public class ETClient {
9694
private String accessToken = null;
9795
private int expiresIn = 0;
9896
private String legacyToken = null;
97+
98+
public void setRefreshToken(String refreshToken) {
99+
this.refreshToken = refreshToken;
100+
}
101+
102+
public String getRefreshToken() {
103+
return refreshToken;
104+
}
105+
99106
private String refreshToken = null;
100107

101108
private long tokenExpirationTime = 0;
102109
private static long soapEndpointExpiration = 0;
103110
private static String fetchedSoapEndpoint = null;
104111
private static final long cacheDurationInMillis = 1000 * 60 * 10; // 10 minutes
105112
private boolean useOAuth2Authentication;
106-
private String accountId;
107-
private String scope;
108113

109-
/**
114+
private String applicationType;
115+
private String authorizationCode;
116+
private String redirectURI;
117+
118+
/**
110119
* Class constructor, Initializes a new instance of the class.
111120
*/
112121
public ETClient()
@@ -137,9 +146,6 @@ public ETClient(ETConfiguration configuration)
137146
clientId = configuration.get("clientId");
138147
clientSecret = configuration.get("clientSecret");
139148

140-
username = configuration.get("username");
141-
password = configuration.get("password");
142-
143149
endpoint = configuration.get("endpoint");
144150
if (endpoint == null) {
145151
endpoint = DEFAULT_ENDPOINT;
@@ -159,30 +165,37 @@ public ETClient(ETConfiguration configuration)
159165
gson = gsonBuilder.create();
160166
}
161167

162-
useOAuth2Authentication = configuration.isTrue("useOAuth2Authentication") ? true : false;
163-
accountId = configuration.get("accountId");
164-
scope = configuration.get("scope");
168+
useOAuth2Authentication = configuration.isTrue("useOAuth2Authentication");
165169

166-
if (clientId != null && clientSecret != null) {
167-
authConnection = new ETRestConnection(this, authEndpoint, true);
168-
requestToken();
169-
restConnection = new ETRestConnection(this, endpoint);
170-
fetchSoapEndpoint();
171-
soapConnection = new ETSoapConnection(this, soapEndpoint, accessToken);
172-
} else {
173-
if (username == null || password == null) {
174-
throw new ETSdkException("must specify either " +
175-
"clientId/clientSecret or username/password");
170+
applicationType = configuration.get("applicationType");
171+
authorizationCode = configuration.get("authorizationCode");
172+
redirectURI = configuration.get("redirectURI");
173+
174+
if(isNullOrBlankOrEmpty(applicationType)){
175+
applicationType = "server";
176+
configuration.set("applicationType", "server");
177+
}
178+
179+
if(applicationType.equals("public") || applicationType.equals("web")){
180+
if (isNullOrBlankOrEmpty(authorizationCode) || isNullOrBlankOrEmpty(redirectURI)){
181+
throw new ETSdkException("AuthorizationCode or RedirectURI is null: For Public/Web Apps, " +
182+
"authorizationCode and redirectURI must be provided in config file");
176183
}
177-
if (soapEndpoint == null) {
178-
throw new ETSdkException("must specify soapEndpoint " +
179-
"when authenticating with username/password");
184+
}
185+
186+
if(applicationType.equals("public")){
187+
if(isNullOrBlankOrEmpty(clientId)){
188+
throw new ETSdkException("ClientId is null: clientId must be provided in config file");
189+
}
190+
}
191+
else{
192+
if(isNullOrBlankOrEmpty(clientId) || isNullOrBlankOrEmpty(clientSecret)){
193+
throw new ETSdkException("ClientId or ClientSecret is null: clientId and clientSecret must be provided in config file");
180194
}
181-
soapConnection = new ETSoapConnection(this, soapEndpoint,
182-
username,
183-
password);
184195
}
185196

197+
buildClients();
198+
186199
if (configuration.isFalse("autoHydrateObjects")) {
187200
autoHydrateObjects = false;
188201
}
@@ -191,15 +204,25 @@ public ETClient(ETConfiguration configuration)
191204
logger.trace("ETClient initialized:");
192205
logger.trace(" clientId = " + clientId);
193206
logger.trace(" clientSecret = *");
194-
logger.trace(" username = " + username);
195-
logger.trace(" password = *");
196207
logger.trace(" endpoint = " + endpoint);
197208
logger.trace(" authEndpoint = " + authEndpoint);
198209
logger.trace(" soapEndpoint = " + soapEndpoint);
199210
logger.trace(" autoHydrateObjects = " + autoHydrateObjects);
200211
}
201212
}
202213

214+
private void buildClients() throws ETSdkException {
215+
authConnection = new ETRestConnection(this, authEndpoint, true);
216+
requestToken();
217+
restConnection = new ETRestConnection(this, endpoint);
218+
fetchSoapEndpoint();
219+
soapConnection = new ETSoapConnection(this, soapEndpoint, accessToken);
220+
}
221+
222+
public static boolean isNullOrBlankOrEmpty(String str) {
223+
return str == null || StringUtils.isBlank(str) || StringUtils.isEmpty(str);
224+
}
225+
203226
private void fetchSoapEndpoint() {
204227
if(useOAuth2Authentication) {
205228
return;
@@ -329,32 +352,8 @@ public synchronized String requestToken()
329352
private synchronized String requestOAuth2Token()
330353
throws ETSdkException
331354
{
332-
if (clientId == null || clientSecret == null) {
333-
// no-op
334-
return null;
335-
}
336-
//
337-
// Construct the JSON payload.
338-
//
339-
340-
JsonObject jsonObject = new JsonObject();
341-
jsonObject.addProperty("client_id", clientId);
342-
jsonObject.addProperty("client_secret", clientSecret);
343-
jsonObject.addProperty("grant_type", "client_credentials");
344-
if(accountId != null && accountId.length() > 0)
345-
{
346-
jsonObject.addProperty("account_id", accountId);
347-
}
348-
if(scope != null && scope.length() > 0)
349-
{
350-
jsonObject.addProperty("scope", scope);
351-
}
352-
353-
String requestPayload = gson.toJson(jsonObject);
354-
355-
ETRestConnection.Response response = null;
356-
357-
response = authConnection.post(PATH_OAUTH2TOKEN, requestPayload);
355+
JsonObject payload = createPayload(configuration);
356+
ETRestConnection.Response response = authConnection.post(PATH_OAUTH2TOKEN, gson.toJson(payload));
358357

359358
if (response.getResponseCode() != HttpURLConnection.HTTP_OK) {
360359
throw new ETSdkException("error obtaining OAuth2 access token "
@@ -364,34 +363,60 @@ private synchronized String requestOAuth2Token()
364363
+ response.getResponseMessage()
365364
+ ")");
366365
}
367-
368-
//
369-
// Parse the JSON response into the appropriate instance
370-
// variables:
371-
//
366+
JsonParser jsonParser = new JsonParser();
372367

373368
String responsePayload = response.getResponsePayload();
369+
JsonObject jsonObject = jsonParser.parse(responsePayload).getAsJsonObject();
374370

375-
JsonParser jsonParser = new JsonParser();
376-
jsonObject = jsonParser.parse(responsePayload).getAsJsonObject();
377371
this.accessToken = jsonObject.get("access_token").getAsString();
378-
this.expiresIn = jsonObject.get("expires_in").getAsInt();
379372
this.endpoint = jsonObject.get("rest_instance_url").getAsString();
380373
this.soapEndpoint = jsonObject.get("soap_instance_url").getAsString() + "service.asmx";
381374

382-
//
383-
// Calculate the token expiration time. As before,
384-
// System.currentTimeMills() is in milliseconds so
385-
// we multiply expiresIn by 1000:
386-
//
387-
375+
this.expiresIn = jsonObject.get("expires_in").getAsInt();
388376
tokenExpirationTime = System.currentTimeMillis() + (expiresIn * 1000);
389377

378+
if(jsonObject.has("refresh_token")){
379+
this.refreshToken = jsonObject.get("refresh_token").getAsString();
380+
}
381+
390382
return accessToken;
391383
}
392384

385+
JsonObject createPayload(ETConfiguration configuration) {
386+
JsonObject payload = new JsonObject();
387+
388+
payload.addProperty("client_id", configuration.get("clientId"));
389+
390+
String applicationType = configuration.get("applicationType");
391+
392+
if(applicationType.equals("web") || applicationType.equals("server")){
393+
payload.addProperty("client_secret", configuration.get("clientSecret"));
394+
}
395+
if(!isNullOrBlankOrEmpty(refreshToken)){
396+
payload.addProperty("grant_type", "refresh_token");
397+
payload.addProperty("refresh_token", refreshToken);
398+
}
399+
else if(applicationType.equals("public") || applicationType.equals("web")){
400+
payload.addProperty("grant_type", "authorization_code");
401+
payload.addProperty("code", configuration.get("authorizationCode"));
402+
payload.addProperty("redirect_uri", configuration.get("redirectURI"));
403+
}
404+
else{
405+
payload.addProperty("grant_type", "client_credentials");
406+
}
407+
408+
if(!isNullOrBlankOrEmpty(configuration.get("accountId"))){
409+
payload.addProperty("account_id", configuration.get("accountId"));
410+
}
411+
if(!isNullOrBlankOrEmpty(configuration.get("scope"))){
412+
payload.addProperty("scope", configuration.get("scope"));
413+
}
414+
415+
return payload;
416+
}
417+
393418
/**
394-
*
419+
*
395420
* @param refreshToken The refresh token
396421
* @return The request token
397422
*/

src/main/java/com/exacttarget/fuelsdk/ETRestConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ private HttpURLConnection sendRequest(URL url, Method method, String payload)
240240
try {
241241
connection = (HttpURLConnection) url.openConnection();
242242

243-
connection.setRequestProperty("User-Agent", "FuelSDK-Java-v1.4.0-REST-"+method+"-"+object);
243+
connection.setRequestProperty("User-Agent", "FuelSDK-Java-v1.5.0-REST-"+method+"-"+object);
244244
connection.setRequestMethod(method.toString());
245245
} catch (ProtocolException ex) {
246246
throw new ETSdkException("error setting request method: " + method.toString(), ex);

src/main/java/com/exacttarget/fuelsdk/ETSoapConnection.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,12 @@ public Soap getSoap() {
234234
}
235235

236236
public Soap getSoap(String m) {
237-
soapClient.getRequestContext().put("HTTP_HEADER_USER_AGENT", "FuelSDK-Java-v1.4.0-SOAP-"+m);
237+
soapClient.getRequestContext().put("HTTP_HEADER_USER_AGENT", "FuelSDK-Java-v1.5.0-SOAP-"+m);
238238
return soap;
239239
}
240240

241241
public Soap getSoap(String m, String o) {
242-
soapClient.getRequestContext().put("HTTP_HEADER_USER_AGENT", "FuelSDK-Java-v1.4.0-SOAP-"+m+"-"+o);
242+
soapClient.getRequestContext().put("HTTP_HEADER_USER_AGENT", "FuelSDK-Java-v1.5.0-SOAP-"+m+"-"+o);
243243
return soap;
244244
}
245245

0 commit comments

Comments
 (0)