diff --git a/.github/workflows/maven-itest.yml b/.github/workflows/maven-itest.yml
index 5bce429a..2068225b 100644
--- a/.github/workflows/maven-itest.yml
+++ b/.github/workflows/maven-itest.yml
@@ -56,6 +56,41 @@ jobs:
aio_api_url: ${{ secrets.aio_api_url }}
aio_publish_url: ${{ secrets.aio_publish_url }}
+ stage_oauth_itest:
+ runs-on: ubuntu-latest
+ environment: aio_stage_oauth
+ strategy:
+ fail-fast: true
+
+ steps:
+
+ # Check out Git repository
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ # Set up environment with Java and Maven
+ - name: Setup JDK
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'temurin'
+ java-version: 11
+ cache: maven
+
+ # Build & Test
+ - name: Stage Integration Test with Maven
+ run: mvn -Daio_publish_url=$aio_publish_url -Daio_api_url=$aio_api_url -Daio_ims_url=$aio_ims_url -Daio_oauth_scopes=$aio_oauth_scopes -Daio_ims_org_id=$aio_ims_org_id -Daio_consumer_org_id=$aio_consumer_org_id -Daio_project_id=$aio_project_id -Daio_workspace_id=$aio_workspace_id -Daio_api_key=$aio_api_key -Daio_client_secret=$aio_client_secret verify -Pitest
+ env:
+ aio_ims_url: ${{ secrets.aio_ims_url }}
+ aio_client_secret: ${{ secrets.aio_client_secret }}
+ aio_oauth_scopes: ${{ secrets.aio_oauth_scopes }}
+ aio_ims_org_id: ${{ secrets.aio_ims_org_id }}
+ aio_consumer_org_id: ${{ secrets.aio_consumer_org_id }}
+ aio_project_id: ${{ secrets.aio_project_id }}
+ aio_workspace_id: ${{ secrets.aio_workspace_id }}
+ aio_api_key: ${{ secrets.aio_api_key }}
+ aio_api_url: ${{ secrets.aio_api_url }}
+ aio_publish_url: ${{ secrets.aio_publish_url }}
+
prod_itest:
runs-on: ubuntu-latest
environment: aio_prod
@@ -93,8 +128,3 @@ jobs:
aio_encoded_pkcs8: ${{ secrets.aio_encoded_pkcs8 }}
aio_api_url: ${{ secrets.aio_api_url }}
aio_publish_url: ${{ secrets.aio_publish_url }}
-
-
-
-
-
diff --git a/aem/aio_aem_events/pom.xml b/aem/aio_aem_events/pom.xml
index e8241808..c58de5da 100644
--- a/aem/aio_aem_events/pom.xml
+++ b/aem/aio_aem_events/pom.xml
@@ -22,7 +22,7 @@
com.adobe.aio.aem
aio-aem
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
aio-aem-events
diff --git a/aem/core_aem/README.md b/aem/core_aem/README.md
index 2fea19e0..d7fbd03e 100644
--- a/aem/core_aem/README.md
+++ b/aem/core_aem/README.md
@@ -5,7 +5,7 @@ wrapping [`aio-lib-java-core`](../../core) and [`aio-lib-java-ims`](../../ims)
It hosts the services to
* get the Adobe Developer Console Workspace
-* get Access token (from JWT exchange token flow) from Adobe Identity Management System (IMS)
+* get Access token (using either JWT or OAuth token flow) from Adobe Identity Management System (IMS)
## `Workspace` Configuration
@@ -18,28 +18,22 @@ service looks up the following OSGI configuration keys:
* `aio.consumer.org.id` your Adobe Developer Console consumer orgnaization id (`project.org.id`)
* `aio.ims.org.id` your Adobe Developer Console IMS Organization ID (`project.org.ims_org_id`)
* `aio.workspace.id` your Adobe Developer Console workspace Id (`project.workspace.id`)
-* `aio.credential.id` your Adobe Developer Console jwt credential id (`project.workspace.details.credentials[i].id`)
-* `aio.api.key` your Adobe Developer Console jwt credential API Key (or Client ID) (`project.workspace.details.credentials[i].jwt.client_id`)
-* `aio.client.secret` your Adobe Developer Console jwt credential client secret (`project.workspace.details.credentials[i].jwt.client_secret`)
-* `aio.meta.scopes` a comma separated list of metascopes associated with your API, see your Adobe Developer Console jwt credential metascopes (`project.workspace.details.credentials[i].jwt.meta_scopes`)
-* `aio.technical.account.id` your Adobe Developer Console jwt credential technical account id (`project.workspace.details.credentials[i].jwt.technical_account_id`)
-* `aio.encoded.pkcs8` your private key (in a base64 encoded pkcs8 format) see below
+* `aio.api.key` your Adobe Developer Console credential API Key (or Client ID)
+When using JWT credentials also set
+* `aio.credential.id` your Adobe Developer Console jwt credential id
+* `aio.client.secret` your Adobe Developer Console jwt credential client secret
+* `aio.meta.scopes` a comma separated list of metascopes associated with your API, see your Adobe Developer Console jwt credential metascopes
+* `aio.technical.account.id` your Adobe Developer Console jwt credential technical account id
+* `aio.encoded.pkcs8` your private key (in a base64 encoded pkcs8 format)
-### `aio.encoded.pkcs8`
+When using OAuth credentials also set
+* `aio.client.secret` your Adobe Developer Console oAuth credential client secret
+* `aio_oauth_scopes` a comma separated list of OAuth scopes associated with your API, see your Adobe Developer Console OAuth scopes (project.workspace.details.credentials[i].oauth_server_to_server.scopes)
-`aio.encoded.pkcs8` configuration value is associated with your Adobe Developer Console private key.
-It is a string: your private key in a pkcs8 format, base64 encoded, here is how to generate it:
-
-First, convert your private key to a PKCS8 format, use the following command:
-
- openssl pkcs8 -topk8 -inform PEM -outform DER -in private.key -nocrypt > private.pkcs8.key
-
-Then, base 64 encode it, use the following command:
-
- base64 private.pkcs8.key
-
-For more details check our [`aio-lib-java-ims` documentation](../../ims/README.md)
+For more details on the above please refer to
+* [`aio-lib-java-core` docs](../../core/README.md) for more details
+* [`aio-lib-java-ims` docs](../../ims/README.md) for more details
### `on premise` AEM configuration:
When running AEM on premise:
@@ -66,19 +60,7 @@ The response json payload should like this:
"workspace": {
"imsUrl": "https://ims-na1.adobelogin.com",
"imsOrgId": "...@AdobeOrg",
- "apiKey": "...",
- "credentialId": "...",
- "technicalAccountId": "...@techacct.adobe.com",
- "metascopes": [
- "...",
- "/s/ent_adobeio_sdk"
- ],
- "consumerOrgId": "...",
- "projectId": "...",
- "workspaceId": "...",
- "projectUrl": "https://developer.adobe.com/console/projects/.../.../overview",
- "clientSecretDefined": true,
- "privateKeyDefined": true
+ "apiKey": "..."
}
},
"error": null
diff --git a/aem/core_aem/pom.xml b/aem/core_aem/pom.xml
index a6d62933..9ad0fb4b 100644
--- a/aem/core_aem/pom.xml
+++ b/aem/core_aem/pom.xml
@@ -19,7 +19,7 @@
com.adobe.aio.aem
aio-aem
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
aio-aem-core
diff --git a/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/internal/WorkspaceSupplierImpl.java b/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/internal/WorkspaceSupplierImpl.java
index aeaf2b93..eb4e8c97 100644
--- a/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/internal/WorkspaceSupplierImpl.java
+++ b/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/internal/WorkspaceSupplierImpl.java
@@ -14,9 +14,12 @@
import com.adobe.aio.aem.status.Status;
import com.adobe.aio.aem.workspace.WorkspaceSupplier;
import com.adobe.aio.aem.workspace.ocd.WorkspaceConfig;
+import com.adobe.aio.auth.Context;
+import com.adobe.aio.auth.JwtContext;
+import com.adobe.aio.auth.OAuthContext;
import com.adobe.aio.ims.util.PrivateKeyBuilder;
+import com.adobe.aio.util.WorkspaceUtil;
import com.adobe.aio.workspace.Workspace;
-import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
@@ -48,8 +51,6 @@ protected void activate(final WorkspaceConfig config) {
public Status getStatus() {
Map details = new HashMap<>();
try {
- details.put("workspace", Workspace.builder()
- .configMap(getAuthConfigMap(workspaceConfig)).build());
Workspace workspace = getWorkspace();
details.put("workspace", workspace);
workspace.validateAll();
@@ -67,33 +68,35 @@ public Status getStatus() {
*/
@Override
public Workspace getWorkspace() {
- if (!StringUtils.isEmpty(workspaceConfig.aio_encoded_pkcs8())) {
- PrivateKey privateKey = new PrivateKeyBuilder()
- .encodedPkcs8Key(workspaceConfig.aio_encoded_pkcs8()).build();
- return Workspace.builder()
- .configMap(getAuthConfigMap(workspaceConfig))
- .privateKey(privateKey).build();
- } else {
- return Workspace.builder()
- .configMap(getAuthConfigMap(workspaceConfig)).build();
- }
+ return WorkspaceUtil.getWorkspaceBuilder(getAuthConfigMap(workspaceConfig)).build();
}
private Map getAuthConfigMap(
WorkspaceConfig config) {
Map map = new HashMap();
- map.put(Workspace.API_KEY, config.aio_api_key());
- map.put(Workspace.CLIENT_SECRET, config.aio_client_secret());
- map.put(Workspace.CONSUMER_ORG_ID, config.aio_consumer_org_id());
- map.put(Workspace.CREDENTIAL_ID, config.aio_credential_id());
- map.put(Workspace.IMS_ORG_ID, config.aio_ims_org_id());
- map.put(Workspace.IMS_URL, config.aio_ims_url());
- map.put(Workspace.PROJECT_ID, config.aio_project_id());
- map.put(Workspace.TECHNICAL_ACCOUNT_ID, config.aio_technical_account_id());
- map.put(Workspace.WORKSPACE_ID, config.aio_workspace_id());
- map.put(Workspace.META_SCOPES, config.aio_meta_scopes());
+ putIfNotBlank(map, Workspace.API_KEY, config.aio_api_key());
+ putIfNotBlank(map, Workspace.CONSUMER_ORG_ID, config.aio_consumer_org_id());
+ putIfNotBlank(map, Workspace.IMS_ORG_ID, config.aio_ims_org_id());
+ putIfNotBlank(map, Workspace.IMS_URL, config.aio_ims_url());
+ putIfNotBlank(map, Workspace.PROJECT_ID, config.aio_project_id());
+ putIfNotBlank(map, Workspace.WORKSPACE_ID, config.aio_workspace_id());
+ putIfNotBlank(map, Workspace.CREDENTIAL_ID, config.aio_credential_id());
+
+ putIfNotBlank(map, Context.CLIENT_SECRET, config.aio_client_secret());
+
+
+ putIfNotBlank(map, JwtContext.TECHNICAL_ACCOUNT_ID, config.aio_technical_account_id());
+ putIfNotBlank(map, JwtContext.META_SCOPES, config.aio_meta_scopes());
+ putIfNotBlank(map, PrivateKeyBuilder.AIO_ENCODED_PKCS_8, config.aio_encoded_pkcs8());
+
+ putIfNotBlank(map, OAuthContext.SCOPES, config.aio_oauth_scopes());
return map;
}
+ private void putIfNotBlank(Map map, String key, String value) {
+ if (StringUtils.isNotBlank(value)) {
+ map.put(key, value);
+ }
+ }
}
diff --git a/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/ocd/WorkspaceConfig.java b/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/ocd/WorkspaceConfig.java
index d54ff780..9b8d662f 100644
--- a/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/ocd/WorkspaceConfig.java
+++ b/aem/core_aem/src/main/java/com/adobe/aio/aem/workspace/ocd/WorkspaceConfig.java
@@ -22,10 +22,14 @@
description = "Adobe IMS URL: prod: https://ims-na1.adobelogin.com | stage: https://ims-na1-stg1.adobelogin.com")
String aio_ims_url() default "https://ims-na1.adobelogin.com";
- @AttributeDefinition(name = "Meta Scopes",
- description = "Comma separated list of metascopes associated with your API (`/s/event_receiver_api,/s/ent_adobeio_sdk` for instance) (project.workspace.details.credentials.jwt.meta_scopes)")
+ @AttributeDefinition(name = "JWT Meta Scopes (For deprecated JWT Auth only)",
+ description = "Comma separated list of metascopes associated with your API (`/s/event_receiver_api,/s/ent_adobeio_sdk` for instance) (project.workspace.details.credentials.jwt.meta_scopes), to be used for deprecated JWT Auth only.")
String aio_meta_scopes() default "/s/ent_adobeio_sdk";
+ @AttributeDefinition(name = "OAuth Scopes",
+ description = "Comma separated String. list of oauth scopes associated with your API (project.workspace.details.credentials.oauth_server_to_server.scopes)")
+ String aio_oauth_scopes();
+
@AttributeDefinition(name = "IMS ORG ID",
description = "Adobe IMS Organization ID as shown in your Adobe Developer Console workspace (project.org.ims_org_id)")
String aio_ims_org_id();
@@ -43,23 +47,23 @@
String aio_workspace_id();
@AttributeDefinition(name = "API Key (Client ID)",
- description = "Adobe I/O API Key (Client ID) as shown in in your Adobe Developer Console workspace (project.workspace.details.credentials.jwt.client_id)")
+ description = "Adobe I/O API Key (Client ID) as shown in in your Adobe Developer Console workspace")
String aio_api_key();
@AttributeDefinition(name = "Credential ID",
description = "Adobe I/O Credential ID as shown in your Adobe Developer Console workspace (project.workspace.details.credentials.id)")
String aio_credential_id();
- @AttributeDefinition(name = "Technical Account ID",
+ @AttributeDefinition(name = "Technical Account ID (For deprecated JWT Auth only)",
description = "Technical account ID as shown in your Adobe Developer Console workspace (project.workspace.details.credentials.jwt.technical_account_id)")
String aio_technical_account_id();
@AttributeDefinition(name = "Client Secret",
- description = "Adobe I/O Client Secret as shown in your Adobe Developer Console workspace (project.workspace.details.credentials.jwt.client_secret)")
+ description = "Adobe I/O Client Secret as shown in your Adobe Developer Console workspace")
String aio_client_secret();
- @AttributeDefinition(name = "Private Key",
- description = "Base64 encoded pkcs8 Private Key.")
+ @AttributeDefinition(name = "Private Key (For deprecated JWT Auth only)",
+ description = "Base64 encoded pkcs8 Private Key (For deprecated JWT Auth only).")
String aio_encoded_pkcs8();
}
diff --git a/aem/events_ingress_aem/pom.xml b/aem/events_ingress_aem/pom.xml
index d91efe8a..6163f101 100644
--- a/aem/events_ingress_aem/pom.xml
+++ b/aem/events_ingress_aem/pom.xml
@@ -19,7 +19,7 @@
com.adobe.aio.aem
aio-aem
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
aio-aem-events-publish
diff --git a/aem/events_mgmt_aem/pom.xml b/aem/events_mgmt_aem/pom.xml
index ae15dd31..e812ed67 100644
--- a/aem/events_mgmt_aem/pom.xml
+++ b/aem/events_mgmt_aem/pom.xml
@@ -19,7 +19,7 @@
com.adobe.aio.aem
aio-aem
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
aio-aem-events-mgmt
diff --git a/aem/events_osgi_mapping/pom.xml b/aem/events_osgi_mapping/pom.xml
index 10d575b7..3476042d 100644
--- a/aem/events_osgi_mapping/pom.xml
+++ b/aem/events_osgi_mapping/pom.xml
@@ -19,7 +19,7 @@
com.adobe.aio.aem
aio-aem
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
aio-aem-events-osgi-mapping
diff --git a/aem/lib_osgi/pom.xml b/aem/lib_osgi/pom.xml
index dea994f9..54c425af 100644
--- a/aem/lib_osgi/pom.xml
+++ b/aem/lib_osgi/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio.aem
aio-aem
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
aio-lib-osgi
diff --git a/aem/pom.xml b/aem/pom.xml
index 91dbee62..b559657b 100644
--- a/aem/pom.xml
+++ b/aem/pom.xml
@@ -19,7 +19,7 @@
com.adobe.aio
aio-lib-java
../pom.xml
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
com.adobe.aio.aem
diff --git a/core/README.md b/core/README.md
index 3f51976a..578f636e 100644
--- a/core/README.md
+++ b/core/README.md
@@ -10,7 +10,9 @@ This library holds a [`Workspace`](./src/main/java/com/adobe/aio/workspace/Works
your [Adobe Developer Console Project Workspace](https://www.adobe.io/apis/experienceplatform/console/docs.html#!AdobeDocs/adobeio-console/master/projects.md),
To get you started quickly use a `.properties` file,
-* see our [sample config file](./src/test/resources/workspace.properties) in our jUnit Test.
+* see our sample config files:
+ * [workspace.jwt.properties](./src/test/resources/workspace.jwt.properties)
+ * [workspace.oauth.properties](./src/test/resources/workspace.oauth.properties)
* download your `project` configurations file from your Adobe Developer Console Project overview page
* map your `project` configurations with this properties
@@ -23,9 +25,11 @@ The `Workspace` POJO holds your Adobe Developer Console Project configurations
* `aio_consumer_org_id` your Adobe Developer Console consumer orgnaization id (`project.org.id`)
* `aio_ims_org_id` your Adobe Developer Console IMS Organization ID (`project.org.ims_org_id`)
* `aio_workspace_id` your Adobe Developer Console workspace Id (`project.workspace.id`)
+* `aio_credential_id` your Adobe Developer Console credential id (`project.workspace.details.credentials[i].id`)
+ * this is optional, but it might be handy to have it in your `Workspace` POJO, to avoid confusion when you have multiple credentials, and to eventually in some Adobe API calls
### Workspace Authentication Context
-The `Workspace` POJO must also hold your Adobe Developer Auth configurations, pick one of the following authentication methods:
+The `Workspace` POJO must also hold your Adobe Developer Auth configurations, pick one of the following authentication methods (see [aio-lib-java-ims](../ims/README.md) docs for more details):
#### OAuth2 authentication
For [OAuth2 authentication](https://developer.adobe.com/developer-console/docs/guides/authentication/ServerToServerAuthentication/#oauth-server-to-server-credential), you will need to provide the following properties:
@@ -35,20 +39,13 @@ For [OAuth2 authentication](https://developer.adobe.com/developer-console/docs/g
#### JWT authentication
For [JWT authentication](https://developer.adobe.com/developer-console/docs/guides/authentication/ServerToServerAuthentication/#service-account-jwt-credential-deprecated), you will need to provide the following properties:
-* `aio_credential_id` your Adobe Developer Console jwt credential id (`project.workspace.details.credentials[i].id`)
* `aio_client_secret` your Adobe Developer Console jwt credential client secret (`project.workspace.details.credentials[i].jwt.client_secret`)
* `aio_api_key` your Adobe Developer Console jwt credential API Key (or Client ID) (`project.workspace.details.credentials[i].jwt.client_id`)
* `aio_meta_scopes` a comma separated list of metascopes associated with your API, see your Adobe Developer Console jwt credential metascopes (`project.workspace.details.credentials[i].jwt.meta_scopes`)
* `aio_technical_account_id` your Adobe Developer Console jwt credential technical account id (`project.workspace.details.credentials[i].jwt.technical_account_id`)
+* `aio_encoded_pkcs8` your privateKey (associated with the public key set in your Adobe Developer Console workspace) in a base64 encoded pkcs8 format
-On top of these, the [`Workspace`](./src/main/java/com/adobe/aio/workspace/Workspace.java) POJO can also hold your JWT private Key
-(associated with the public key you uploaded in your Adobe Developer Console Workspace)
-this will help to power Adobe JWT authentication flow and transparently add the proper `Bearer`
-authentication token to all your request,
-Note the easiest way is to stuff your Private Key as a `pkcs8` base64 encoded String
-using the `aio_encoded_pkcs8` property key.
-confer [aio-lib-java-ims](../ims/README.md#Create-and-configure-your-public-and-private-key) documentation for more details.
## Builds
diff --git a/core/pom.xml b/core/pom.xml
index 72e0ec38..683bc706 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/core/src/main/java/com/adobe/aio/auth/Context.java b/core/src/main/java/com/adobe/aio/auth/Context.java
index f0bd8025..48c026d3 100644
--- a/core/src/main/java/com/adobe/aio/auth/Context.java
+++ b/core/src/main/java/com/adobe/aio/auth/Context.java
@@ -19,13 +19,10 @@
public interface Context {
/**
- * Property name used in maps and config files for setting the AIO IMS URL.
+ * Property name for looking up Authentication Client Secret in various contexts.
+ * Reference: AIO Developer Documentation
*/
- public static final String IMS_URL = "aio_ims_url";
- /**
- * Property name used in maps and config files for setting the AIO IMS Org Id.
- */
- public static final String IMS_ORG_ID = "aio_ims_org_id";
+ String CLIENT_SECRET = "aio_client_secret";
/**
* Validates this context is minimally populated and able to function.
diff --git a/core/src/main/java/com/adobe/aio/auth/JwtContext.java b/core/src/main/java/com/adobe/aio/auth/JwtContext.java
index 4f4ca233..fed94d4e 100644
--- a/core/src/main/java/com/adobe/aio/auth/JwtContext.java
+++ b/core/src/main/java/com/adobe/aio/auth/JwtContext.java
@@ -13,37 +13,28 @@
import java.security.PrivateKey;
import java.util.HashSet;
-import java.util.Map;
import java.util.Objects;
-import java.util.Properties;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import com.fasterxml.jackson.annotation.JsonIgnore;
-import static com.adobe.aio.util.FileUtil.*;
-
/**
* JWT Authentication context.
*/
public class JwtContext implements Context {
- public static final String CREDENTIAL_ID = "aio_credential_id";
- public static final String CLIENT_SECRET = "aio_client_secret";
+
public static final String TECHNICAL_ACCOUNT_ID = "aio_technical_account_id";
public static final String META_SCOPES = "aio_meta_scopes";
- private final String credentialId;
private final String technicalAccountId;
private final Set metascopes;
private final String clientSecret;
private final PrivateKey privateKey;
- public JwtContext(final String credentialId, final String clientSecret, final String technicalAccountId,
+ public JwtContext(final String clientSecret, final String technicalAccountId,
final Set metascopes, final PrivateKey privateKey) {
- this.credentialId = credentialId;
this.clientSecret = clientSecret;
this.technicalAccountId = technicalAccountId;
this.metascopes = metascopes;
@@ -69,10 +60,6 @@ public void validate() {
}
}
- public String getCredentialId() {
- return credentialId;
- }
-
public String getTechnicalAccountId() {
return technicalAccountId;
}
@@ -108,7 +95,6 @@ public boolean equals(Object o) {
JwtContext that = (JwtContext) o;
- if (!Objects.equals(credentialId, that.credentialId)) return false;
if (!Objects.equals(technicalAccountId, that.technicalAccountId))
return false;
if (!Objects.equals(metascopes, that.metascopes)) return false;
@@ -118,8 +104,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
- int result = credentialId != null ? credentialId.hashCode() : 0;
- result = 31 * result + (technicalAccountId != null ? technicalAccountId.hashCode() : 0);
+ int result = technicalAccountId != null ? technicalAccountId.hashCode() : 0;
result = 31 * result + (metascopes != null ? metascopes.hashCode() : 0);
result = 31 * result + (clientSecret != null ? clientSecret.hashCode() : 0);
result = 31 * result + (privateKey != null ? privateKey.hashCode() : 0);
@@ -129,25 +114,18 @@ public int hashCode() {
@Override
public String toString() {
return "JwtContext{" +
- "credentialId='" + credentialId + '\'' +
- ", technicalAccountId='" + technicalAccountId + '\'' +
+ "technicalAccountId='" + technicalAccountId + '\'' +
", metascopes=" + metascopes +
'}';
}
public static class Builder {
- private String credentialId;
private String clientSecret;
private String technicalAccountId;
private PrivateKey privateKey;
private final Set metascopes = new HashSet<>();
- public Builder credentialId(final String credentialId) {
- this.credentialId = credentialId;
- return this;
- }
-
public Builder clientSecret(final String clientSecret) {
this.clientSecret = clientSecret;
return this;
@@ -168,36 +146,8 @@ public Builder privateKey(final PrivateKey privateKey) {
return this;
}
- public Builder configMap(final Map configMap) {
- this
- .credentialId(configMap.get(CREDENTIAL_ID))
- .clientSecret(configMap.get(CLIENT_SECRET))
- .technicalAccountId(configMap.get(TECHNICAL_ACCOUNT_ID));
- if (!StringUtils.isEmpty(configMap.get(META_SCOPES))) {
- String[] metascopeArray = configMap.get(META_SCOPES).split(",");
- for (String metascope : metascopeArray) {
- this.addMetascope(metascope);
- }
- }
- return this;
- }
-
- public Builder systemEnv() {
- return configMap(System.getenv());
- }
-
- public Builder propertiesPath(final String propertiesPath) {
- return properties(
- readPropertiesFromFile(propertiesPath)
- .orElse(readPropertiesFromClassPath(propertiesPath)));
- }
-
- public Builder properties(final Properties properties) {
- return configMap(getMapFromProperties(properties));
- }
-
public JwtContext build() {
- return new JwtContext(credentialId, clientSecret, technicalAccountId, metascopes, privateKey);
+ return new JwtContext(clientSecret, technicalAccountId, metascopes, privateKey);
}
}
}
diff --git a/core/src/main/java/com/adobe/aio/auth/OAuthContext.java b/core/src/main/java/com/adobe/aio/auth/OAuthContext.java
index f361caa6..b818464a 100644
--- a/core/src/main/java/com/adobe/aio/auth/OAuthContext.java
+++ b/core/src/main/java/com/adobe/aio/auth/OAuthContext.java
@@ -29,11 +29,6 @@
* Reference: OAuth Client Credentials
*/
public class OAuthContext implements Context {
- /**
- * Property name for looking up Authentication Client Secret in various contexts.
- * Reference: AIO Developer Documentation
- */
- public static final String CLIENT_SECRET = "aio_client_secret";
/**
* Property name for looking up Authentication Scopes in various contexts.
* Reference: AIO Developer Documentation
@@ -112,26 +107,6 @@ public Builder addScope(final String scope) {
return this;
}
- public Builder configMap(final Map configMap) {
- this.clientSecret(configMap.get(CLIENT_SECRET));
- if (!StringUtils.isEmpty(configMap.get(SCOPES))) {
- Arrays.stream(configMap.get(SCOPES).split(",")).forEach(this::addScope);
- }
- return this;
- }
-
- public Builder systemEvn() {
- return configMap(System.getenv());
- }
-
- public Builder propertiesPath(final String propertiesPath) {
- return properties(readPropertiesFromFile(propertiesPath).orElse(readPropertiesFromClassPath(propertiesPath)));
- }
-
- public Builder properties(final Properties properties) {
- return configMap(getMapFromProperties(properties));
- }
-
public OAuthContext build() {
return new OAuthContext(clientSecret, scopes);
}
diff --git a/core/src/main/java/com/adobe/aio/util/Constants.java b/core/src/main/java/com/adobe/aio/util/Constants.java
index 88e5783b..f24924fc 100644
--- a/core/src/main/java/com/adobe/aio/util/Constants.java
+++ b/core/src/main/java/com/adobe/aio/util/Constants.java
@@ -17,7 +17,7 @@ public class Constants {
public static final String BEARER_PREFIX = "Bearer ";
public static final String API_KEY_HEADER = "x-api-key";
public static final String IMS_ORG_HEADER = "x-gw-ims-org-id";
- public static final String IMS_URL = "https://ims-na1.adobelogin.com";
+ public static final String PROD_IMS_URL = "https://ims-na1.adobelogin.com";
public static final String API_MANAGEMENT_URL = "https://api.adobe.io";
public static final String CUSTOM_EVENTS_PROVIDER_METADATA_ID = "3rd_party_custom_events";
diff --git a/core/src/main/java/com/adobe/aio/util/FileUtil.java b/core/src/main/java/com/adobe/aio/util/FileUtil.java
index 837be638..153e869c 100644
--- a/core/src/main/java/com/adobe/aio/util/FileUtil.java
+++ b/core/src/main/java/com/adobe/aio/util/FileUtil.java
@@ -11,23 +11,23 @@
*/
package com.adobe.aio.util;
-import com.adobe.aio.exception.AIOException;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
+
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
-import java.util.Optional;
import java.util.Properties;
-import org.apache.commons.lang3.StringUtils;
public class FileUtil {
private FileUtil() {
}
- public static Map getMapFromProperties(final Properties properties) {
+ public static Map getMap(final String propertiesClassPath) {
+ return getMap(getProperties(propertiesClassPath));
+ }
+
+ public static Map getMap(final Properties properties) {
Map map = new HashMap<>();
for (final String name : properties.stringPropertyNames()) {
map.put(name, properties.getProperty(name));
@@ -35,29 +35,18 @@ public static Map getMapFromProperties(final Properties properti
return map;
}
- public static Optional readPropertiesFromFile(final String configFilePath) {
- if (StringUtils.isEmpty(configFilePath)) {
- return Optional.empty();
- } else {
- try (InputStream in = new FileInputStream(configFilePath)) {
- return Optional.of(read(in));
- } catch (FileNotFoundException e) {
- return Optional.empty();
- } catch (IOException e) {
- throw new AIOException("Unable to load your Properties from File " + configFilePath, e);
- }
- }
- }
-
- public static Properties readPropertiesFromClassPath(final String configClassPath) {
- try (InputStream in = FileUtil.class.getClassLoader().getResourceAsStream(configClassPath)) {
+ public static Properties getProperties(final String propertiesClassPath) {
+ try (InputStream in = FileUtil.class.getClassLoader().getResourceAsStream(propertiesClassPath)) {
return read(in);
- } catch (IOException e) {
- throw new AIOException("Unable to load your Properties from class path " + configClassPath, e);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Unable to load your Properties from class path " + propertiesClassPath, e);
}
}
private static Properties read(InputStream in) throws IOException {
+ if (in == null) {
+ throw new IllegalArgumentException("InputStream cannot be null");
+ }
Properties prop = new Properties();
prop.load(in);
in.close();
diff --git a/core/src/main/java/com/adobe/aio/workspace/Workspace.java b/core/src/main/java/com/adobe/aio/workspace/Workspace.java
index cd6986d5..28e02579 100644
--- a/core/src/main/java/com/adobe/aio/workspace/Workspace.java
+++ b/core/src/main/java/com/adobe/aio/workspace/Workspace.java
@@ -11,17 +11,13 @@
*/
package com.adobe.aio.workspace;
-import static com.adobe.aio.util.FileUtil.getMapFromProperties;
-import static com.adobe.aio.util.FileUtil.readPropertiesFromClassPath;
-import static com.adobe.aio.util.FileUtil.readPropertiesFromFile;
import com.adobe.aio.auth.Context;
import com.adobe.aio.auth.JwtContext;
+import com.adobe.aio.auth.OAuthContext;
import com.adobe.aio.util.Constants;
-import java.security.PrivateKey;
import java.util.Map;
import java.util.Objects;
-import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
public class Workspace {
@@ -32,46 +28,27 @@ public class Workspace {
public static final String PROJECT_ID = "aio_project_id";
public static final String WORKSPACE_ID = "aio_workspace_id";
public static final String API_KEY = "aio_api_key";
- /**
- * @deprecated This will be removed in v2.0 of the library.
- */
- @Deprecated
public static final String CREDENTIAL_ID = "aio_credential_id";
- /**
- * @deprecated This will be removed in v2.0 of the library.
- */
- @Deprecated
- public static final String CLIENT_SECRET = "aio_client_secret";
- /**
- * @deprecated This will be removed in v2.0 of the library.
- */
- @Deprecated
- public static final String TECHNICAL_ACCOUNT_ID = "aio_technical_account_id";
- /**
- * @deprecated This will be removed in v2.0 of the library.
- */
- @Deprecated
- public static final String META_SCOPES = "aio_meta_scopes";
- // workspace context related:
private final String imsUrl;
private final String imsOrgId;
private final String apiKey;
private final String consumerOrgId;
private final String projectId;
private final String workspaceId;
+ private final String credentialId;
private final Context authContext;
private Workspace(final String imsUrl, final String imsOrgId, final String apiKey,
final String consumerOrgId, final String projectId, final String workspaceId,
- Context authContext) {
- this.imsUrl = StringUtils.isEmpty(imsUrl) ? Constants.IMS_URL : imsUrl;
+ final String credentialId, Context authContext) {
+ this.imsUrl = StringUtils.isEmpty(imsUrl) ? Constants.PROD_IMS_URL : imsUrl;
this.imsOrgId = imsOrgId;
-
this.apiKey = apiKey;
this.consumerOrgId = consumerOrgId;
this.projectId = projectId;
this.workspaceId = workspaceId;
+ this.credentialId = credentialId;
this.authContext = authContext;
}
@@ -80,8 +57,11 @@ public static Builder builder() {
}
public void validateAll() {
- authContext.validate();
validateWorkspaceContext();
+ if (!isAuthOAuth() && !isAuthJWT()) {
+ throw new IllegalStateException("Missing auth configuration, set either jwt or oauth...");
+ }
+ authContext.validate();
}
/**
@@ -105,6 +85,14 @@ public void validateWorkspaceContext() throws IllegalStateException {
if (StringUtils.isEmpty(this.getWorkspaceId())) {
throw new IllegalStateException("Your `Workspace` is missing a workspaceId");
}
+ // note that the credentialId is optional
+ // but it might be handy to have it in your `Workspace` POJO,
+ // to avoid confusion when you have multiple credentials,
+ // and to eventually in some Adobe API calls
+
+ if (authContext == null) {
+ throw new IllegalStateException("Missing auth configuration ...");
+ }
}
public String getProjectUrl() {
@@ -141,22 +129,21 @@ public String getWorkspaceId() {
return workspaceId;
}
+ public String getCredentialId() { return credentialId;}
+
public Context getAuthContext() {
return authContext;
}
- /**
- * @deprecated This will be removed in v2.0 of the library.
- */
- @Deprecated
- public String getCredentialId() {
- if (authContext instanceof JwtContext) {
- return ((JwtContext) authContext).getCredentialId();
- } else {
- return null;
- }
+ public boolean isAuthOAuth() {
+ return authContext!=null && authContext instanceof OAuthContext;
+ }
+
+ public boolean isAuthJWT() {
+ return authContext!=null && authContext instanceof JwtContext;
}
+
@Override
public boolean equals(Object o) {
if (this == o)
@@ -197,10 +184,10 @@ public static class Builder {
private String consumerOrgId;
private String projectId;
private String workspaceId;
+ private String credentialId;
private Map workspaceProperties;
- private JwtContext.Builder jwtbuilder;
private Context authContext;
private Builder() {
@@ -236,88 +223,19 @@ public Builder workspaceId(final String workspaceId) {
return this;
}
- public Builder authContext(final Context authContext) {
- this.authContext = authContext;
- return this;
- }
-
public Builder credentialId(final String credentialId) {
- if (jwtbuilder == null) {
- jwtbuilder = JwtContext.builder();
- }
- jwtbuilder.credentialId(credentialId);
- return this;
- }
-
- public Builder clientSecret(final String clientSecret) {
- if (jwtbuilder == null) {
- jwtbuilder = JwtContext.builder();
- }
- jwtbuilder.clientSecret(clientSecret);
- return this;
- }
-
- public Builder technicalAccountId(final String technicalAccountId) {
- if (jwtbuilder == null) {
- jwtbuilder = JwtContext.builder();
- }
- jwtbuilder.technicalAccountId(technicalAccountId);
- return this;
- }
-
- public Builder addMetascope(final String metascope) {
- if (jwtbuilder == null) {
- jwtbuilder = JwtContext.builder();
- }
- jwtbuilder.addMetascope(metascope);
+ this.credentialId = credentialId;
return this;
}
- public Builder privateKey(final PrivateKey privateKey) {
- if (jwtbuilder == null) {
- jwtbuilder = JwtContext.builder();
- }
- jwtbuilder.privateKey(privateKey);
- return this;
- }
-
- public Builder configMap(final Map configMap) {
- this
- .imsUrl(configMap.get(IMS_URL))
- .imsOrgId(configMap.get(IMS_ORG_ID))
- .apiKey(configMap.get(API_KEY))
- .consumerOrgId(configMap.get(CONSUMER_ORG_ID))
- .projectId(configMap.get(PROJECT_ID))
- .workspaceId(configMap.get(WORKSPACE_ID));
-
- // For backwards compatibility - should this be kept?
- jwtbuilder = JwtContext.builder();
- jwtbuilder.configMap(configMap);
+ public Builder authContext(final Context authContext) {
+ this.authContext = authContext;
return this;
}
- public Builder systemEnv() {
- return configMap(System.getenv());
- }
-
- public Builder propertiesPath(final String propertiesPath) {
- return properties(
- readPropertiesFromFile(propertiesPath)
- .orElse(readPropertiesFromClassPath(propertiesPath)));
- }
-
- public Builder properties(final Properties properties) {
- return configMap(getMapFromProperties(properties));
- }
-
public Workspace build() {
- if (authContext != null) {
- return new Workspace(imsUrl, imsOrgId, apiKey, consumerOrgId, projectId, workspaceId, authContext);
- }
- if (jwtbuilder == null) {
- jwtbuilder = JwtContext.builder();
- }
- return new Workspace(imsUrl, imsOrgId, apiKey, consumerOrgId, projectId, workspaceId, jwtbuilder.build());
+ return new Workspace(imsUrl, imsOrgId, apiKey, consumerOrgId, projectId, workspaceId, credentialId, authContext);
}
+
}
}
diff --git a/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java b/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java
index 60259f93..52613ca7 100644
--- a/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java
+++ b/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java
@@ -11,11 +11,8 @@
import org.junit.jupiter.api.Test;
public class JwtContextTest {
- private static final String TEST_PROPERTIES = "workspace.properties";
private static final String TEST_VALUE = "_changeMe";
- private static JwtContext expected;
-
private static PrivateKey privateKey;
@BeforeAll
@@ -24,23 +21,6 @@ public static void beforeClass() throws Exception {
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
- expected = JwtContext.builder().propertiesPath(TEST_PROPERTIES).privateKey(privateKey).build();
- }
-
- @Test
- void properties() {
- JwtContext actual = JwtContext.builder()
- .credentialId(CREDENTIAL_ID + TEST_VALUE)
- .technicalAccountId(TECHNICAL_ACCOUNT_ID + TEST_VALUE)
- .addMetascope(META_SCOPES + TEST_VALUE)
- .clientSecret(CLIENT_SECRET + TEST_VALUE)
- .privateKey(privateKey)
- .build();
-
- assertEquals(actual, expected);
- assertEquals(actual.hashCode(), expected.hashCode());
- assertEquals(actual.toString(), expected.toString());
- actual.validate();
}
@Test
diff --git a/core/src/test/java/com/adobe/aio/auth/OAuthContextTest.java b/core/src/test/java/com/adobe/aio/auth/OAuthContextTest.java
index 778a3762..c75b388d 100644
--- a/core/src/test/java/com/adobe/aio/auth/OAuthContextTest.java
+++ b/core/src/test/java/com/adobe/aio/auth/OAuthContextTest.java
@@ -8,28 +8,8 @@
public class OAuthContextTest {
- private static final String TEST_PROPERTIES = "workspace.properties";
private static final String TEST_VALUE = "_changeMe";
- private static OAuthContext expected;
-
- @BeforeAll
- public static void beforeClass() throws Exception {
- expected = OAuthContext.builder().propertiesPath(TEST_PROPERTIES).build();
- }
-
- @Test
- void properties() {
- OAuthContext actual = OAuthContext.builder()
- .clientSecret(CLIENT_SECRET + TEST_VALUE)
- .addScope(SCOPES + TEST_VALUE)
- .build();
- assertEquals(actual, expected);
- assertEquals(actual.hashCode(), expected.hashCode());
- assertEquals(actual.toString(), expected.toString());
- actual.validate();
- }
-
@Test
void missingClientSecret() {
OAuthContext actual = OAuthContext.builder().build();
diff --git a/core/src/test/java/com/adobe/aio/util/FileUtilTest.java b/core/src/test/java/com/adobe/aio/util/FileUtilTest.java
index f4bd618d..0f42096d 100644
--- a/core/src/test/java/com/adobe/aio/util/FileUtilTest.java
+++ b/core/src/test/java/com/adobe/aio/util/FileUtilTest.java
@@ -15,6 +15,7 @@
import java.util.Map;
import java.util.Properties;
+import com.adobe.aio.exception.AIOException;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@@ -23,30 +24,37 @@ public class FileUtilTest {
private static final String KEY = "key";
private static final String VALUE = "value";
- private static final String TEST_PROPERTIES_FILE = "test.properties";
+ private static final String TEST_PROPERTIES_CLASS_PATH = "test.properties";
private Properties getTestProperties() {
Properties properties = new Properties();
properties.put(KEY, VALUE);
return properties;
}
+ @Test
+ public void testGetMapFromMissingPropertiesClassPath() {
+ Map map = new HashMap<>();
+ map.put(KEY, VALUE);
+ assertThrows(IllegalArgumentException.class, () -> FileUtil.getMap("missing.properties"));
+ }
@Test
- public void testGetMapFromProperties() {
+ public void testGetMapFromPropertiesClassPath() {
Map map = new HashMap<>();
map.put(KEY, VALUE);
- assertEquals(map, FileUtil.getMapFromProperties(getTestProperties()));
+ assertEquals(map, FileUtil.getMap(TEST_PROPERTIES_CLASS_PATH));
}
@Test
- public void testReadPropertiesFromFile() {
- assertFalse(FileUtil.readPropertiesFromFile("").isPresent());
- assertFalse(FileUtil.readPropertiesFromFile(null).isPresent());
+ public void testGetMapFromProperties() {
+ Map map = new HashMap<>();
+ map.put(KEY, VALUE);
+ assertEquals(map, FileUtil.getMap(getTestProperties()));
}
@Test
public void testReadPropertiesFromClassPath() {
- assertEquals(getTestProperties(), FileUtil.readPropertiesFromClassPath(TEST_PROPERTIES_FILE));
+ assertEquals(getTestProperties(), FileUtil.getProperties(TEST_PROPERTIES_CLASS_PATH));
}
}
diff --git a/core/src/test/java/com/adobe/aio/workspace/WorkspaceTest.java b/core/src/test/java/com/adobe/aio/workspace/WorkspaceTest.java
index 1661f6f7..a8295792 100644
--- a/core/src/test/java/com/adobe/aio/workspace/WorkspaceTest.java
+++ b/core/src/test/java/com/adobe/aio/workspace/WorkspaceTest.java
@@ -17,7 +17,6 @@
import java.security.PrivateKey;
import com.adobe.aio.auth.Context;
-import com.adobe.aio.auth.JwtContext;
import com.adobe.aio.util.Constants;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -26,8 +25,6 @@
public class WorkspaceTest {
- private static Workspace expected;
- private static final String TEST_PROPERTIES = "workspace.properties";
private static final String TEST_VALUE = "_changeMe";
private static PrivateKey privateKey;
@@ -37,11 +34,10 @@ public static void beforeClass() throws Exception {
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate();
- expected = Workspace.builder().propertiesPath(TEST_PROPERTIES).privateKey(privateKey).build();
}
@Test
- public void properties() throws IOException {
+ public void successFullBuilder() throws IOException {
class MockContext implements Context {
@Override
@@ -51,7 +47,7 @@ public void validate() {
}
Workspace actual = Workspace.builder()
- .imsUrl(Constants.IMS_URL)
+ .imsUrl(Constants.PROD_IMS_URL)
.imsOrgId(Workspace.IMS_ORG_ID + TEST_VALUE)
.apiKey(Workspace.API_KEY + TEST_VALUE)
.consumerOrgId(Workspace.CONSUMER_ORG_ID + TEST_VALUE)
@@ -65,8 +61,8 @@ public void validate() {
assertEquals(Workspace.CONSUMER_ORG_ID + TEST_VALUE, actual.getConsumerOrgId());
assertEquals(Workspace.PROJECT_ID + TEST_VALUE, actual.getProjectId());
assertEquals(Workspace.WORKSPACE_ID + TEST_VALUE, actual.getWorkspaceId());
- assertEquals(Constants.IMS_URL, actual.getImsUrl());
- actual.validateAll();
+ assertEquals(Constants.PROD_IMS_URL, actual.getImsUrl());
+ actual.validateWorkspaceContext();
}
@Test
@@ -128,24 +124,4 @@ public void projectUrl() {
assertEquals("https://developer.adobe.com/console/projects/aio_consumer_org_id_changeMe/aio_project_id_changeMe/overview", actual.getProjectUrl());
}
- @Test
- public void jwtBackwardsCompat() throws Exception {
- Workspace actual = Workspace.builder()
- .imsUrl(Constants.IMS_URL)
- .imsOrgId(Workspace.IMS_ORG_ID + TEST_VALUE)
- .apiKey(Workspace.API_KEY + TEST_VALUE)
- .consumerOrgId(Workspace.CONSUMER_ORG_ID + TEST_VALUE)
- .projectId(Workspace.PROJECT_ID + TEST_VALUE)
- .workspaceId(Workspace.WORKSPACE_ID + TEST_VALUE)
- .clientSecret(JwtContext.CLIENT_SECRET + TEST_VALUE)
- .credentialId(JwtContext.CREDENTIAL_ID + TEST_VALUE)
- .technicalAccountId(JwtContext.TECHNICAL_ACCOUNT_ID + TEST_VALUE)
- .privateKey(privateKey)
- .addMetascope(JwtContext.META_SCOPES + TEST_VALUE)
- .build();
- assertEquals(actual, expected);
- assertEquals(actual.hashCode(), expected.hashCode());
- assertEquals(actual.toString(), expected.toString());
- actual.validateAll();
- }
}
diff --git a/core/src/test/resources/workspace.properties b/core/src/test/resources/workspace.jwt.properties
similarity index 85%
rename from core/src/test/resources/workspace.properties
rename to core/src/test/resources/workspace.jwt.properties
index bd16d06d..27eee20f 100644
--- a/core/src/test/resources/workspace.properties
+++ b/core/src/test/resources/workspace.jwt.properties
@@ -18,20 +18,18 @@ aio_consumer_org_id=aio_consumer_org_id_changeMe
aio_ims_org_id=aio_ims_org_id_changeMe
# aio_workspace_id = your Adobe Developer Console workspace Id (project.workspace.id)
aio_workspace_id=aio_workspace_id_changeMe
-# aio_credential_id = your Adobe Developer Console jwt credential id (project.workspace.details.credentials[i].id)
+# aio_credential_id = your Adobe Developer Console credential id (project.workspace.details.credentials[i].id)
aio_credential_id=aio_credential_id_changeMe
-# aio_client_secret = your Adobe Developer Console jwt or OAuth credential client secret (project.workspace.details.credentials[i].jwt.client_secret)
-aio_client_secret=aio_client_secret_changeMe
+
# aio_api_key = your Adobe Developer Console jwt credential API Key (or Client ID) (project.workspace.details.credentials[i].jwt.client_id
aio_api_key=aio_api_key_changeMe
+# aio_client_secret = your Adobe Developer Console jwt or OAuth credential client secret (project.workspace.details.credentials[i].jwt.client_secret)
+aio_client_secret=aio_client_secret_changeMe
# aio_meta_scopes : comma separated list of metascopes associated with your API, see your Adobe Developer Console jwt credential metascopes (project.workspace.details.credentials[i].jwt.meta_scopes)
# sample aio_meta_scopes: /s/ent_user_sdk,/s/ent_marketing_sdk,/s/creative_sdk (project.workspace.details.credentials[i].jwt.meta_scopes)
aio_meta_scopes=aio_meta_scopes_changeMe
# aio_technical_account_id = your Adobe Developer Console jwt credential technical account id (project.workspace.details.credentials[i].jwt.technical_account_id)
aio_technical_account_id=aio_technical_account_id_changeMe
-# aio_oauth_scopes : comma separated list of scopes associated with your API, see your Adobe Developer Console OAuth credential scopes
-# sample aio_meta_scopes: openid, AdobeID, read_organizations
-aio_oauth_scopes=aio_oauth_scopes_changeMe
diff --git a/core/src/test/resources/workspace.oauth.properties b/core/src/test/resources/workspace.oauth.properties
new file mode 100644
index 00000000..f847f386
--- /dev/null
+++ b/core/src/test/resources/workspace.oauth.properties
@@ -0,0 +1,32 @@
+#
+# Copyright 2017 Adobe. All rights reserved.
+# This file is licensed 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 REPRESENTATIONS
+# OF ANY KIND, either express or implied. See the License for the specific language
+# governing permissions and limitations under the License.
+#
+
+# aio_project_id = your Adobe Developer Console project id (project.id)
+aio_project_id=aio_project_id_changeMe
+# aio_consumer_org_id = your Adobe Developer Console consumer orgnaization id (project.org.id)
+aio_consumer_org_id=aio_consumer_org_id_changeMe
+# aio_ims_org_id = your Adobe Developer Console IMS Organization ID (project.org.ims_org_id)
+aio_ims_org_id=aio_ims_org_id_changeMe
+# aio_workspace_id = your Adobe Developer Console workspace Id (project.workspace.id)
+aio_workspace_id=aio_workspace_id_changeMe
+# aio_credential_id = your Adobe Developer Console credential id (project.workspace.details.credentials[i].id)
+aio_credential_id=aio_credential_id_changeMe
+
+# aio_api_key = your Adobe Developer Console credential API Key (or Client ID) (project.workspace.details.credentials[i].oauth_server_to_server.client_id)
+aio_api_key=aio_api_key_changeMe
+# aio_client_secret = your Adobe Developer Console jwt credential client secret (project.workspace.details.credentials[i].oauth_server_to_server.client_secrets[0])
+aio_client_secret=aio_client_secret_changeMe
+# aio_oauth_scopes : comma separated list of oauth associated with your API, see your Adobe Developer Console oauth scopes (project.workspace.details.credentials[i].oauth_server_to_server.scopes)
+# sample aio_oauth_scopes: aio_oauth_scopes= AdobeID,openid,read_organizations,additional_info.projectedProductContext,additional_info.roles,adobeio_api,read_client_secret,manage_client_secrets
+aio_oauth_scopes=aio_oauth_scopes_changeMe
+
+
diff --git a/events_ingress/pom.xml b/events_ingress/pom.xml
index de7382b7..ca2e0031 100644
--- a/events_ingress/pom.xml
+++ b/events_ingress/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/events_ingress/src/test/resources/workspace.properties b/events_ingress/src/test/resources/workspace.properties
deleted file mode 100644
index bc5b692e..00000000
--- a/events_ingress/src/test/resources/workspace.properties
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright 2017 Adobe. All rights reserved.
-# This file is licensed 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 REPRESENTATIONS
-# OF ANY KIND, either express or implied. See the License for the specific language
-# governing permissions and limitations under the License.
-#
-
-# aio_meta_scopes : comma separated list of metascopes associated with your API
-# sample aio_meta_scopes: /s/ent_user_sdk,/s/ent_marketing_sdk,/s/creative_sdk
-aio_meta_scopes=aio_meta_scopes_changeMe
-# aio_ims_org_id = your IMS Organization ID as shown in your Adobe Developer Console workspace
-aio_ims_org_id=aio_ims_org_id_changeMe
-# aio_consumer_org_id = your consumer Org Id as shown in your Adobe Developer Console workspace (project.org.id)
-aio_consumer_org_id=aio_consumer_org_id_changeMe
-# aio_project_id = your project Id as shown in your Adobe Developer Console workspace (project.id)
-aio_project_id=aio_project_id_changeMe
-# aio_workspace_id = your workspace Id as shown in your Adobe Developer Console workspace (project.workspace.id)
-aio_workspace_id=aio_workspace_id_changeMe
-# aio_api_key = your credential API Key (Client ID) as shown in in your Adobe Developer Console workspace
-aio_api_key=aio_api_key_changeMe
-# aio_credential_id = your credential id as shown in your Adobe Developer Console workspace
-aio_credential_id=aio_credential_id_changeMe
-# aio_client_secret = your credential Client secret as shown in in your Adobe Developer Console workspace
-aio_client_secret=aio_client_secret_changeMe
-# aio_technical_account_id = your credential Technical account ID as shown in your Adobe Developer Console workspace
-aio_technical_account_id=aio_technical_account_id_changeMe
-
-# You then have 3 options to configure the privateKey (associated with the public key set in your Adobe Developer Console workspace):
-# * Option 1: use a pcks8 file
-# * Option 2: use base 64 encoded pcks8 key
-# * Option 3: use a keystore
-aio_encoded_pkcs8=aio_encoded_pkcs8_changeMe
-
-######################################
-# Management API test drive properties
-######################################
-aio_provider_id=aio_provider_id_changeMe
-aio_event_code=aio_event_code_changeMe
-
-
diff --git a/events_journal/pom.xml b/events_journal/pom.xml
index 9f8b0879..538ec5e9 100644
--- a/events_journal/pom.xml
+++ b/events_journal/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/events_journal/src/main/java/com/adobe/aio/event/journal/feign/FeignJournalService.java b/events_journal/src/main/java/com/adobe/aio/event/journal/feign/FeignJournalService.java
index 3de112e1..1e868b2a 100644
--- a/events_journal/src/main/java/com/adobe/aio/event/journal/feign/FeignJournalService.java
+++ b/events_journal/src/main/java/com/adobe/aio/event/journal/feign/FeignJournalService.java
@@ -36,7 +36,7 @@ public class FeignJournalService implements JournalService {
public FeignJournalService(final Workspace workspace, final String journalUrl) {
if (StringUtils.isEmpty(journalUrl)) {
throw new IllegalArgumentException(
- "JournalService is missing aj ournalUrl");
+ "JournalService is missing a journalUrl");
}
if (workspace == null) {
throw new IllegalArgumentException("RegistrationService is missing a workspace context");
diff --git a/events_journal/src/test/resources/workspace.properties b/events_journal/src/test/resources/workspace.properties
deleted file mode 100644
index 896fb845..00000000
--- a/events_journal/src/test/resources/workspace.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright 2017 Adobe. All rights reserved.
-# This file is licensed 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 REPRESENTATIONS
-# OF ANY KIND, either express or implied. See the License for the specific language
-# governing permissions and limitations under the License.
-#
-
-aio_meta_scopes=aio_meta_scopes_changeMe
-# ims_org_id = your IMS Organization ID as shown in your Adobe Developer Console workspace
-aio_ims_org_id=aio_ims_org_id_changeMe
-# consumer_org_id = your consumer Org Id as shown in your Adobe Developer Console workspace
-aio_consumer_org_id=aio_consumer_org_id_changeMe
-# api_key = your credential API Key (Client ID) as shown in in your Adobe Developer Console workspace
-aio_api_key=aio_api_key_changeMe
-# credential_id = your credential id as shown in your Adobe Developer Console workspace
-aio_credential_id=aio_credential_id_changeMe
-# client_secret = your credential Client secret as shown in in your Adobe Developer Console workspace
-aio_client_secret=aio_client_secret_changeMe
-# technical_account_id = your credential Technical account ID as shown in your Adobe Developer Console workspace
-aio_technical_account_id=aio_technical_account_id_changeMe
-# You then have 3 options to configure the privateKey (associated with the public key set in your Adobe Developer Console workspace):
-# * Option 1: use a pcks8 file (using the `pkcs8_file_path` config)
-# * Option 2: use base 64 encoded pcks8 key (using the `encoded_pkcs8` config)
-# * Option 3: use a keystore (using the `pkcs12_file_path`, `pkcs12_alias` and `pkcs12_password` config)
-aio_encoded_pkcs8=changeMe
-######################################
-# test drive properties
-######################################
-aio_journal_url=changeMe
-
-
diff --git a/events_mgmt/pom.xml b/events_mgmt/pom.xml
index 54d5d569..85a71fd6 100644
--- a/events_mgmt/pom.xml
+++ b/events_mgmt/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/events_mgmt/src/test/resources/workspace.properties b/events_mgmt/src/test/resources/workspace.properties
deleted file mode 100644
index bc5b692e..00000000
--- a/events_mgmt/src/test/resources/workspace.properties
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright 2017 Adobe. All rights reserved.
-# This file is licensed 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 REPRESENTATIONS
-# OF ANY KIND, either express or implied. See the License for the specific language
-# governing permissions and limitations under the License.
-#
-
-# aio_meta_scopes : comma separated list of metascopes associated with your API
-# sample aio_meta_scopes: /s/ent_user_sdk,/s/ent_marketing_sdk,/s/creative_sdk
-aio_meta_scopes=aio_meta_scopes_changeMe
-# aio_ims_org_id = your IMS Organization ID as shown in your Adobe Developer Console workspace
-aio_ims_org_id=aio_ims_org_id_changeMe
-# aio_consumer_org_id = your consumer Org Id as shown in your Adobe Developer Console workspace (project.org.id)
-aio_consumer_org_id=aio_consumer_org_id_changeMe
-# aio_project_id = your project Id as shown in your Adobe Developer Console workspace (project.id)
-aio_project_id=aio_project_id_changeMe
-# aio_workspace_id = your workspace Id as shown in your Adobe Developer Console workspace (project.workspace.id)
-aio_workspace_id=aio_workspace_id_changeMe
-# aio_api_key = your credential API Key (Client ID) as shown in in your Adobe Developer Console workspace
-aio_api_key=aio_api_key_changeMe
-# aio_credential_id = your credential id as shown in your Adobe Developer Console workspace
-aio_credential_id=aio_credential_id_changeMe
-# aio_client_secret = your credential Client secret as shown in in your Adobe Developer Console workspace
-aio_client_secret=aio_client_secret_changeMe
-# aio_technical_account_id = your credential Technical account ID as shown in your Adobe Developer Console workspace
-aio_technical_account_id=aio_technical_account_id_changeMe
-
-# You then have 3 options to configure the privateKey (associated with the public key set in your Adobe Developer Console workspace):
-# * Option 1: use a pcks8 file
-# * Option 2: use base 64 encoded pcks8 key
-# * Option 3: use a keystore
-aio_encoded_pkcs8=aio_encoded_pkcs8_changeMe
-
-######################################
-# Management API test drive properties
-######################################
-aio_provider_id=aio_provider_id_changeMe
-aio_event_code=aio_event_code_changeMe
-
-
diff --git a/events_test/pom.xml b/events_test/pom.xml
index 84b1769e..1df5f674 100644
--- a/events_test/pom.xml
+++ b/events_test/pom.xml
@@ -16,7 +16,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/events_test/src/main/java/com/adobe/aio/event/journal/JournalServiceTester.java b/events_test/src/main/java/com/adobe/aio/event/journal/JournalServiceTester.java
index f6982491..fa0cec27 100644
--- a/events_test/src/main/java/com/adobe/aio/event/journal/JournalServiceTester.java
+++ b/events_test/src/main/java/com/adobe/aio/event/journal/JournalServiceTester.java
@@ -17,9 +17,8 @@
import com.adobe.aio.event.journal.model.JournalEntry;
import com.adobe.aio.util.WorkspaceUtil;
import com.adobe.aio.workspace.Workspace;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+
+import java.util.*;
import java.util.function.BiPredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,16 +48,63 @@ public JournalServiceTester() {
workspace = WorkspaceUtil.getSystemWorkspaceBuilder().build();
}
+ /**
+ *
+ * @param journalUrl
+ * @return the latest journal entry, we do retry the journaling API, up to pollingTimeOutInMs,
+ * if it fails (due to temporary failure, or cache propagation latencies).
+ */
+ public JournalEntry getLatestEntry(String journalUrl) {
+ long pollingDuration = 0;
+ long sleeptime = 2000L;
+ JournalEntry entry = null;
+ while (pollingDuration < JOURNAL_POLLING_TIME_OUT_IN_MILLISECONDS && entry == null)
+ {
+ JournalService journalService =
+ JournalService.builder().workspace(workspace).url(journalUrl).build();
+ entry = journalService.getLatest();
+ if (entry == null) {
+ logger.warn("Latest Journal entry is null... retrying in 2 seconds... ");
+ pollingDuration += sleeptime;
+ try {
+ Thread.sleep(sleeptime);
+ } catch (InterruptedException e) {
+ logger.error("Interrupted while sleeping", e);
+ }
+ } else {
+ entry = journalService.get(entry.getNextLink());
+ }
+ }
+
+ if (entry == null) {
+ logger.error("We polled the journal for " + JOURNAL_POLLING_TIME_OUT_IN_MILLISECONDS + " milliseconds and could NOT GET the latest Journal Entry.");
+ throw new RuntimeException("We polled the journal for " + JOURNAL_POLLING_TIME_OUT_IN_MILLISECONDS + " milliseconds and could NOT GET the latest Journal Entry.");
+ } else {
+ logger.info("Successfully polled the latest Journal Entry before publishing a new test event...");
+ }
+ return entry;
+ }
+
public boolean pollJournalForEvent(String journalUrl, String eventId,
+ BiPredicate isEventIdInEvent)
+ throws InterruptedException {
+ JournalService journalService = JournalService.builder()
+ .workspace(workspace)
+ .url(journalUrl)
+ .build();
+ JournalEntry entry = journalService.getOldest();
+ return pollJournalForEvent(journalUrl, entry, eventId, isEventIdInEvent);
+ }
+
+
+ public boolean pollJournalForEvent(String journalUrl, JournalEntry fromEntry, String eventId,
BiPredicate isEventIdInEvent)
throws InterruptedException {
- JournalService journalService = JournalService.builder()
- .workspace(workspace)
- .url(journalUrl)
- .build();
+ JournalService journalService =
+ JournalService.builder().workspace(workspace).url(journalUrl).build();
long pollingDuration = 0;
- JournalEntry entry = journalService.getOldest();
+ JournalEntry entry = fromEntry;
while (!isEventIdInJournalEntry(entry, eventId, isEventIdInEvent)) {
if (entry.isEmpty()) {
logger.info("Empty journal entry, we will retry-after {} seconds.",
diff --git a/events_test/src/test/java/com/adobe/aio/event/journal/JournalServiceIntegrationTest.java b/events_test/src/test/java/com/adobe/aio/event/journal/JournalServiceIntegrationTest.java
index 221a8ba4..5ca711d5 100644
--- a/events_test/src/test/java/com/adobe/aio/event/journal/JournalServiceIntegrationTest.java
+++ b/events_test/src/test/java/com/adobe/aio/event/journal/JournalServiceIntegrationTest.java
@@ -17,6 +17,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.adobe.aio.event.journal.model.JournalEntry;
import com.adobe.aio.event.management.ProviderServiceIntegrationTest;
import com.adobe.aio.event.management.ProviderServiceTester;
import com.adobe.aio.event.management.RegistrationServiceTester;
@@ -37,6 +38,7 @@ public JournalServiceIntegrationTest() {
providerServiceTester = new ProviderServiceTester();
registrationServiceTester = new RegistrationServiceTester();
publishServiceTester = new PublishServiceTester();
+
}
@Test
@@ -70,12 +72,15 @@ public void testJournalPolling()
TEST_REGISTRATION_NAME, providerId, TEST_EVENT_CODE);
registrationId = registration.getRegistrationId();
+ JournalEntry fromEntry = getLatestEntry(registration.getJournalUrl().getHref());
+ logger.info("polled latest Journal Entry before publishing a new test event...");
+
String cloudEventId = publishServiceTester.publishCloudEvent(false, providerId, TEST_EVENT_CODE);
boolean wasCloudEventPolled = pollJournalForEvent(
- registration.getJournalUrl().getHref(), cloudEventId, isEventIdTheCloudEventId);
+ registration.getJournalUrl().getHref(), fromEntry, cloudEventId, isEventIdTheCloudEventId);
String rawEventId = publishServiceTester.publishRawEvent(providerId, TEST_EVENT_CODE);
- boolean wasRawEventPolled = pollJournalForEvent(registration.getJournalUrl().getHref(), rawEventId,
+ boolean wasRawEventPolled = pollJournalForEvent(registration.getJournalUrl().getHref(), fromEntry, rawEventId,
isEventIdInTheCloudEventData);
assertTrue(wasCloudEventPolled, "The published CloudEvent was not retrieved in the Journal");
diff --git a/events_test/src/test/resources/workspace.properties b/events_test/src/test/resources/workspace.properties
deleted file mode 100644
index 671ddcaf..00000000
--- a/events_test/src/test/resources/workspace.properties
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright 2017 Adobe. All rights reserved.
-# This file is licensed 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 REPRESENTATIONS
-# OF ANY KIND, either express or implied. See the License for the specific language
-# governing permissions and limitations under the License.
-#
-
-aio_meta_scopes=aio_meta_scopes_changeMe
-# ims_org_id = your IMS Organization ID as shown in your Adobe Developer Console workspace
-aio_ims_org_id=aio_ims_org_id_changeMe
-# consumer_org_id = your consumer Org Id as shown in your Adobe Developer Console workspace
-aio_consumer_org_id=aio_consumer_org_id_changeMe
-# api_key = your credential API Key (Client ID) as shown in in your Adobe Developer Console workspace
-aio_api_key=aio_api_key_changeMe
-# credential_id = your credential id as shown in your Adobe Developer Console workspace
-aio_credential_id=aio_credential_id_changeMe
-# client_secret = your credential Client secret as shown in in your Adobe Developer Console workspace
-aio_client_secret=aio_client_secret_changeMe
-# technical_account_id = your credential Technical account ID as shown in your Adobe Developer Console workspace
-aio_technical_account_id=aio_technical_account_id_changeMe
-# You then have 3 options to configure the privateKey (associated with the public key set in your Adobe Developer Console workspace):
-# * Option 1: use a pcks8 file (using the `pkcs8_file_path` config)
-# * Option 2: use base 64 encoded pcks8 key (using the `encoded_pkcs8` config)
-# * Option 3: use a keystore (using the `pkcs12_file_path`, `pkcs12_alias` and `pkcs12_password` config)
-aio_encoded_pkcs8=changeMe
-
-######################################
-# I/O Events url
-######################################
-#aio_api_url=https://api.adobe.io
-#aio_publish_url=https://eventsingress.adobe.io
-
-
-
diff --git a/events_webhook/pom.xml b/events_webhook/pom.xml
index 18256a85..c163b403 100644
--- a/events_webhook/pom.xml
+++ b/events_webhook/pom.xml
@@ -16,7 +16,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/events_xdm/pom.xml b/events_xdm/pom.xml
index adb40dde..ac52923a 100644
--- a/events_xdm/pom.xml
+++ b/events_xdm/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/ims/README.md b/ims/README.md
index 032def58..78c48066 100644
--- a/ims/README.md
+++ b/ims/README.md
@@ -1,111 +1,80 @@
# `aio-lib-java-ims`
-`aio-lib-java-ims` is an Adobe I/O - Java SDK - IMS Library.
-This Java library wraps http API endpoints exposed by
-[Adobe Identity Management System (IMS)](https://developer.adobe.com/developer-console/docs/guides/#!AdobeDocs/adobeio-auth/master/AuthenticationOverview/ServiceAccountIntegration.md)
+`aio-lib-java-ims` is the Adobe I/O - Java SDK - IMS Library.
-## Service Account Integration (JWT authentication flow)
+* wrapping http API endpoints exposed by [Adobe Identity Management System (IMS)](https://developer.adobe.com/developer-console/docs/guides/#!AdobeDocs/adobeio-auth/master/AuthenticationOverview/ServiceAccountIntegration.md)
+* providing an Authentication [Open Feign RequestInterceptor](https://github.com/OpenFeign/feign#request-interceptors) that can be leveraged to transparently add the authentication headers expected by many Adobe APIs, it will add
+ * an `Authorization` header with a `Bearer` access token
+ * renewing it only when expired or when not present in memory yet
+ * a `x-api-key` header matching your token
-A Service Account connection allows your application to call Adobe services on behalf of
-the application itself or on behalf of an enterprise organization.
-
-For this type of connection, you will create a JSON Web Token (JWT) that encapsulates
-your credentials and begin each API session by exchanging the JWT for an access token.
-
-The JWT encodes all of the identity and security information required to obtain an access
-token and must be signed with the private key that is associated with a public key certificate specified on your integration.
-
-Browse our [JWT authentication documentation](https://developer.adobe.com/developer-console/docs/guides/authentication/JWT/)
-for more details.
-
-This Java library will help you implement this JWT exchange token flow, to get a valid access token
-and start interacting with the many Adobe I/O API that support such authentication.
+## Test Drive
-### Configurations
-
-This library fluent workspace builder API offers many ways to have your `Workspace` (a Java POJO representation of your `Adobe Developer Console` Workspace) configured.
-
-To get you started quickly you could use a `.properties` file,
-see our [sample config file](./src/test/resources/workspace.properties)
-
-#### Create and configure your public and private key
-
-As introduced above the authentication flow signs the JWT request and therefore requires private-public keys configurations
-, therefore you will need to
-
-* First, create this RSA private/public certificate pair, using openssl:
-
- `openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt`
+It only takes a few lines of code:
-* Then, upload the public key in your Adobe Developer Workspace, see our [JWT authentication documentation](https://developer.adobe.com/developer-console/docs/guides/authentication/JWT/)
-* Finally, configure this library (and its [`PrivateKeyBuilder`](./src/main/java/com/adobe/util/PrivateKeyBuilder.java)) with your privateKey, you may either
- * use a pcks8 file
- * use a base 64 encoded pcks8 key
- * use a keystore file
+ Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().build(); // [1]
+ ImsService imsService = ImsService.builder().workspace(workspace).build(); // [2]
+ logger.info("accessToken: {}", imsService.getAccessToken()); // [3]
-##### Option 1: Use a pcks8 file
+ // [1] build your `Workspace` (a Java POJO representation of your `Adobe Developer Console` Workspace)
+ // looking up other System Environment variables.
+ // Note that our fluent workspace and private Key builders offers many ways to have your workspace configured,
+ // we are showing here the most concise
+ // [2] build the Ims Service wrapper and have it use this workspace context
+ // [3] use this service to retrieve an OAuth access token
-First, convert your private key to a PKCS8 format, use the following command:
+ // here is one way you can build the related Adobe IMS Auth Interceptor
+ RequestInterceptor authInterceptor = AuthInterceptor.builder().workspace(workspace).build();
- openssl pkcs8 -topk8 -inform PEM -outform DER -in private.key -nocrypt > private.pkcs8.key
-
-Then, set your workspace `aio_pkcs8_file_path` properties
-to match the `private.pkcs8.key` file path (you generated using the previous command)
-
-
-##### Option 2: use a base 64 encoded pcks8 key
-
-First, convert your private key to a PKCS8 format, use the following command:
-
- openssl pkcs8 -topk8 -inform PEM -outform DER -in private.key -nocrypt > private.pkcs8.key
-
-Then, base 64 encode it, use the following command:
-
- base64 private.pkcs8.key
+Have a look at our [ImsService `main()` Test Drive](./src/test/java/com/adobe/aio/ims/ImsServiceTestDrive.java)
-Finally, set your workspace `aio_encoded_pkcs8` properties value using the string you generated with the above command
-##### Option 3: use a keystore
+## Configurations
-First, use the following commands to set the alias (as `myalias` here) and a non-empty keystore password.
+Note that this library is built on top of `aio-lib-java-core` which holds a fluent workspace builder API that offers many ways to build your `Workspace` (a Java POJO representation of your `Adobe Developer Console` Workspace).
+See more details on the [Workspace](../aio-lib-java-core/README.md#Workspace) configurations in the `aio-lib-java-core` [README](../core/README.md#Workspace)
- cat private.key certificate_pub.crt > private-key-crt
- openssl pkcs12 -export -in private-key-crt -out keystore.p12 -name myalias -noiter -nomaciter
+It allows you to integrate with the two server to server authentication credentials that Adobe supports.
+* OAuth Server-to-Server credentials
+* Service Account (JWT) credentials (deprecated)
-Then fill the associated `aio_pkcs12_file_path`, `aio_pkcs12_alias` and `aio_pkcs12_password` workspace properties.
+These credentials only differ in the way your application generates the access token, the rest of their functioning is similar.
+### OAuth Server-to-Server credentials Configurations
+The OAuth Server-to-Server credential relies on the OAuth 2.0 `client_credentials` grant type to generate access tokens.
+To generate an access token, your application can make a single HTTP request with your `client_id` and `client_secret` and `scopes`.
-### Our reusable `OpenFeign` JWT (exchange token flow) Authentication `RequestInterceptor`
+Browse our [OAuth authentication documentation](https://developer.adobe.com/developer-console/docs/guides/authentication/ServerToServerAuthentication/#oauth-server-to-server-credential) for more details,
+and to get you started quickly, have a look at our [sample oauth config file: `workspace.oauth.properties`](./src/test/resources/workspace.oauth.properties)
-This lib also contains JWT (exchange token flow) Authentication `RequestInterceptor`: [JWTAuthInterceptor](src/main/java/com/adobe/aio/ims/api/JWTAuthInterceptor.java)
-It is a [Open Feign RequestInterceptor](https://github.com/OpenFeign/feign#request-interceptors).
-It can be leverage to add the authentication headers expected by many Adobe APIs, it will add
-* an `Authorization` header with a `Bearer` access token (generated from a JWT exchange flow)
- * renewing it only when expired (after 24 hours) or when not present in memory yet
-* a `x-api-key` header matching your JWT token
-### Test Drive
+### Service Account (JWT) credential (deprecated)
+A Service Account connection allows your application to call Adobe services on behalf of
+the application itself or on behalf of an enterprise organization.
- PrivateKey privateKey = new PrivateKeyBuilder().systemEnv().build(); // [1]
- Workspace workspace = Workspace.builder()
- .systemEnv()
- .privateKey(privateKey)
- .build(); // [2]
- ImsService imsService = ImsService.builder().workspace(workspace).build(); // [3]
+For this type of connection, you will create a JSON Web Token (JWT) that encapsulates
+your credentials and begin each API session by exchanging the JWT for an access token.
- AccessToken accessToken = imsService.getJwtExchangeAccessToken(); // [4]
+The JWT encodes all of the identity and security information required to obtain an access
+token and must be signed with the private key that is associated with a public key certificate specified on your integration.
- // [1] Build your PrivateKey looking up the key indicated by you System Environment variables
- // [2] build your `Workspace` (a Java POJO representation of your `Adobe Developer Console` Workspace)
- // looking up other System Environment variables.
- // Note that our fluent workspace and private Key builders offers many ways to have your workspace configured,
- // we are showing here the most concise
- // [3] build the Ims Service wrapper and have it use this workspace context
- // [4] use this service to retrieve an access token using a jwt exchange token flow
+Browse our [JWT authentication documentation](https://developer.adobe.com/developer-console/docs/guides/authentication/JWT/) for more details,
+and to get you started quickly, look at our [sample jwt config file: `workspace.jwt.properties`](./src/test/resources/workspace.jwt.properties)
+#### Create and configure your public and private key
+As introduced above the authentication flow signs the JWT request and therefore requires private-public keys configurations
+, therefore you will need to
-Have a look at our [ImsService `main()` Test Drive](./src/test/java/com/adobe/aio/ims/ImsServiceTestDrive.java)
+* create this RSA private/public certificate pair, using openssl:
+ `openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout private.key -out certificate_pub.crt`
+* upload the public key in your Adobe Developer Workspace, see our [JWT authentication documentation](https://developer.adobe.com/developer-console/docs/guides/authentication/JWT/)
+* configure this library (and its [`PrivateKeyBuilder`](./src/main/java/com/adobe/util/PrivateKeyBuilder.java)) with your privateKey using a base 64 encoded pcks8 key
+ * convert your private key to a PKCS8 format, use the following command:
+ `openssl pkcs8 -topk8 -inform PEM -outform DER -in private.key -nocrypt > private.pkcs8.key`
+ * base 64 encode it (and stuff it in a `private.pkcs8.key.base64` file), use the following command:
+ `base64 -i private.pkcs8.key -o private.pkcs8.key.base64`
+* set your workspace `aio_encoded_pkcs8` properties value using the string you generated with the above command
## Builds
diff --git a/ims/pom.xml b/ims/pom.xml
index 9988d48f..a6843e80 100644
--- a/ims/pom.xml
+++ b/ims/pom.xml
@@ -17,7 +17,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
../pom.xml
4.0.0
diff --git a/ims/src/main/java/com/adobe/aio/ims/ImsService.java b/ims/src/main/java/com/adobe/aio/ims/ImsService.java
index 954a17dd..58134b18 100644
--- a/ims/src/main/java/com/adobe/aio/ims/ImsService.java
+++ b/ims/src/main/java/com/adobe/aio/ims/ImsService.java
@@ -17,26 +17,23 @@
public interface ImsService {
- /**
- * Returns an {@link AccessToken} that can be used for other AIO API Calls.
- *
- * @deprecated this will be removed in v2.0
- * @return AccessToken a valid API authentication token
- */
- @Deprecated()
- AccessToken getJwtExchangeAccessToken();
/**
- * Checks that the access token is still valid.
+ * Checks that the jwt access token is still valid.
*
- * @deprecated this will be removed in v2.0
- * @param accessToken the token to check
+ * @deprecated this will be removed as JWT token exchange is deprecated
+ * @param jwtAccessToken the jwt token to check
* @return true if the provided access token is still valid, false otherwise
*/
@Deprecated()
- boolean validateAccessToken(String accessToken);
+ boolean validateJwtAccessToken(String jwtAccessToken);
- AccessToken getOAuthAccessToken();
+ /**
+ * Looking up the contextual Workspace, it will use
+ * either the OAuth or JWT authentication context to fetch a valid access token.
+ * @return AccessToken a valid API authentication token
+ */
+ AccessToken getAccessToken();
static Builder builder() {
return new Builder();
@@ -67,7 +64,10 @@ public Builder workspace(Workspace workspace) {
* @throws IllegalStateException if the Workspace authentication context is not valid.
*/
public ImsService build() throws IllegalStateException {
- this.workspace.getAuthContext().validate();
+ if (workspace == null) {
+ throw new IllegalStateException("Workspace is required to build ImsService");
+ }
+ workspace.validateAll();
return new FeignImsService(this.workspace);
}
}
diff --git a/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java b/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java
index b4eabe1c..11053c8e 100644
--- a/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java
+++ b/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java
@@ -53,7 +53,7 @@ public class JwtTokenBuilder {
private static final String AUD_SUFFIX = "/c/";
public JwtTokenBuilder(final Workspace workspace) {
- if (!(workspace.getAuthContext() instanceof JwtContext)) {
+ if (!workspace.isAuthJWT()) {
throw new IllegalStateException("AuthContext in workspace not of type `JwtContext`.");
}
diff --git a/ims/src/main/java/com/adobe/aio/ims/feign/AuthInterceptor.java b/ims/src/main/java/com/adobe/aio/ims/feign/AuthInterceptor.java
index 62826e35..3a86a44e 100644
--- a/ims/src/main/java/com/adobe/aio/ims/feign/AuthInterceptor.java
+++ b/ims/src/main/java/com/adobe/aio/ims/feign/AuthInterceptor.java
@@ -1,8 +1,5 @@
package com.adobe.aio.ims.feign;
-import com.adobe.aio.auth.Context;
-import com.adobe.aio.auth.JwtContext;
-import com.adobe.aio.auth.OAuthContext;
import com.adobe.aio.ims.ImsService;
import com.adobe.aio.ims.model.AccessToken;
import com.adobe.aio.workspace.Workspace;
@@ -11,14 +8,14 @@
import static com.adobe.aio.util.Constants.*;
-public abstract class AuthInterceptor implements RequestInterceptor {
+public class AuthInterceptor implements RequestInterceptor {
private volatile Long expirationTimeMillis;
private volatile AccessToken accessToken;
private final ImsService imsService;
- protected AuthInterceptor(final ImsService imsService) {
- this.imsService = imsService;
+ protected AuthInterceptor (final Workspace workspace) {
+ this.imsService = ImsService.builder().workspace(workspace).build();
}
@Override
@@ -30,7 +27,9 @@ ImsService getImsService() {
return this.imsService;
}
- abstract AccessToken fetchAccessToken();
+ AccessToken fetchAccessToken() {
+ return getImsService().getAccessToken();
+ }
synchronized String getAccessToken() {
if (expirationTimeMillis == null || System.currentTimeMillis() >= expirationTimeMillis) {
@@ -62,25 +61,18 @@ public static Builder builder() {
public static class Builder {
- private Context authContext;
- private ImsService imsService;
+ private Workspace workspace;
private Builder() {
}
public Builder workspace(Workspace workspace) {
- this.authContext = workspace.getAuthContext();
- this.imsService = ImsService.builder().workspace(workspace).build();
+ this.workspace = workspace;
return this;
}
public AuthInterceptor build() {
- if (authContext instanceof JwtContext) {
- return new JWTAuthInterceptor(imsService);
- } else if (authContext instanceof OAuthContext) {
- return new OAuthInterceptor(imsService);
- }
- throw new IllegalStateException("Unable to find interceptor for AuthContext");
+ return new AuthInterceptor(workspace);
}
}
diff --git a/ims/src/main/java/com/adobe/aio/ims/feign/FeignImsService.java b/ims/src/main/java/com/adobe/aio/ims/feign/FeignImsService.java
index c293194a..634adca9 100644
--- a/ims/src/main/java/com/adobe/aio/ims/feign/FeignImsService.java
+++ b/ims/src/main/java/com/adobe/aio/ims/feign/FeignImsService.java
@@ -23,9 +23,13 @@
import com.adobe.aio.ims.api.ImsApi;
import com.adobe.aio.ims.model.AccessToken;
import com.adobe.aio.util.feign.FeignUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class FeignImsService implements ImsService {
+ private Logger logger = LoggerFactory.getLogger(this.getClass());
+
public static final String ACCESS_TOKEN = "access_token";
private final ImsApi imsApi;
private final Workspace workspace;
@@ -36,11 +40,29 @@ public FeignImsService(final Workspace workspace) {
}
@Override
- public AccessToken getJwtExchangeAccessToken() {
- if (!(workspace.getAuthContext() instanceof JwtContext)) {
- throw new IllegalStateException("AuthContext in workspace not of type `JwtContext`.");
+ public AccessToken getAccessToken() {
+ if (workspace.isAuthJWT()) {
+ return getJwtExchangeAccessToken();
+ } else if (workspace.isAuthOAuth()) {
+ return getOAuthAccessToken();
+ } else {
+ throw new IllegalStateException("AuthContext in workspace not of type `OAuthContext` or `JwtContext`.");
}
+ }
+ @Override
+ public boolean validateJwtAccessToken(String jwtAccessToken) {
+ if (!workspace.isAuthJWT()) {
+ logger.error("AuthContext in workspace not of type `JwtContext`... this only validates JWT Token");
+ return false;
+ }
+ return imsApi.validateJwtToken(ACCESS_TOKEN, workspace.getApiKey(), jwtAccessToken).getValid();
+ }
+
+ private AccessToken getJwtExchangeAccessToken() {
+ if (!workspace.isAuthJWT()) {
+ throw new IllegalStateException("AuthContext in workspace not of type `JwtContext`.");
+ }
JwtContext context = (JwtContext) workspace.getAuthContext();
context.validate();
@@ -49,24 +71,14 @@ public AccessToken getJwtExchangeAccessToken() {
return imsApi.getJwtAccessToken(workspace.getApiKey(), context.getClientSecret(), token);
}
- @Override
- public boolean validateAccessToken(String accessToken) {
- if (!(workspace.getAuthContext() instanceof JwtContext)) {
- throw new IllegalStateException("AuthContext in workspace not of type `JwtContext`.");
- }
-
- return imsApi.validateJwtToken(ACCESS_TOKEN, workspace.getApiKey(), accessToken).getValid();
- }
-
- @Override
- public AccessToken getOAuthAccessToken() {
- if (!(workspace.getAuthContext() instanceof OAuthContext)) {
+ private AccessToken getOAuthAccessToken() {
+ if (!workspace.isAuthOAuth()) {
throw new IllegalStateException("AuthContext in workspace not of type `OAuthContext`.");
}
OAuthContext context = (OAuthContext) workspace.getAuthContext();
String scopes = context.getScopes().stream().filter(StringUtils::isNotBlank).map(String::trim).collect(Collectors.joining(","));
-
return imsApi.getOAuthAccessToken(workspace.getApiKey(), context.getClientSecret(), scopes);
}
+
}
diff --git a/ims/src/main/java/com/adobe/aio/ims/feign/JWTAuthInterceptor.java b/ims/src/main/java/com/adobe/aio/ims/feign/JWTAuthInterceptor.java
deleted file mode 100644
index ceecf3df..00000000
--- a/ims/src/main/java/com/adobe/aio/ims/feign/JWTAuthInterceptor.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2017 Adobe. All rights reserved.
- * This file is licensed 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 REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-package com.adobe.aio.ims.feign;
-
-import com.adobe.aio.ims.ImsService;
-import com.adobe.aio.ims.model.AccessToken;
-
-@Deprecated
-public class JWTAuthInterceptor extends AuthInterceptor {
-
- protected JWTAuthInterceptor(ImsService imsService) {
- super(imsService);
- }
-
- public boolean isUp() {
- return getImsService().validateAccessToken(this.getAccessToken());
- }
-
- AccessToken fetchAccessToken() {
- return getImsService().getJwtExchangeAccessToken();
- }
-}
diff --git a/ims/src/main/java/com/adobe/aio/ims/feign/OAuthInterceptor.java b/ims/src/main/java/com/adobe/aio/ims/feign/OAuthInterceptor.java
deleted file mode 100644
index beade471..00000000
--- a/ims/src/main/java/com/adobe/aio/ims/feign/OAuthInterceptor.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2017 Adobe. All rights reserved.
- * This file is licensed 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 REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-package com.adobe.aio.ims.feign;
-
-import com.adobe.aio.ims.ImsService;
-import com.adobe.aio.ims.model.AccessToken;
-
-public class OAuthInterceptor extends AuthInterceptor {
- protected OAuthInterceptor(ImsService imsService) {
- super(imsService);
- }
-
- @Override
- AccessToken fetchAccessToken() {
- return getImsService().getOAuthAccessToken();
- }
-}
diff --git a/ims/src/main/java/com/adobe/aio/ims/util/PrivateKeyBuilder.java b/ims/src/main/java/com/adobe/aio/ims/util/PrivateKeyBuilder.java
index ce28b32b..1cb70c2a 100644
--- a/ims/src/main/java/com/adobe/aio/ims/util/PrivateKeyBuilder.java
+++ b/ims/src/main/java/com/adobe/aio/ims/util/PrivateKeyBuilder.java
@@ -11,24 +11,14 @@
*/
package com.adobe.aio.ims.util;
-import static com.adobe.aio.util.FileUtil.getMapFromProperties;
-import static com.adobe.aio.util.FileUtil.readPropertiesFromClassPath;
-import static com.adobe.aio.util.FileUtil.readPropertiesFromFile;
-
-import java.io.IOException;
import java.security.PrivateKey;
import java.util.Map;
-import java.util.Properties;
+
import org.apache.commons.lang3.StringUtils;
public class PrivateKeyBuilder {
public static final String AIO_ENCODED_PKCS_8 = "aio_encoded_pkcs8";
- private static final String AIO_PKCS_8_FILE_PATH = "aio_pkcs8_file_path";
-
- private static final String AIO_PKCS_12_FILE_PATH = "aio_pkcs12_file_path";
- private static final String AIO_PKCS_12_PASSWORD = "aio_pkcs12_password";
- private static final String AIO_PKCS_12_ALIAS = "aio_pkcs12_alias";
private Map configMap;
private String encodedPkcs8Key;
@@ -36,26 +26,6 @@ public class PrivateKeyBuilder {
public PrivateKeyBuilder() {
}
- public PrivateKeyBuilder systemEnv() {
- this.configMap = System.getenv();
- return this;
- }
-
- /**
- * @param configPath: will first look on the file system, if not found, in the classpath
- * @return a PrivateKeyBuilder loaded with the provided config
- */
- public PrivateKeyBuilder configPath(String configPath) {
- this.configMap = getMapFromProperties(
- readPropertiesFromFile(configPath)
- .orElse(readPropertiesFromClassPath(configPath)));
- return this;
- }
-
- public PrivateKeyBuilder properties(Properties properties) {
- this.configMap = getMapFromProperties(properties);
- return this;
- }
public PrivateKeyBuilder encodedPkcs8Key(String encodedPkcs8Key) {
this.encodedPkcs8Key = encodedPkcs8Key;
@@ -72,30 +42,9 @@ public PrivateKey build() {
+ "" + e.getMessage(), e);
}
} else {
- return getPrivateKey(this.configMap);
+ return null;
}
}
- private static PrivateKey getPrivateKey(final Map imsConfig) {
- try {
- if (imsConfig.containsKey(AIO_ENCODED_PKCS_8)) {
- return KeyStoreUtil.getPrivateKeyFromEncodedPkcs8(imsConfig.get(AIO_ENCODED_PKCS_8));
- } else if (imsConfig.containsKey(AIO_PKCS_8_FILE_PATH)) {
- return KeyStoreUtil.getPrivateKeyFromPkcs8File(imsConfig.get(AIO_PKCS_8_FILE_PATH));
- } else if (imsConfig.containsKey(AIO_PKCS_12_FILE_PATH) && imsConfig.containsKey(
- AIO_PKCS_12_PASSWORD)
- && imsConfig.containsKey(AIO_PKCS_12_ALIAS)) {
- return KeyStoreUtil.getPrivateKeyFromPkcs12File(
- imsConfig.get(AIO_PKCS_12_FILE_PATH), imsConfig.get(AIO_PKCS_12_ALIAS),
- imsConfig.get(AIO_PKCS_12_PASSWORD));
- } else {
- throw new IllegalArgumentException(
- "AIO is missing a valid (pkcs8 or pkcs12) Private Key configuration");
- }
- } catch (Exception e) {
- throw new IllegalArgumentException(
- "AIO holds an invalid (pkcs8 or pkcs12) Private Key configuration. "
- + "" + e.getMessage(), e);
- }
- }
+
}
diff --git a/ims/src/main/java/com/adobe/aio/util/WorkspaceUtil.java b/ims/src/main/java/com/adobe/aio/util/WorkspaceUtil.java
index 7462525f..55cd68c9 100644
--- a/ims/src/main/java/com/adobe/aio/util/WorkspaceUtil.java
+++ b/ims/src/main/java/com/adobe/aio/util/WorkspaceUtil.java
@@ -11,115 +11,191 @@
*/
package com.adobe.aio.util;
+import com.adobe.aio.auth.Context;
+import com.adobe.aio.auth.JwtContext;
+import com.adobe.aio.auth.OAuthContext;
import com.adobe.aio.ims.util.PrivateKeyBuilder;
import com.adobe.aio.workspace.Workspace;
-import java.security.PrivateKey;
-import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.security.PrivateKey;
+import java.util.*;
+
+import static com.adobe.aio.auth.Context.CLIENT_SECRET;
+import static com.adobe.aio.auth.JwtContext.*;
+import static com.adobe.aio.auth.OAuthContext.SCOPES;
+import static com.adobe.aio.util.FileUtil.getMap;
+import static com.adobe.aio.workspace.Workspace.*;
+
public class WorkspaceUtil {
- public static final String API_URL = "aio_api_url";
- public static final String PUBLISH_URL = "aio_publish_url";
- public static final String DEFAULT_TEST_PROPERTIES = "workspace.secret.properties";
- private static final Logger logger = LoggerFactory.getLogger(WorkspaceUtil.class);
-
- private WorkspaceUtil() {
- }
-
- /**
- * Loads configurations for a Workspace from either one and only one of the following
- * sources, probing them first to check that all the required properties are given,
- * in order:
- *
- * - System Properties
- * - Environment Variables
- * - classpath:{@link WorkspaceUtil#DEFAULT_TEST_PROPERTIES}
- *
- * @return a Workspace.Builder loaded with the provided config
- */
- public static Workspace.Builder getSystemWorkspaceBuilder() {
- if (StringUtils.isNoneBlank(
- System.getProperty(PrivateKeyBuilder.AIO_ENCODED_PKCS_8),
- System.getProperty(Workspace.API_KEY),
- System.getProperty(Workspace.WORKSPACE_ID),
- System.getProperty(Workspace.CLIENT_SECRET),
- System.getProperty(Workspace.CONSUMER_ORG_ID),
- System.getProperty(Workspace.CREDENTIAL_ID),
- System.getProperty(Workspace.IMS_ORG_ID),
- System.getProperty(Workspace.META_SCOPES),
- System.getProperty(Workspace.PROJECT_ID),
- System.getProperty(Workspace.TECHNICAL_ACCOUNT_ID))) {
- logger.debug("loading test Workspace from JVM System Properties");
- PrivateKey privateKey = new PrivateKeyBuilder().encodedPkcs8Key(
- System.getProperty(PrivateKeyBuilder.AIO_ENCODED_PKCS_8)).build();
- return Workspace.builder()
- .properties(System.getProperties())
- .privateKey(privateKey);
- } else if (StringUtils.isNoneBlank(
- System.getenv(PrivateKeyBuilder.AIO_ENCODED_PKCS_8),
- System.getenv(Workspace.API_KEY),
- System.getenv(Workspace.WORKSPACE_ID),
- System.getenv(Workspace.CLIENT_SECRET),
- System.getenv(Workspace.CONSUMER_ORG_ID),
- System.getenv(Workspace.CREDENTIAL_ID),
- System.getenv(Workspace.IMS_ORG_ID),
- System.getenv(Workspace.META_SCOPES),
- System.getenv(Workspace.PROJECT_ID),
- System.getenv(Workspace.TECHNICAL_ACCOUNT_ID))) {
- logger.debug("loading test Workspace from JVM System Properties");
- PrivateKey privateKey =
- new PrivateKeyBuilder()
- .encodedPkcs8Key(System.getenv(PrivateKeyBuilder.AIO_ENCODED_PKCS_8))
- .build();
- return Workspace.builder().systemEnv().privateKey(privateKey);
- } else {
- /**
- * WARNING: don't push back your workspace secrets to github
- */
- logger.debug("loading test Workspace from classpath {}", DEFAULT_TEST_PROPERTIES);
- return getWorkspaceBuilder(DEFAULT_TEST_PROPERTIES);
+ public static final String API_URL = "aio_api_url";
+ public static final String PUBLISH_URL = "aio_publish_url";
+
+ /**
+ * Default workspace configuration file class path
+ * WARNING: don't push back this file to github as it contains many secrets.
+ * We do provide a sample properties files in the
+ * ./src/test/resources
folder
+ */
+ public static final String DEFAULT_TEST_PROPERTIES = "workspace.secret.properties";
+
+ private static final Logger logger = LoggerFactory.getLogger(WorkspaceUtil.class);
+
+ private WorkspaceUtil() {
+ }
+
+ /**
+ * Loads Workspace from either one and only one of the following
+ * sources, probing them first to check that all the required properties are given,
+ * in order:
+ *
+ * - System Properties
+ * - Environment Variables
+ * - classpath:{@link WorkspaceUtil#DEFAULT_TEST_PROPERTIES}
+ *
+ *
+ * @return a Workspace.Builder loaded with the provided config
+ */
+ public static Workspace.Builder getSystemWorkspaceBuilder() {
+ return getWorkspaceBuilder(getSystemWorkspaceConfig(DEFAULT_TEST_PROPERTIES));
+ }
+
+ public static Workspace.Builder getWorkspaceBuilder(Map configMap) {
+ Workspace.Builder builder =
+ Workspace.builder().imsUrl(configMap.get(IMS_URL))
+ .imsOrgId(configMap.get(IMS_ORG_ID))
+ .apiKey(configMap.get(API_KEY))
+ .consumerOrgId(configMap.get(CONSUMER_ORG_ID))
+ .projectId(configMap.get(PROJECT_ID))
+ .workspaceId(configMap.get(WORKSPACE_ID))
+ .credentialId(configMap.get(CREDENTIAL_ID));
+ builder.authContext(getAuthContext(configMap));
+ return builder;
+ }
+
+ public static boolean isOAuthConfig(Map configMap) {
+ return configMap.containsKey(SCOPES);
+ }
+
+ public static Context getAuthContext(Map configMap) {
+ if (isOAuthConfig(configMap)) {
+ return getOAuthContextBuilder(configMap).build();
+ } else {
+ return getJwtContextBuilder(configMap).build();
+ }
}
- }
-
- public static String getSystemProperty(String key) {
- return getSystemProperty(key,DEFAULT_TEST_PROPERTIES);
- }
-
- /**
- * Loads a property from either one of the following sources, probing it first to
- * check that the required property is given, in order:
- *
- * - System Properties
- * - Environment Variables
- * - classpath:{@code propertyClassPath}
- *
- *
- * @param key the property name
- * @param propertyClassPath the classpath of the property file
- * @return the value of the property
- */
- public static String getSystemProperty(String key, String propertyClassPath) {
- if (StringUtils.isNotBlank(System.getProperty(key))) {
- logger.debug("loading property `{}`from JVM System Properties", key);
- return System.getProperty(key);
- } if (StringUtils.isNotBlank(System.getenv(key))) {
- logger.debug("loading property `{}` from Environment Variables", key);
- return System.getenv(key);
- } else {
- logger.debug("loading property `{}` from classpath `{}`", key, propertyClassPath);
- return FileUtil.readPropertiesFromClassPath(propertyClassPath).getProperty(key);
+
+ public static OAuthContext.Builder getOAuthContextBuilder(Map configMap) {
+ OAuthContext.Builder builder = new OAuthContext.Builder();
+ builder.clientSecret(configMap.get(CLIENT_SECRET));
+ if (!StringUtils.isEmpty(configMap.get(SCOPES))) {
+ Arrays.stream(configMap.get(SCOPES).split(",")).forEach(builder::addScope);
+ }
+ return builder;
+ }
+
+
+ public static JwtContext.Builder getJwtContextBuilder(Map configMap) {
+ JwtContext.Builder builder = new JwtContext.Builder()
+ .clientSecret(configMap.get(CLIENT_SECRET))
+ .technicalAccountId(configMap.get(TECHNICAL_ACCOUNT_ID));
+ if (!StringUtils.isEmpty(configMap.get(META_SCOPES))) {
+ String[] metascopeArray = configMap.get(META_SCOPES).split(",");
+ for (String metascope : metascopeArray) {
+ builder.addMetascope(metascope);
+ }
+ }
+ getPrivateKey(configMap).ifPresent(builder::privateKey);
+ return builder;
+ }
+
+ public static Optional getPrivateKey(Map configMap) {
+ String encodedPkcs8Key = configMap.get(PrivateKeyBuilder.AIO_ENCODED_PKCS_8);
+ if (encodedPkcs8Key != null) {
+ logger.debug("loading test JWT Private Key from JVM System Properties");
+ try {
+ return Optional.of(new PrivateKeyBuilder().encodedPkcs8Key(encodedPkcs8Key).build());
+ } catch (Exception e) {
+ logger.error("Error {} loading test Private Key from configMap", e.getMessage());
+ return Optional.empty();
+ }
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ public static String getSystemProperty(String key) {
+ return getSystemProperty(key, DEFAULT_TEST_PROPERTIES);
}
- }
-
- private static Workspace.Builder getWorkspaceBuilder(String propertyFileClassPath) {
- Properties prop = FileUtil.readPropertiesFromClassPath(propertyFileClassPath);
- PrivateKey privateKey = new PrivateKeyBuilder().properties(prop).build();
- return Workspace.builder()
- .properties(prop)
- .privateKey(privateKey);
- }
+
+ /**
+ * Loads a property from either one of the following sources, probing it first to
+ * check that the required property is given, in order:
+ *
+ * - System Properties
+ * - Environment Variables
+ * - classpath:{@code propertyClassPath}
+ *
+ *
+ * @param key the property name
+ * @param propertyClassPath the classpath of the property file
+ * @return the value of the property
+ */
+ public static String getSystemProperty(String key, String propertyClassPath) {
+ return getSystemProperties(Arrays.asList(key), propertyClassPath).get(key);
+ }
+
+ public static Map getSystemWorkspaceConfig(String propertiesClassPath) {
+ return getSystemProperties(Arrays.asList(API_KEY,
+ Workspace.WORKSPACE_ID,
+ CLIENT_SECRET,
+ Workspace.CONSUMER_ORG_ID,
+ IMS_ORG_ID,
+ Workspace.PROJECT_ID), propertiesClassPath);
+ }
+
+ /**
+ * Loads configurations from either one and only one of the following
+ * sources, probing them first to check that all the required properties are given,
+ * in order:
+ *
+ * - JVM System Properties
+ * - Environment Variables
+ * - the provided propertiesClassPath
+ *
+ *
+ * @param propertiesClassPath the classpath of the properties file
+ * @param keys the list of keys to look up
+ * @return Map of all the properties
+ */
+ private static Map getSystemProperties(List keys, String propertiesClassPath) {
+ if (StringUtils.isNoneBlank(keys.stream().map(System::getProperty).toArray(String[]::new))) {
+ logger.debug("loading `{}` from JVM System Properties", keys);
+ return getMap(System.getProperties());
+ }
+ if (StringUtils.isNoneBlank(keys.stream().map(System::getenv).toArray(String[]::new))) {
+ logger.debug("loading `{}` from Environment Variables", keys);
+ return System.getenv();
+ } else {
+ if (WorkspaceUtil.class.getClassLoader().getResourceAsStream(propertiesClassPath) == null) {
+ logger.error("No system configuration found for keys `{}`, no properties file either at `{}`",
+ keys, propertiesClassPath);
+ return Collections.emptyMap();
+ } else {
+ logger.debug("loading `{}` from classpath `{}`", keys, propertiesClassPath);
+ Map map = getMap(propertiesClassPath);
+ if (StringUtils.isNoneBlank(keys.stream().map(map::get).toArray(String[]::new))) {
+ return map;
+ } else {
+ logger.error("Missing configurations: keys: `{}` classpath: `{}`", keys, propertiesClassPath);
+ return Collections.emptyMap();
+ }
+ }
+ }
+ }
+
}
diff --git a/ims/src/test/java/com/adobe/aio/ims/ImsServiceTestDrive.java b/ims/src/test/java/com/adobe/aio/ims/ImsServiceTestDrive.java
new file mode 100644
index 00000000..938aeb26
--- /dev/null
+++ b/ims/src/test/java/com/adobe/aio/ims/ImsServiceTestDrive.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 Adobe. All rights reserved.
+ * This file is licensed 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 REPRESENTATIONS
+ * OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.adobe.aio.ims;
+
+import com.adobe.aio.ims.feign.AuthInterceptor;
+import com.adobe.aio.util.WorkspaceUtil;
+import com.adobe.aio.workspace.Workspace;
+import feign.RequestInterceptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ImsServiceTestDrive {
+
+ private static final Logger logger = LoggerFactory.getLogger(ImsServiceTestDrive.class);
+
+ public static void main(String[] args) {
+ try {
+ Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().build(); // [1]
+ ImsService imsService = ImsService.builder().workspace(workspace).build(); // [2]
+ logger.info("accessToken: {}", imsService.getAccessToken()); // [3]
+
+ // [1] build your `Workspace` (a Java POJO representation of your `Adobe Developer Console` Workspace)
+ // looking up other System Environment variables.
+ // Note that our fluent workspace and private Key builders offers many ways to have your workspace configured,
+ // we are showing here the most concise
+ // [2] build the Ims Service wrapper and have it use this workspace context
+ // [3] use this service to retrieve an OAuth access token
+
+ // here is one way you can build the related Adobe IMS Auth Interceptor
+ RequestInterceptor authInterceptor = AuthInterceptor.builder()
+ .workspace(workspace)
+ .build();
+
+ System.exit(0);
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ System.exit(-1);
+ }
+ }
+
+}
diff --git a/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java b/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java
index c750704d..4a91b29f 100644
--- a/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java
+++ b/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java
@@ -4,12 +4,14 @@
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
+import java.util.Map;
import com.adobe.aio.auth.Context;
import com.adobe.aio.auth.JwtContext;
+import com.adobe.aio.util.FileUtil;
+import com.adobe.aio.util.WorkspaceUtil;
import com.adobe.aio.workspace.Workspace;
import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import org.junit.jupiter.api.Test;
@@ -40,8 +42,11 @@ void build() throws Exception{
PrivateKey privateKey = kp.getPrivate();
PublicKey publicKey = kp.getPublic();
- Workspace.Builder builder = Workspace.builder();
- Workspace workspace = builder.propertiesPath("workspace.properties").privateKey(privateKey).build();
+ Map testConfigs = FileUtil.getMap("workspace.jwt.properties");
+ JwtContext authContext = WorkspaceUtil.getJwtContextBuilder(testConfigs).privateKey(privateKey).build();
+ Workspace.Builder builder = WorkspaceUtil.getWorkspaceBuilder(testConfigs);
+ Workspace workspace = builder.authContext(authContext).build();
+
String actual = new JwtTokenBuilder(workspace).build();
Jwt, Claims> jwt = Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(actual);
diff --git a/ims/src/test/java/com/adobe/aio/ims/feign/AuthInterceptorTest.java b/ims/src/test/java/com/adobe/aio/ims/feign/AuthInterceptorTest.java
index f538ae8c..9d01f1d3 100644
--- a/ims/src/test/java/com/adobe/aio/ims/feign/AuthInterceptorTest.java
+++ b/ims/src/test/java/com/adobe/aio/ims/feign/AuthInterceptorTest.java
@@ -1,131 +1,151 @@
package com.adobe.aio.ims.feign;
-import java.lang.reflect.Field;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.adobe.aio.auth.Context;
import com.adobe.aio.ims.ImsService;
import com.adobe.aio.ims.model.AccessToken;
import com.adobe.aio.workspace.Workspace;
import feign.RequestTemplate;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedConstruction;
-import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
-import static com.adobe.aio.util.Constants.*;
-import static org.junit.jupiter.api.Assertions.*;
+import java.lang.reflect.Field;
+import java.util.*;
+
+import static com.adobe.aio.util.Constants.AUTHORIZATION_HEADER;
+import static com.adobe.aio.util.Constants.BEARER_PREFIX;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
public class AuthInterceptorTest {
- private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
+ private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
+
+ @Mock
+ private RequestTemplate template;
+
+ @Mock
+ private Workspace workspace;
+
+ @Mock
+ private ImsService imsService;
+
+
+ @Test
+ void applyAlreadySet() throws Exception {
+ Calendar expires = Calendar.getInstance();
+ expires.add(Calendar.HOUR, 1);
+ AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
+
+ Map> headers = new HashMap<>();
+ headers.put(AUTHORIZATION_HEADER, Collections.EMPTY_LIST);
- @Mock
- private RequestTemplate template;
+ when(template.headers()).thenReturn(headers);
- @Mock
- private Context authContext;
+ try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
+ (mock, mockContext) -> {
+ when(mock.workspace(workspace)).thenReturn(mock);
+ when(mock.build()).thenReturn(imsService);
+ }
+ )) {
+ AuthInterceptor interceptor = AuthInterceptor.builder().workspace(workspace).build();
+ Field expiresField = AuthInterceptor.class.getDeclaredField("expirationTimeMillis");
+ expiresField.setAccessible(true);
+ expiresField.set(interceptor, expires.getTimeInMillis());
- @Mock
- private Workspace workspace;
+ Field tokenField = AuthInterceptor.class.getDeclaredField("accessToken");
+ tokenField.setAccessible(true);
+ tokenField.set(interceptor, token);
+ interceptor.apply(template);
+ }
+
+ }
+
+ @Test
+ void apply() throws Exception {
+ Calendar expires = Calendar.getInstance();
+ expires.add(Calendar.HOUR, 1);
+ AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
+
+ when(template.headers()).thenReturn(Collections.emptyMap());
+
+ try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
+ (mock, mockContext) -> {
+ when(mock.workspace(workspace)).thenReturn(mock);
+ when(mock.build()).thenReturn(imsService);
+ }
+ )) {
+ AuthInterceptor interceptor = AuthInterceptor.builder().workspace(workspace).build();
+ Field expiresField = AuthInterceptor.class.getDeclaredField("expirationTimeMillis");
+ expiresField.setAccessible(true);
+ expiresField.set(interceptor, expires.getTimeInMillis());
+
+ Field tokenField = AuthInterceptor.class.getDeclaredField("accessToken");
+ tokenField.setAccessible(true);
+ tokenField.set(interceptor, token);
+ interceptor.apply(template);
+
+ verify(template).header(AUTHORIZATION_HEADER, BEARER_PREFIX + ACCESS_TOKEN);
+ }
+ }
+
+ @Test
+ void getAccessTokenNotSet() {
+ Calendar expires = Calendar.getInstance();
+ expires.add(Calendar.HOUR, 1);
+ AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
+
+ try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
+ (mock, mockContext) -> {
+ when(mock.workspace(workspace)).thenReturn(mock);
+ when(mock.build()).thenReturn(imsService);
+ }
+ )) {
+ AuthInterceptor interceptor = AuthInterceptor.builder().workspace(workspace).build();
+ doReturn(token).when(imsService).getAccessToken();
+ assertEquals(ACCESS_TOKEN, interceptor.getAccessToken());
+ }
+ }
+
+ @Test
+ void getAccessTokenExpired() throws Exception {
+ Calendar expires = Calendar.getInstance();
+ expires.add(Calendar.HOUR, 1);
+ AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
+
+ try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
+ (mock, mockContext) -> {
+ when(mock.workspace(workspace)).thenReturn(mock);
+ when(mock.build()).thenReturn(imsService);
+ }
+ )) {
+ AuthInterceptor interceptor = AuthInterceptor.builder().workspace(workspace).build();
+
+ Field expiresField = AuthInterceptor.class.getDeclaredField("expirationTimeMillis");
+ expiresField.setAccessible(true);
+ expiresField.set(interceptor, 1L);
+
+ doReturn(token).when(imsService).getAccessToken();
+ assertEquals(ACCESS_TOKEN, interceptor.getAccessToken());
+ }
+ }
- @Mock
- private ImsService imsService;
+ @Test
+ void fetchAccessToken() {
- @Test
- void invalidContext() {
- when(workspace.getAuthContext()).thenReturn(authContext);
+ when(imsService.getAccessToken()).thenReturn(new AccessToken(ACCESS_TOKEN, 0));
- try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
- (mock, mockContext) -> {
- when(mock.workspace(workspace)).thenReturn(mock);
- when(mock.build()).thenReturn(imsService);
+ try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
+ (mock, mockContext) -> {
+ when(mock.workspace(workspace)).thenReturn(mock);
+ when(mock.build()).thenReturn(imsService);
+ }
+ )) {
+ AuthInterceptor interceptor = AuthInterceptor.builder().workspace(workspace).build();
+ assertNotNull(interceptor.fetchAccessToken());
}
- )) {
- assertThrows(IllegalStateException.class, () -> AuthInterceptor.builder().workspace(workspace).build());
}
- }
-
- @Test
- void applyAlreadySet() throws Exception {
- Calendar expires = Calendar.getInstance();
- expires.add(Calendar.HOUR, 1);
- AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
-
- Map> headers = new HashMap<>();
- headers.put(AUTHORIZATION_HEADER, Collections.EMPTY_LIST);
-
- when(template.headers()).thenReturn(headers);
-
- AuthInterceptor interceptor = mock(AuthInterceptor.class,
- withSettings().useConstructor(imsService).defaultAnswer(CALLS_REAL_METHODS));
- Field expiresField = AuthInterceptor.class.getDeclaredField("expirationTimeMillis");
- expiresField.setAccessible(true);
- expiresField.set(interceptor, expires.getTimeInMillis());
-
- Field tokenField = AuthInterceptor.class.getDeclaredField("accessToken");
- tokenField.setAccessible(true);
- tokenField.set(interceptor, token);
- interceptor.apply(template);
-
- }
-
- @Test
- void apply() throws Exception {
- Calendar expires = Calendar.getInstance();
- expires.add(Calendar.HOUR, 1);
- AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
-
- when(template.headers()).thenReturn(Collections.emptyMap());
-
- AuthInterceptor interceptor = mock(AuthInterceptor.class,
- withSettings().useConstructor(imsService).defaultAnswer(CALLS_REAL_METHODS));
- Field expiresField = AuthInterceptor.class.getDeclaredField("expirationTimeMillis");
- expiresField.setAccessible(true);
- expiresField.set(interceptor, expires.getTimeInMillis());
-
- Field tokenField = AuthInterceptor.class.getDeclaredField("accessToken");
- tokenField.setAccessible(true);
- tokenField.set(interceptor, token);
- interceptor.apply(template);
-
- verify(template).header(AUTHORIZATION_HEADER, BEARER_PREFIX + ACCESS_TOKEN);
- }
-
- @Test
- void getAccessTokenNotSet() {
- Calendar expires = Calendar.getInstance();
- expires.add(Calendar.HOUR, 1);
- AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
-
- AuthInterceptor interceptor = mock(AuthInterceptor.class,
- withSettings().useConstructor(imsService).defaultAnswer(CALLS_REAL_METHODS));
- doReturn(token).when(interceptor).fetchAccessToken();
- assertEquals(ACCESS_TOKEN, interceptor.getAccessToken());
- }
-
- @Test
- void getAccessTokenExpired() throws Exception {
- Calendar expires = Calendar.getInstance();
- expires.add(Calendar.HOUR, 1);
- AccessToken token = new AccessToken(ACCESS_TOKEN, 3600000);
-
- AuthInterceptor interceptor = mock(AuthInterceptor.class,
- withSettings().useConstructor(imsService).defaultAnswer(CALLS_REAL_METHODS));
- Field expiresField = AuthInterceptor.class.getDeclaredField("expirationTimeMillis");
- expiresField.setAccessible(true);
- expiresField.set(interceptor, 1L);
-
- doReturn(token).when(interceptor).fetchAccessToken();
- assertEquals(ACCESS_TOKEN, interceptor.getAccessToken());
- }
}
diff --git a/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceIntegrationTest.java b/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceIntegrationTest.java
index 1c1b770b..31a712a9 100644
--- a/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceIntegrationTest.java
+++ b/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceIntegrationTest.java
@@ -11,6 +11,7 @@
*/
package com.adobe.aio.ims.feign;
+import com.adobe.aio.auth.Context;
import com.adobe.aio.ims.ImsService;
import com.adobe.aio.ims.model.AccessToken;
import com.adobe.aio.util.WorkspaceUtil;
@@ -20,6 +21,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Map;
+
+import static com.adobe.aio.util.WorkspaceUtil.DEFAULT_TEST_PROPERTIES;
+import static com.adobe.aio.workspace.Workspace.API_KEY;
import static org.junit.jupiter.api.Assertions.*;
public class FeignImsServiceIntegrationTest {
@@ -27,42 +32,42 @@ public class FeignImsServiceIntegrationTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Test
- public void getAndValidateJwtExchangeAccessToken() {
+ public void getAccessToken() {
Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().build();
ImsService imsService = ImsService.builder().workspace(workspace).build();
- AccessToken accessToken = imsService.getJwtExchangeAccessToken();
- logger.info("JWT Exchange token flow complete");
+ AccessToken accessToken = imsService.getAccessToken();
assertNotNull(accessToken);
assertNotNull(accessToken.getAccessToken());
- assertTrue(accessToken.getExpiresIn()>0);
- assertTrue(imsService.validateAccessToken(accessToken.getAccessToken()));
- logger.info("JWT Exchange access token validated");
- }
-
- @Test
- public void getAndValidateJwtExchangeAccessTokenWithBadApiKey() {
- Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().apiKey("bad_api_key").build();
- ImsService imsService = ImsService.builder().workspace(workspace).build();
- assertThrows(FeignException.BadRequest.class, imsService::getJwtExchangeAccessToken);
+ assertTrue(accessToken.getExpiresIn() > 0);
+ logger.info("retrieved an access Token");
+ if (workspace.isAuthJWT()) {
+ assertTrue(imsService.validateJwtAccessToken(accessToken.getAccessToken()));
+ logger.info("JWT Exchange access token validated");
+ }
}
@Test
- public void getAndValidateJwtExchangeAccessTokenWithBadSecret() {
- Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().clientSecret("bad_secret").build();
+ public void getAccessTokenWithBadApiKey() {
+ Map workspaceConfig = WorkspaceUtil.getSystemWorkspaceConfig(DEFAULT_TEST_PROPERTIES);
+ workspaceConfig.put(API_KEY, "bad_api_key");
+ Workspace workspace = WorkspaceUtil.getWorkspaceBuilder(workspaceConfig).build();
ImsService imsService = ImsService.builder().workspace(workspace).build();
- assertThrows(FeignException.BadRequest.class, imsService::getJwtExchangeAccessToken);
+ assertThrows(FeignException.BadRequest.class, imsService::getAccessToken);
}
@Test
- public void getAndValidateJwtExchangeAccessTokenWithBadTechAccount() {
- Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().technicalAccountId("bad_tech_account_id@techacct.adobe.com").build();
+ public void getAccessTokenWithBadSecret() {
+ Map workspaceConfig = WorkspaceUtil.getSystemWorkspaceConfig(DEFAULT_TEST_PROPERTIES);
+ workspaceConfig.put(Context.CLIENT_SECRET, "bad_secret");
+ Workspace workspace = WorkspaceUtil.getWorkspaceBuilder(workspaceConfig).build();
ImsService imsService = ImsService.builder().workspace(workspace).build();
- assertThrows(FeignException.BadRequest.class, imsService::getJwtExchangeAccessToken);
+ assertThrows(FeignException.BadRequest.class, imsService::getAccessToken);
}
@Test
- public void getAndValidateJwtExchangeAccessTokenWithMissingPrivateKey() {
- Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().privateKey(null).build();
+ public void buildImsServiceWithMissingAuth() {
+ Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().authContext(null).build();
assertThrows(IllegalStateException.class, () -> ImsService.builder().workspace(workspace).build());
}
+
}
diff --git a/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTest.java b/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTest.java
index ea0060ae..2c150f28 100644
--- a/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTest.java
+++ b/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTest.java
@@ -38,15 +38,15 @@ public class FeignImsServiceTest {
@BeforeEach
void before() {
- when(workspace.getImsUrl()).thenReturn(Constants.IMS_URL);
+ when(workspace.getImsUrl()).thenReturn(Constants.PROD_IMS_URL);
}
@Test
- void getOauthInvalidAuthContext() {
+ void getInvalidAuthContext() {
when(workspace.getAuthContext()).thenReturn(mock(Context.class));
ImsService service = new FeignImsService(workspace);
- Exception ex = assertThrows(IllegalStateException.class, service::getOAuthAccessToken);
- assertEquals("AuthContext in workspace not of type `OAuthContext`.", ex.getMessage());
+ Exception ex = assertThrows(IllegalStateException.class, service::getAccessToken);
+ assertEquals("AuthContext in workspace not of type `OAuthContext` or `JwtContext`.", ex.getMessage());
}
@Test
@@ -58,6 +58,7 @@ void getOAuthAccessToken(MockServerClient client) {
when(workspace.getImsUrl()).thenReturn(imsUrl);
when(workspace.getAuthContext()).thenReturn(context);
when(workspace.getApiKey()).thenReturn(apiKey);
+ when(workspace.isAuthOAuth()).thenReturn(true);
when(context.getClientSecret()).thenReturn(clientSecret);
Set scopes = new HashSet<>();
@@ -86,26 +87,18 @@ void getOAuthAccessToken(MockServerClient client) {
.withBody("{ \"access_token\": \"ACCESS_TOKEN\", \"token_type\": \"bearer\", \"expires_in\": \"1000\" }")
);
ImsService service = new FeignImsService(workspace);
- AccessToken token = service.getOAuthAccessToken();
+ AccessToken token = service.getAccessToken();
assertNotNull(token);
assertEquals("ACCESS_TOKEN", token.getAccessToken());
}
- @Test
- void getJwtInvalidAuthContext() {
- when(workspace.getAuthContext()).thenReturn(mock(Context.class));
- ImsService service = new FeignImsService(workspace);
- Exception ex = assertThrows(IllegalStateException.class, service::getJwtExchangeAccessToken);
- assertEquals("AuthContext in workspace not of type `JwtContext`.", ex.getMessage());
- }
-
@Test
void getJwtInvalidJwtAuthContext() {
Context context = JwtContext.builder().build();
when(workspace.getAuthContext()).thenReturn(context);
ImsService service = new FeignImsService(workspace);
- assertThrows(IllegalStateException.class, service::getJwtExchangeAccessToken);
+ assertThrows(IllegalStateException.class, service::getAccessToken);
}
@Test
@@ -118,6 +111,7 @@ void getJwtExchangeAccessTokenError(MockServerClient client) {
when(workspace.getImsUrl()).thenReturn(imsUrl);
when(workspace.getAuthContext()).thenReturn(context);
when(workspace.getApiKey()).thenReturn(apiKey);
+ when(workspace.isAuthJWT()).thenReturn(true);
when(context.getClientSecret()).thenReturn(clientSecret);
client.when(
@@ -137,7 +131,7 @@ void getJwtExchangeAccessTokenError(MockServerClient client) {
}
)) {
ImsService service = new FeignImsService(workspace);
- assertThrows(FeignException.class, service::getJwtExchangeAccessToken);
+ assertThrows(FeignException.class, service::getAccessToken);
}
verify(context).validate();
}
@@ -152,6 +146,7 @@ void getJwtExchangeAccessTokenSuccess(MockServerClient client) {
when(workspace.getImsUrl()).thenReturn(imsUrl);
when(workspace.getAuthContext()).thenReturn(context);
when(workspace.getApiKey()).thenReturn(apiKey);
+ when(workspace.isAuthJWT()).thenReturn(true);
when(context.getClientSecret()).thenReturn(clientSecret);
client.when(
@@ -174,24 +169,15 @@ void getJwtExchangeAccessTokenSuccess(MockServerClient client) {
}
)) {
ImsService service = new FeignImsService(workspace);
- AccessToken token = service.getJwtExchangeAccessToken();
+ AccessToken token = service.getAccessToken();
assertNotNull(token);
assertEquals("ACCESS_TOKEN", token.getAccessToken());
}
verify(context).validate();
}
-
-
- @Test
- void validateInvalidJwtAuthContext() {
- when(workspace.getAuthContext()).thenReturn(mock(Context.class));
- ImsService service = new FeignImsService(workspace);
- assertThrows(IllegalStateException.class, service::getJwtExchangeAccessToken);
- }
-
@Test
- void validateAccessToken(MockServerClient client) {
+ void validateJwtAccessToken(MockServerClient client) {
final String imsUrl = "http://localhost:" + client.getPort();
final String apiKey = "API_KEY";
final String accessToken = "ACCESS_TOKEN";
@@ -211,7 +197,8 @@ void validateAccessToken(MockServerClient client) {
when(workspace.getAuthContext()).thenReturn(context);
when(workspace.getImsUrl()).thenReturn(imsUrl);
when(workspace.getApiKey()).thenReturn(apiKey);
+ when(workspace.isAuthJWT()).thenReturn(true);
ImsService service = new FeignImsService(workspace);
- assertTrue(service.validateAccessToken(accessToken));
+ assertTrue(service.validateJwtAccessToken(accessToken));
}
}
diff --git a/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTestDrive.java b/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTestDrive.java
deleted file mode 100644
index 4dcead17..00000000
--- a/ims/src/test/java/com/adobe/aio/ims/feign/FeignImsServiceTestDrive.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2017 Adobe. All rights reserved.
- * This file is licensed 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 REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-package com.adobe.aio.ims.feign;
-
-import com.adobe.aio.ims.ImsService;
-import com.adobe.aio.util.WorkspaceUtil;
-import com.adobe.aio.workspace.Workspace;
-import com.adobe.aio.ims.model.AccessToken;
-import com.adobe.aio.ims.util.PrivateKeyBuilder;
-import feign.RequestInterceptor;
-import java.security.PrivateKey;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FeignImsServiceTestDrive {
-
- private static final Logger logger = LoggerFactory.getLogger(FeignImsServiceTestDrive.class);
-
- public static void runTheReadmeFile() {
-
- PrivateKey privateKey = new PrivateKeyBuilder().systemEnv().build(); // [1]
- Workspace workspace = Workspace.builder()
- .systemEnv()
- .privateKey(privateKey)
- .build(); // [2]
- ImsService imsService = ImsService.builder().workspace(workspace).build(); // [3]
-
- AccessToken accessToken = imsService.getJwtExchangeAccessToken(); // [4]
-
- // [1] Build your PrivateKey looking up the key indicated by you System Environment variables
- // [2] build your `Workspace` (a Java POJO representation of your `Adobe Developer Console` Workspace)
- // looking up other System Environment variables.
- // Note that our fluent workspace and private Key builders offers many ways to have your workspace configured,
- // we are showing here the most concise
- // [3] build the Ims Service wrapper and have it use this workspace context
- // [4] use this service to retrieve an access token using a jwt exchange token flow
-
- // here is one way you can build the related IMS Feign JWT Auth Interceptor
- RequestInterceptor authInterceptor = JWTAuthInterceptor.builder()
- .workspace(workspace)
- .build();
- }
-
- /**
- * use your own property file filePath or classpath. WARNING: don't push back to github as it
- * contains many secrets. We do provide a sample/template workspace.properties file in the
- * ./src/test/resources folder
- */
- private static final String DEFAULT_TEST_PROPERTIES = "workspace.secret.properties";
-
- public static void main(String[] args) {
- try {
- Workspace workspace = WorkspaceUtil.getSystemWorkspaceBuilder().build();
- ImsService imsService = ImsService.builder().workspace(workspace).build();
-
- AccessToken accessToken = imsService.getJwtExchangeAccessToken();
- logger.info("accessToken: {}", accessToken);
- logger.info("accessToken validated: {}:",imsService.validateAccessToken(accessToken.getAccessToken()));
- System.exit(0);
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- System.exit(-1);
- }
- }
-
-}
diff --git a/ims/src/test/java/com/adobe/aio/ims/feign/JwtAuthInterceptorTest.java b/ims/src/test/java/com/adobe/aio/ims/feign/JwtAuthInterceptorTest.java
deleted file mode 100644
index b99577e2..00000000
--- a/ims/src/test/java/com/adobe/aio/ims/feign/JwtAuthInterceptorTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.adobe.aio.ims.feign;
-
-import java.lang.reflect.Field;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.adobe.aio.auth.JwtContext;
-import com.adobe.aio.ims.ImsService;
-import com.adobe.aio.ims.model.AccessToken;
-import com.adobe.aio.workspace.Workspace;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.MockedConstruction;
-import org.mockito.junit.jupiter.MockitoExtension;
-import shaded_package.org.checkerframework.checker.units.qual.A;
-
-import static com.adobe.aio.util.Constants.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-@ExtendWith(MockitoExtension.class)
-public class JwtAuthInterceptorTest {
- private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
-
- @Mock
- private Workspace workspace;
-
- @Mock
- private JwtContext authContext;
-
- @Mock
- private ImsService imsService;
-
- @Test
- void isUp() {
- when(workspace.getAuthContext()).thenReturn(authContext);
- when(imsService.validateAccessToken(ACCESS_TOKEN)).thenReturn(true);
-
- try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
- (mock, mockContext) -> {
- when(mock.workspace(workspace)).thenReturn(mock);
- when(mock.build()).thenReturn(imsService);
- }
- )) {
- JWTAuthInterceptor spy = spy((JWTAuthInterceptor) AuthInterceptor.builder().workspace(workspace).build());
- doReturn(ACCESS_TOKEN).when(spy).getAccessToken();
- assertTrue(spy.isUp());
- }
- }
-
- @Test
- void fetchAccessToken() {
- when(workspace.getAuthContext()).thenReturn(authContext);
- when(imsService.getJwtExchangeAccessToken()).thenReturn(new AccessToken(ACCESS_TOKEN, 0));
-
- try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
- (mock, mockContext) -> {
- when(mock.workspace(workspace)).thenReturn(mock);
- when(mock.build()).thenReturn(imsService);
- }
- )) {
- JWTAuthInterceptor interceptor = (JWTAuthInterceptor) AuthInterceptor.builder().workspace(workspace).build();
- assertNotNull(interceptor.fetchAccessToken());
- }
- }
-}
diff --git a/ims/src/test/java/com/adobe/aio/ims/feign/OAuthAuthInterceptorTest.java b/ims/src/test/java/com/adobe/aio/ims/feign/OAuthAuthInterceptorTest.java
deleted file mode 100644
index de93714d..00000000
--- a/ims/src/test/java/com/adobe/aio/ims/feign/OAuthAuthInterceptorTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.adobe.aio.ims.feign;
-
-import com.adobe.aio.auth.JwtContext;
-import com.adobe.aio.auth.OAuthContext;
-import com.adobe.aio.ims.ImsService;
-import com.adobe.aio.ims.model.AccessToken;
-import com.adobe.aio.workspace.Workspace;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.MockedConstruction;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-@ExtendWith(MockitoExtension.class)
-public class OAuthAuthInterceptorTest {
- private static final String ACCESS_TOKEN = "ACCESS_TOKEN";
-
- @Mock
- private Workspace workspace;
-
- @Mock
- private OAuthContext authContext;
-
- @Mock
- private ImsService imsService;
-
- @Test
- void fetchAccessToken() {
- when(workspace.getAuthContext()).thenReturn(authContext);
- when(imsService.getOAuthAccessToken()).thenReturn(new AccessToken(ACCESS_TOKEN, 0));
-
- try (MockedConstruction ignored = mockConstruction(ImsService.Builder.class,
- (mock, mockContext) -> {
- when(mock.workspace(workspace)).thenReturn(mock);
- when(mock.build()).thenReturn(imsService);
- }
- )) {
- OAuthInterceptor interceptor = (OAuthInterceptor) AuthInterceptor.builder().workspace(workspace).build();
- assertNotNull(interceptor.fetchAccessToken());
- }
- }
-}
diff --git a/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java b/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java
new file mode 100644
index 00000000..08fa6e46
--- /dev/null
+++ b/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 Adobe. All rights reserved.
+ * This file is licensed 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 REPRESENTATIONS
+ * OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package com.adobe.aio.util;
+
+import com.adobe.aio.auth.JwtContext;
+import com.adobe.aio.auth.OAuthContext;
+import com.adobe.aio.workspace.Workspace;
+import org.junit.jupiter.api.Test;
+
+import static com.adobe.aio.auth.Context.CLIENT_SECRET;
+import static com.adobe.aio.auth.JwtContext.*;
+import static com.adobe.aio.auth.OAuthContext.SCOPES;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class WorkspaceUtilTest {
+
+ private static final String TEST_JWT_WORKSPACE_PROPERTIES = "workspace.jwt.properties";
+ private static final String TEST_OAUTH_WORKSPACE_PROPERTIES = "workspace.oauth.properties";
+ private static final String TEST_VALUE = "_changeMe";
+
+ @Test
+ public void getWorkspaceBuilderFromJwtProperties() {
+ Workspace workspaceFromProperties = WorkspaceUtil.getWorkspaceBuilder(FileUtil.getMap(TEST_JWT_WORKSPACE_PROPERTIES)).build();
+ JwtContext expectedAuthContext = JwtContext.builder()
+ .clientSecret(CLIENT_SECRET + TEST_VALUE)
+ .technicalAccountId(TECHNICAL_ACCOUNT_ID + TEST_VALUE)
+ .addMetascope(META_SCOPES + TEST_VALUE)
+ .build();
+ Workspace expected = Workspace.builder()
+ .imsUrl(Constants.PROD_IMS_URL)
+ .imsOrgId(Workspace.IMS_ORG_ID + TEST_VALUE)
+ .apiKey(Workspace.API_KEY + TEST_VALUE)
+ .consumerOrgId(Workspace.CONSUMER_ORG_ID + TEST_VALUE)
+ .projectId(Workspace.PROJECT_ID + TEST_VALUE)
+ .workspaceId(Workspace.WORKSPACE_ID + TEST_VALUE)
+ .credentialId(Workspace.CREDENTIAL_ID + TEST_VALUE)
+ .authContext(expectedAuthContext)
+ .build();
+
+ assertEquals(expected, workspaceFromProperties);
+ assertEquals(expected.hashCode(), workspaceFromProperties.hashCode());
+ assertEquals(expected.toString(), workspaceFromProperties.toString());
+ assertEquals(expectedAuthContext, workspaceFromProperties.getAuthContext());
+ assertTrue(workspaceFromProperties.isAuthJWT());
+ workspaceFromProperties.validateWorkspaceContext();
+ }
+
+ @Test
+ public void getWorkspaceBuilderFromOAuthProperties() {
+ Workspace workspaceFromProperties = WorkspaceUtil.getWorkspaceBuilder(FileUtil.getMap(TEST_OAUTH_WORKSPACE_PROPERTIES)).build();
+ OAuthContext expectedAuthContext = new OAuthContext.Builder().clientSecret(CLIENT_SECRET + TEST_VALUE).addScope(SCOPES + TEST_VALUE).build();
+ Workspace expected = Workspace.builder()
+ .imsUrl(Constants.PROD_IMS_URL)
+ .imsOrgId(Workspace.IMS_ORG_ID + TEST_VALUE)
+ .apiKey(Workspace.API_KEY + TEST_VALUE)
+ .consumerOrgId(Workspace.CONSUMER_ORG_ID + TEST_VALUE)
+ .projectId(Workspace.PROJECT_ID + TEST_VALUE)
+ .workspaceId(Workspace.WORKSPACE_ID + TEST_VALUE)
+ .authContext(expectedAuthContext)
+ .build();
+ assertEquals(expected, workspaceFromProperties);
+ assertEquals(expected.hashCode(), workspaceFromProperties.hashCode());
+ assertEquals(expected.toString(), workspaceFromProperties.toString());
+ assertEquals(expectedAuthContext, workspaceFromProperties.getAuthContext());
+ assertTrue(workspaceFromProperties.isAuthOAuth());
+ workspaceFromProperties.validateAll();
+ }
+
+}
diff --git a/ims/src/test/resources/workspace.properties b/ims/src/test/resources/workspace.jwt.properties
similarity index 89%
rename from ims/src/test/resources/workspace.properties
rename to ims/src/test/resources/workspace.jwt.properties
index 23b3eb9f..8ecdf9c0 100644
--- a/ims/src/test/resources/workspace.properties
+++ b/ims/src/test/resources/workspace.jwt.properties
@@ -18,7 +18,7 @@ aio_consumer_org_id=aio_consumer_org_id_changeMe
aio_ims_org_id=aio_ims_org_id_changeMe
# aio_workspace_id = your Adobe Developer Console workspace Id (project.workspace.id)
aio_workspace_id=aio_workspace_id_changeMe
-# aio_credential_id = your Adobe Developer Console jwt credential id (project.workspace.details.credentials[i].id)
+# aio_credential_id = your Adobe Developer Console credential id (project.workspace.details.credentials[i].id)
aio_credential_id=aio_credential_id_changeMe
# aio_client_secret = your Adobe Developer Console jwt credential client secret (project.workspace.details.credentials[i].jwt.client_secret)
aio_client_secret=aio_client_secret_changeMe
@@ -29,5 +29,6 @@ aio_api_key=aio_api_key_changeMe
aio_meta_scopes=aio_meta_scopes_changeMe
# aio_technical_account_id = your Adobe Developer Console jwt credential technical account id (project.workspace.details.credentials[i].jwt.technical_account_id)
aio_technical_account_id=aio_technical_account_id_changeMe
+# aio_encoded_pkcs8 = your privateKey (associated with the public key set in your Adobe Developer Console workspace) in a base64 encoded pkcs8 format
aio_encoded_pkcs8=changeMe
diff --git a/ims/src/test/resources/workspace.oauth.properties b/ims/src/test/resources/workspace.oauth.properties
new file mode 100644
index 00000000..591df34d
--- /dev/null
+++ b/ims/src/test/resources/workspace.oauth.properties
@@ -0,0 +1,28 @@
+#
+# Copyright 2017 Adobe. All rights reserved.
+# This file is licensed 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 REPRESENTATIONS
+# OF ANY KIND, either express or implied. See the License for the specific language
+# governing permissions and limitations under the License.
+#
+
+# aio_project_id = your Adobe Developer Console project id (project.id)
+aio_project_id=aio_project_id_changeMe
+# aio_consumer_org_id = your Adobe Developer Console consumer orgnaization id (project.org.id)
+aio_consumer_org_id=aio_consumer_org_id_changeMe
+# aio_ims_org_id = your Adobe Developer Console IMS Organization ID (project.org.ims_org_id)
+aio_ims_org_id=aio_ims_org_id_changeMe
+# aio_workspace_id = your Adobe Developer Console workspace Id (project.workspace.id)
+aio_workspace_id=aio_workspace_id_changeMe
+# aio_client_secret = your Adobe Developer Console jwt credential client secret (project.workspace.details.credentials[i].oauth_server_to_server.client_secrets[0])
+aio_client_secret=aio_client_secret_changeMe
+# aio_api_key = your Adobe Developer Console credential API Key (or Client ID) (project.workspace.details.credentials[i].oauth_server_to_server.client_id)
+aio_api_key=aio_api_key_changeMe
+# aio_oauth_scopes : comma separated list of oauth associated with your API, see your Adobe Developer Console oauth scopes (project.workspace.details.credentials[i].oauth_server_to_server.scopes)
+# sample aio_oauth_scopes: aio_oauth_scopes= AdobeID,openid,read_organizations,additional_info.projectedProductContext,additional_info.roles,adobeio_api,read_client_secret,manage_client_secrets
+aio_oauth_scopes=aio_oauth_scopes_changeMe
+
diff --git a/pom.xml b/pom.xml
index 5707a8e6..2decc576 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
com.adobe.aio
aio-lib-java
- 1.1.29-SNAPSHOT
+ 2.0.0-SNAPSHOT
pom