Skip to content

Commit 0a5e747

Browse files
committed
New approach to standardizing OAuth
* Config declares necessary details for both methods, both implement OAuthAwareConfig declaring URL, scope, authCreds(), and sessionCreds(). * Response POJOs implement IAccessToken to check active status and provide session creds as WebParams. SF returns true for check and falls back to error checking. * OAuthMethod declared in config to pivot between configs. # Conflicts: # rest-client/src/main/java/com/compassion/commons/rest/client/auth/AccessToken.java
1 parent e3dcf6d commit 0a5e747

File tree

3 files changed

+109
-26
lines changed

3 files changed

+109
-26
lines changed
Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.compassion.commons.rest.client.auth;
22

3-
import java.util.concurrent.TimeUnit;
3+
import java.io.IOException;
44

55
import com.compassion.commons.rest.client.WebParam.WebHeader;
66
import com.compassion.commons.rest.client.WebParam.WebQueryParam;
@@ -11,38 +11,44 @@
1111

1212
import jakarta.ws.rs.client.ClientBuilder;
1313
import lombok.Getter;
14+
import lombok.NoArgsConstructor;
1415
import lombok.extern.log4j.Log4j2;
1516

1617
@Log4j2
17-
@Getter
18-
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
19-
public class AccessToken {
20-
private static final String SCOPE_KEY = "scope", GRANT_TYPE = "grant_type",
21-
CLIENT_CREDS = "client_credentials", DEF_ENDPOINT = "/oauth2/token";
18+
public abstract class AccessToken {
2219

23-
private String accessToken;
24-
private int expiresIn;
25-
private String tokenType;
26-
27-
@JsonIgnore
28-
private long expiresAfter;
20+
public static IAccessToken acquire(OAuthMethod method, OAuthAwareConfig config) throws IOException {
21+
log.info("Acquiring new access token for {}", config.baseUrl());
22+
23+
try (var client = new RestClient(ClientBuilder.newBuilder())) {
24+
var ret = client.request(RecursiveTarget.newTarget(config.baseUrl()), config.authCreds())
25+
.post(Entity.json(null));
26+
27+
if (ret.getStatus() < 200 || ret.getStatus() >= 300) {
28+
throw new IOException(
29+
String.format("Retrieving access token failed with status code %d and details: %s", ret.getStatus(), ret.readEntity(String.class)));
30+
}
31+
return ret.readEntity(method.getPojo());
32+
}
33+
}
2934

30-
public void setExpiresIn(int expiresIn) {
31-
this.expiresIn = expiresIn;
32-
this.expiresAfter = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiresIn - 5);
33-
log.info("Access token valid until {}", String.format("%1$tm/%1$td %1$tI:%1$tM:%1$tS", expiresAfter));
35+
public interface IAccessToken {
36+
Boolean checkActive();
37+
WebParam providedSessionCreds();
3438
}
3539

36-
public static AccessToken acquire(AuthEnvironment env, String scope, WebHeader httpAuth) {
37-
log.info("Acquiring new access token for {}", env.getAuthSubdomain());
40+
@NoArgsConstructor @AllArgsConstructor @Getter
41+
public enum OAuthMethod {
42+
SALESFORCE(SFSessionResponse.class),
43+
OATMEAL(OatmealSessionResponse.class);
3844

39-
try (var client = new RestClient(ClientBuilder.newBuilder())) {
40-
client.setBase(String.format("https://%s.ci.org", env.getAuthSubdomain()))
41-
.addPerpetualParams(httpAuth);
42-
43-
return client.request(RecursiveTarget.newTarget(DEF_ENDPOINT), WebQueryParam.of(GRANT_TYPE, CLIENT_CREDS),
44-
WebQueryParam.of(SCOPE_KEY, scope))
45-
.get(AccessToken.class);
46-
}
45+
private Class<? extends IAccessToken> pojo;
46+
}
47+
48+
public interface OAuthAwareConfig {
49+
WebParam authCreds();
50+
WebParam sessionCreds();
51+
String getScope();
52+
String baseUrl();
4753
}
4854
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.compassion.commons.rest.client.auth;
2+
3+
import java.util.concurrent.TimeUnit;
4+
5+
import org.apache.commons.lang3.StringUtils;
6+
7+
import com.compassion.commons.rest.client.WebParam;
8+
import com.compassion.commons.rest.client.WebParam.WebHeader;
9+
import com.compassion.commons.rest.client.auth.AccessToken.IAccessToken;
10+
import com.fasterxml.jackson.annotation.JsonIgnore;
11+
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
12+
import com.fasterxml.jackson.databind.annotation.JsonNaming;
13+
import com.google.common.net.HttpHeaders;
14+
15+
import lombok.Getter;
16+
import lombok.Setter;
17+
import lombok.extern.log4j.Log4j2;
18+
19+
@Getter @Setter @Log4j2
20+
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
21+
public class OatmealSessionResponse implements IAccessToken {
22+
private String accessToken;
23+
private int expiresIn;
24+
private String tokenType;
25+
@JsonIgnore private long expiresAfter;
26+
27+
public void setExpiresIn(int expiresIn) {
28+
this.expiresIn = expiresIn;
29+
this.expiresAfter = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiresIn - 5);
30+
log.info("Access token valid until {}", String.format("%1$tm/%1$td %1$tI:%1$tM:%1$tS", expiresAfter));
31+
}
32+
33+
@Override
34+
public Boolean checkActive() {
35+
return accessToken != null && System.currentTimeMillis() > getExpiresAfter();
36+
}
37+
38+
@Override
39+
public WebParam providedSessionCreds() {
40+
return WebHeader.of(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken());
41+
}
42+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.compassion.commons.rest.client.auth;
2+
3+
import org.apache.commons.lang3.StringUtils;
4+
5+
import com.compassion.commons.rest.client.WebParam;
6+
import com.compassion.commons.rest.client.WebParam.WebHeader;
7+
import com.compassion.commons.rest.client.auth.AccessToken.IAccessToken;
8+
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
9+
import com.fasterxml.jackson.databind.annotation.JsonNaming;
10+
import com.google.common.net.HttpHeaders;
11+
12+
import lombok.Getter;
13+
import lombok.Setter;
14+
import lombok.experimental.Accessors;
15+
16+
@Getter @Setter @Accessors(chain = true)
17+
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
18+
public class SFSessionResponse implements IAccessToken {
19+
20+
private String accessToken;
21+
private String instanceUrl;
22+
private String tokenType;
23+
private String issuedAt;
24+
private String id, signature;
25+
26+
@Override
27+
public Boolean checkActive() {
28+
// Salesforce does not provide expiration details so status is only known when a request fails.
29+
return true;
30+
}
31+
@Override
32+
public WebParam providedSessionCreds() {
33+
return WebHeader.of(HttpHeaders.AUTHORIZATION, StringUtils.joinWith(" ", getTokenType(), getAccessToken()));
34+
}
35+
}

0 commit comments

Comments
 (0)