From fcbb8ba51044dc497af0a2033ffa02771cae8776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20Vintil=C4=83?= Date: Mon, 16 Jun 2025 23:52:41 +0300 Subject: [PATCH 1/3] CI-5972: Fix tests on Windows platform --- .../webhook/service/EventVerifierTest.java | 10 ++++----- .../adobe/xdm/event/SerializationTest.java | 21 ++++++++++++------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/events_webhook/src/test/java/com/adobe/aio/event/webhook/service/EventVerifierTest.java b/events_webhook/src/test/java/com/adobe/aio/event/webhook/service/EventVerifierTest.java index 22077fea..1db51169 100644 --- a/events_webhook/src/test/java/com/adobe/aio/event/webhook/service/EventVerifierTest.java +++ b/events_webhook/src/test/java/com/adobe/aio/event/webhook/service/EventVerifierTest.java @@ -274,7 +274,7 @@ private static PublicKey getPubKey1() throws Exception { + "aWMxNONoH9kH2mhguidf8MCWwIuYyqO+J+IzsshXVWGyMyn3q7fVZCra9ISEZqWE\n" + "iwIDAQAB"; - publicK = publicK.replaceAll(System.lineSeparator(), ""); + publicK = publicK.replaceAll("\n", ""); return stringToKey(publicK); } @@ -286,7 +286,7 @@ private static PublicKey getPubKey2() throws Exception { + "jku8atEfdo341WcHSHW2hf/Gx2mazhGg1of6wZVforXo3R1HVqIVMlOk6GMcz4HH\n" + "iLOuEOURFucux3jm4gF2DF1B627vCqaGDoduvyIjitXQS6KqSx3dzB2dGOBDPpsr\n" + "8wIDAQAB"; - publicK = publicK.replaceAll(System.lineSeparator(), ""); + publicK = publicK.replaceAll("\n", ""); return stringToKey(publicK); } @@ -299,7 +299,7 @@ private static PublicKey getPublicKey1ForBatchPayload() throws Exception { + "AMJqNqyVENaVON0sVA8u10aIPi9xIi9vR9rGpridIP+zMiwsv+H1zWoU5CX4eN5RN/\n" + "QIDAQAB"; - publicK = publicK.replaceAll(System.lineSeparator(), ""); + publicK = publicK.replaceAll("\n", ""); return stringToKey(publicK); } @@ -311,7 +311,7 @@ private static PublicKey getPublicKey2ForBatchPayload() throws Exception { + "rLA1kZ6X2rKxrnz6bTG8ad+rkL3DbY/WvAah9ZJz8Xq87TS3/NDsveloVQ3+Wm+nF3\n" + "tyzdyTRDldwviRFX+EDhzAbTtk2hEZEIU3+9zxhSAscBUfV/2+P12vnowVoYNN7mqr\n" + "QIDAQAB"; - publicK = publicK.replaceAll(System.lineSeparator(), ""); + publicK = publicK.replaceAll("\n", ""); return stringToKey(publicK); } @@ -323,7 +323,7 @@ private static PublicKey getAnotherPubKey() throws Exception { + "mZ5+3/uF4Ms21BqRSGCUEwNKpSxXT2bFNlUw0/DbM6gJuE1CJdk5z/sbLA0S3b1z\n" + "PR1LpgOeG84lFG7c0gcIaeZX+c3dLdmNBfkOQwacFP3m0urlJkSxI8MomaeEOS2y\n" + "hQIDAQAB"; - publicK = publicK.replaceAll(System.lineSeparator(), ""); + publicK = publicK.replaceAll("\n", ""); return stringToKey(publicK); } } diff --git a/events_xdm/src/test/java/com/adobe/xdm/event/SerializationTest.java b/events_xdm/src/test/java/com/adobe/xdm/event/SerializationTest.java index f6896251..c1d3f6e5 100644 --- a/events_xdm/src/test/java/com/adobe/xdm/event/SerializationTest.java +++ b/events_xdm/src/test/java/com/adobe/xdm/event/SerializationTest.java @@ -22,10 +22,11 @@ import com.adobe.xdm.extensions.ims.ImsUser; import com.adobe.xdm.external.repo.Directory; import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Hashtable; import org.junit.jupiter.api.BeforeEach; @@ -272,10 +273,16 @@ public void testXdmContextSerialization() throws IOException { } private static String readFile(String fileName) throws IOException { - byte[] encoded = Files.readAllBytes(Paths.get( - Thread.currentThread().getContextClassLoader() - .getResource(fileName).getPath())); - return new String(encoded, StandardCharsets.UTF_8); - } + try (InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = in.read(buffer, 0, buffer.length)) != -1) { + out.write(buffer, 0, bytesRead); + } + + return new String(out.toByteArray(), StandardCharsets.UTF_8); + } + } } From 7c6908037633a542839c9ffda404173372259cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20Vintil=C4=83?= Date: Mon, 16 Jun 2025 23:52:41 +0300 Subject: [PATCH 2/3] CI-5972: Remove JWT Auth --- aem/core_aem/README.md | 11 +- .../internal/WorkspaceSupplierImpl.java | 7 - .../aem/workspace/ocd/WorkspaceConfig.java | 12 -- core/README.md | 10 -- .../java/com/adobe/aio/auth/JwtContext.java | 153 ------------------ .../com/adobe/aio/workspace/Workspace.java | 9 +- .../com/adobe/aio/auth/JwtContextTest.java | 62 ------- .../test/resources/workspace.jwt.properties | 35 ---- .../test/resources/workspace.oauth.properties | 2 +- ims/README.md | 32 +--- .../java/com/adobe/aio/ims/ImsService.java | 13 +- .../com/adobe/aio/ims/JwtTokenBuilder.java | 86 ---------- .../java/com/adobe/aio/ims/api/ImsApi.java | 14 -- .../adobe/aio/ims/feign/FeignImsService.java | 29 +--- .../adobe/aio/ims/util/PrivateKeyBuilder.java | 50 ------ .../com/adobe/aio/util/WorkspaceUtil.java | 44 +---- .../adobe/aio/ims/JwtTokenBuilderTest.java | 70 -------- .../feign/FeignImsServiceIntegrationTest.java | 4 - .../aio/ims/feign/FeignImsServiceTest.java | 114 +------------ .../com/adobe/aio/util/WorkspaceUtilTest.java | 30 ---- .../test/resources/workspace.jwt.properties | 34 ---- .../test/resources/workspace.oauth.properties | 2 +- 22 files changed, 12 insertions(+), 811 deletions(-) delete mode 100644 core/src/main/java/com/adobe/aio/auth/JwtContext.java delete mode 100644 core/src/test/java/com/adobe/aio/auth/JwtContextTest.java delete mode 100644 core/src/test/resources/workspace.jwt.properties delete mode 100644 ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java delete mode 100644 ims/src/main/java/com/adobe/aio/ims/util/PrivateKeyBuilder.java delete mode 100644 ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java delete mode 100644 ims/src/test/resources/workspace.jwt.properties diff --git a/aem/core_aem/README.md b/aem/core_aem/README.md index d7fbd03e..a08aefe4 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 (using either JWT or OAuth token flow) from Adobe Identity Management System (IMS) +* get Access token (using the OAuth token flow) from Adobe Identity Management System (IMS) ## `Workspace` Configuration @@ -18,14 +18,7 @@ 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.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.api.key` your Adobe Developer Console credential API Key (or Client ID) When using OAuth credentials also set * `aio.client.secret` your Adobe Developer Console oAuth credential client secret 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 eb4e8c97..6658f768 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 @@ -15,9 +15,7 @@ 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.util.HashMap; @@ -84,11 +82,6 @@ private Map getAuthConfigMap( 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; } 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 9b8d662f..2eaba07f 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,6 @@ 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 = "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(); @@ -54,16 +50,8 @@ 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 (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") String aio_client_secret(); - @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/core/README.md b/core/README.md index 578f636e..e81c15ef 100644 --- a/core/README.md +++ b/core/README.md @@ -11,7 +11,6 @@ your [Adobe Developer Console Project Workspace](https://www.adobe.io/apis/exper To get you started quickly use a `.properties` file, * 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 @@ -37,15 +36,6 @@ For [OAuth2 authentication](https://developer.adobe.com/developer-console/docs/g * `aio_client_secret` one your Adobe Developer Console OAuth Client Secrets (`project.workspace.details.credentials[i].oauth_server_to_server.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`) -#### 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_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 - - ## Builds diff --git a/core/src/main/java/com/adobe/aio/auth/JwtContext.java b/core/src/main/java/com/adobe/aio/auth/JwtContext.java deleted file mode 100644 index fed94d4e..00000000 --- a/core/src/main/java/com/adobe/aio/auth/JwtContext.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2023 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.auth; - -import java.security.PrivateKey; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -import org.apache.commons.lang3.StringUtils; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -/** - * JWT Authentication context. - */ -public class JwtContext implements Context { - - public static final String TECHNICAL_ACCOUNT_ID = "aio_technical_account_id"; - public static final String META_SCOPES = "aio_meta_scopes"; - - private final String technicalAccountId; - private final Set metascopes; - private final String clientSecret; - private final PrivateKey privateKey; - - public JwtContext(final String clientSecret, final String technicalAccountId, - final Set metascopes, final PrivateKey privateKey) { - this.clientSecret = clientSecret; - this.technicalAccountId = technicalAccountId; - this.metascopes = metascopes; - this.privateKey = privateKey; - } - - public static Builder builder() { - return new Builder(); - } - - public void validate() { - if (StringUtils.isEmpty(clientSecret)) { - throw new IllegalStateException("Your `JwtContext` is missing a clientSecret"); - } - if (StringUtils.isEmpty(technicalAccountId)) { - throw new IllegalStateException("Your `JwtContext` is missing a technicalAccountId"); - } - if (metascopes.isEmpty()) { - throw new IllegalStateException("Your `JwtContext` is missing a metascope"); - } - if (privateKey == null) { - throw new IllegalStateException("Your `JwtContext` is missing a privateKey"); - } - } - - public String getTechnicalAccountId() { - return technicalAccountId; - } - - public Set getMetascopes() { - return metascopes; - } - - // we want to avoid serializing this secret - @JsonIgnore - public String getClientSecret() { - return clientSecret; - } - - public boolean isClientSecretDefined() { - return !StringUtils.isEmpty(this.clientSecret); - } - - // we want to avoid serializing this secret - @JsonIgnore - public PrivateKey getPrivateKey() { - return privateKey; - } - - public boolean isPrivateKeyDefined() { - return (this.privateKey != null); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - JwtContext that = (JwtContext) o; - - if (!Objects.equals(technicalAccountId, that.technicalAccountId)) - return false; - if (!Objects.equals(metascopes, that.metascopes)) return false; - if (!Objects.equals(clientSecret, that.clientSecret)) return false; - return Objects.equals(privateKey, that.privateKey); - } - - @Override - public int hashCode() { - 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); - return result; - } - - @Override - public String toString() { - return "JwtContext{" + - "technicalAccountId='" + technicalAccountId + '\'' + - ", metascopes=" + metascopes + - '}'; - } - - public static class Builder { - - private String clientSecret; - private String technicalAccountId; - private PrivateKey privateKey; - private final Set metascopes = new HashSet<>(); - - public Builder clientSecret(final String clientSecret) { - this.clientSecret = clientSecret; - return this; - } - - public Builder technicalAccountId(final String technicalAccountId) { - this.technicalAccountId = technicalAccountId; - return this; - } - - public Builder addMetascope(final String metascope) { - this.metascopes.add(metascope); - return this; - } - - public Builder privateKey(final PrivateKey privateKey) { - this.privateKey = privateKey; - return this; - } - - public JwtContext build() { - return new JwtContext(clientSecret, technicalAccountId, metascopes, privateKey); - } - } -} 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 28e02579..577e06af 100644 --- a/core/src/main/java/com/adobe/aio/workspace/Workspace.java +++ b/core/src/main/java/com/adobe/aio/workspace/Workspace.java @@ -13,7 +13,6 @@ 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.util.Map; @@ -58,8 +57,8 @@ public static Builder builder() { public void validateAll() { validateWorkspaceContext(); - if (!isAuthOAuth() && !isAuthJWT()) { - throw new IllegalStateException("Missing auth configuration, set either jwt or oauth..."); + if (!isAuthOAuth()) { + throw new IllegalStateException("Missing auth configuration, set oauth properties..."); } authContext.validate(); } @@ -139,10 +138,6 @@ public boolean isAuthOAuth() { return authContext!=null && authContext instanceof OAuthContext; } - public boolean isAuthJWT() { - return authContext!=null && authContext instanceof JwtContext; - } - @Override public boolean equals(Object o) { diff --git a/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java b/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java deleted file mode 100644 index 52613ca7..00000000 --- a/core/src/test/java/com/adobe/aio/auth/JwtContextTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.adobe.aio.auth; - -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.PrivateKey; - -import static com.adobe.aio.auth.JwtContext.*; -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class JwtContextTest { - private static final String TEST_VALUE = "_changeMe"; - - private static PrivateKey privateKey; - - @BeforeAll - public static void beforeClass() throws Exception { - KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); - kpg.initialize(2048); - KeyPair kp = kpg.generateKeyPair(); - privateKey = kp.getPrivate(); - } - - @Test - void missingClientSecret() { - JwtContext actual = JwtContext.builder().build(); - Exception ex = assertThrows(IllegalStateException.class, actual::validate); - assertEquals("Your `JwtContext` is missing a clientSecret", ex.getMessage()); - } - - @Test - void missingTechnicalAccountId() { - JwtContext actual = JwtContext.builder() - .clientSecret(CLIENT_SECRET + TEST_VALUE) - .build(); - Exception ex = assertThrows(IllegalStateException.class, actual::validate); - assertEquals("Your `JwtContext` is missing a technicalAccountId", ex.getMessage()); - } - - @Test - void missingMetascopes() { - JwtContext actual = JwtContext.builder() - .clientSecret(CLIENT_SECRET + TEST_VALUE) - .technicalAccountId(TECHNICAL_ACCOUNT_ID + TEST_VALUE) - .build(); - Exception ex = assertThrows(IllegalStateException.class, actual::validate); - assertEquals("Your `JwtContext` is missing a metascope", ex.getMessage()); - } - - @Test - void missingPrivateKey() { - JwtContext actual = JwtContext.builder() - .clientSecret(CLIENT_SECRET + TEST_VALUE) - .technicalAccountId(TECHNICAL_ACCOUNT_ID + TEST_VALUE) - .addMetascope(META_SCOPES + TEST_VALUE) - .build(); - Exception ex = assertThrows(IllegalStateException.class, actual::validate); - assertEquals("Your `JwtContext` is missing a privateKey", ex.getMessage()); - } -} diff --git a/core/src/test/resources/workspace.jwt.properties b/core/src/test/resources/workspace.jwt.properties deleted file mode 100644 index 27eee20f..00000000 --- a/core/src/test/resources/workspace.jwt.properties +++ /dev/null @@ -1,35 +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_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 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 - - - diff --git a/core/src/test/resources/workspace.oauth.properties b/core/src/test/resources/workspace.oauth.properties index f847f386..a63c2692 100644 --- a/core/src/test/resources/workspace.oauth.properties +++ b/core/src/test/resources/workspace.oauth.properties @@ -23,7 +23,7 @@ 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 = your Adobe Developer Console oauth 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 diff --git a/ims/README.md b/ims/README.md index 78c48066..5ae1793e 100644 --- a/ims/README.md +++ b/ims/README.md @@ -35,11 +35,8 @@ Have a look at our [ImsService `main()` Test Drive](./src/test/java/com/adobe/ai 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) -It allows you to integrate with the two server to server authentication credentials that Adobe supports. +It allows you to integrate with the server to server authentication credentials that Adobe supports. * OAuth Server-to-Server credentials -* Service Account (JWT) credentials (deprecated) - -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. @@ -49,33 +46,6 @@ Browse our [OAuth authentication documentation](https://developer.adobe.com/deve and to get you started quickly, have a look at our [sample oauth config file: `workspace.oauth.properties`](./src/test/resources/workspace.oauth.properties) -### 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. - -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, -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 - -* 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/src/main/java/com/adobe/aio/ims/ImsService.java b/ims/src/main/java/com/adobe/aio/ims/ImsService.java index 58134b18..a1dcd437 100644 --- a/ims/src/main/java/com/adobe/aio/ims/ImsService.java +++ b/ims/src/main/java/com/adobe/aio/ims/ImsService.java @@ -17,20 +17,9 @@ public interface ImsService { - - /** - * Checks that the jwt access token is still valid. - * - * @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 validateJwtAccessToken(String jwtAccessToken); - /** * Looking up the contextual Workspace, it will use - * either the OAuth or JWT authentication context to fetch a valid access token. + * the OAuth authentication context to fetch a valid access token. * @return AccessToken a valid API authentication token */ AccessToken getAccessToken(); diff --git a/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java b/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java deleted file mode 100644 index 11053c8e..00000000 --- a/ims/src/main/java/com/adobe/aio/ims/JwtTokenBuilder.java +++ /dev/null @@ -1,86 +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; - -import com.adobe.aio.auth.Context; -import com.adobe.aio.auth.JwtContext; -import com.adobe.aio.workspace.Workspace; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import java.security.PrivateKey; -import java.util.HashMap; -import java.util.Map; - -/** - * FYI, the JWT token will generate for you will contain the following claims: - * - * `exp` - the expiration time. IMS allows a time skew of 30 seconds between the time specified and the IMS server time. - * `iss` - the issuer. It must be present, and it must be in the format: `org_ident@AdobeOrg` It represents the identity of the organization which issued the token, and it must be for an organization that has provided IMS with a valid certificate. - * `sub` - the subject. It must be present and must be in the format: `user_ident@user_auth_src`. It represents the ident and authsrc of the technical account for which a certificate has been uploaded to IMS - * `aud` - the audience of the token. Must be only one entry, in the format: `ENDPOINT_URI/c/client_id`, where the client_id is the client id for which the access token will be issued. The `ENDPOINT_URI` must be a valid IMS endpoint (e.g. `https://ims-na1.adobelogin.com` for IMS production) - * `one or more metascopes claims`, in the format: `ENDPOINT_URI/s/SCOPE_CODE: true`, where the ENDPOINT_URI has the same meaning as for the audience, and the SCOPE_CODE is a valid meta-scope code that was granted to you when the certificate binding was created. - * - * Note that Optionally, the JWT can contain the following claims (not implemented here yet) - * `jti` - a unique identifier for the token. It is dependent on the setting being configured when the certificate binding was created, and if it is set as required it must have not been previously seen by the service, or the request will be reject - * - * It will also help you getting this signed with a `RSASSA-PKCS1-V1_5` Digital Signatures with `SHA-2` and a `RS256` The JWT algorithm/`alg` header value. - * For this, it leverages a third-party open source library : [jjwt](https://github.com/jwtk/jjwt) - * - * @deprecated See Developer Console documentation - */ -@Deprecated -public class JwtTokenBuilder { - - private final Map claims; - private final PrivateKey privateKey; - - private static final String ISS = "iss"; - private static final String EXP = "exp"; - private static final String SUB = "sub"; - private static final String AUD = "aud"; - private static final String IAT = "iat"; - - private static final String AUD_SUFFIX = "/c/"; - - public JwtTokenBuilder(final Workspace workspace) { - if (!workspace.isAuthJWT()) { - throw new IllegalStateException("AuthContext in workspace not of type `JwtContext`."); - } - - JwtContext context = (JwtContext) workspace.getAuthContext(); - context.validate(); - this.claims = getClaims(workspace, context); - this.privateKey = context.getPrivateKey(); - } - - private static Map getClaims(final Workspace workspace, JwtContext context) { - Map claims = new HashMap(); - claims.put(ISS, workspace.getImsOrgId()); - claims.put(SUB, context.getTechnicalAccountId()); - claims.put(AUD, workspace.getImsUrl() + AUD_SUFFIX + workspace.getApiKey()); - - for (String metascope : context.getMetascopes()) { - claims.put(workspace.getImsUrl() + metascope, true); - } - - long iat = System.currentTimeMillis() / 1000L; - claims.put(IAT, iat); - claims.put(EXP, iat + 180L); - return claims; - } - - public String build() { - return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.RS256, privateKey).compact(); - } - -} diff --git a/ims/src/main/java/com/adobe/aio/ims/api/ImsApi.java b/ims/src/main/java/com/adobe/aio/ims/api/ImsApi.java index ea851370..bfdbd501 100644 --- a/ims/src/main/java/com/adobe/aio/ims/api/ImsApi.java +++ b/ims/src/main/java/com/adobe/aio/ims/api/ImsApi.java @@ -20,20 +20,6 @@ public interface ImsApi { - @RequestLine("POST /ims/exchange/jwt") - @Headers("Content-Type: application/x-www-form-urlencoded") - AccessToken getJwtAccessToken( - @Param("client_id") String clientId, - @Param("client_secret") String clientSecret, - @Param("jwt_token") String jwtToken); - - @RequestLine("POST /ims/validate_token/v1") - @Headers("Content-Type: application/x-www-form-urlencoded") - TokenValidation validateJwtToken( - @Param("type") String type, - @Param("client_id") String clientId, - @Param("token") String accessToken); - @RequestLine("POST /ims/token/v3?client_id={client_id}") @Headers("Content-Type: application/x-www-form-urlencoded") @Body("client_secret={client_secret}&grant_type=client_credentials&scope={scopes}") 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 634adca9..1be8af8e 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 @@ -15,10 +15,8 @@ import org.apache.commons.lang3.StringUtils; -import com.adobe.aio.auth.JwtContext; import com.adobe.aio.auth.OAuthContext; import com.adobe.aio.ims.ImsService; -import com.adobe.aio.ims.JwtTokenBuilder; import com.adobe.aio.workspace.Workspace; import com.adobe.aio.ims.api.ImsApi; import com.adobe.aio.ims.model.AccessToken; @@ -41,34 +39,11 @@ public FeignImsService(final Workspace workspace) { @Override public AccessToken getAccessToken() { - if (workspace.isAuthJWT()) { - return getJwtExchangeAccessToken(); - } else if (workspace.isAuthOAuth()) { + 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`."); + throw new IllegalStateException("AuthContext in workspace not of type `OAuthContext`."); } - JwtContext context = (JwtContext) workspace.getAuthContext(); - context.validate(); - - JwtTokenBuilder builder = new JwtTokenBuilder(workspace); - String token = builder.build(); - return imsApi.getJwtAccessToken(workspace.getApiKey(), context.getClientSecret(), token); } private AccessToken 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 deleted file mode 100644 index 1cb70c2a..00000000 --- a/ims/src/main/java/com/adobe/aio/ims/util/PrivateKeyBuilder.java +++ /dev/null @@ -1,50 +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.util; - -import java.security.PrivateKey; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; - -public class PrivateKeyBuilder { - - public static final String AIO_ENCODED_PKCS_8 = "aio_encoded_pkcs8"; - - private Map configMap; - private String encodedPkcs8Key; - - public PrivateKeyBuilder() { - } - - - public PrivateKeyBuilder encodedPkcs8Key(String encodedPkcs8Key) { - this.encodedPkcs8Key = encodedPkcs8Key; - return this; - } - - public PrivateKey build() { - if (!StringUtils.isEmpty(encodedPkcs8Key)) { - try { - return KeyStoreUtil.getPrivateKeyFromEncodedPkcs8(encodedPkcs8Key); - } catch (Exception e) { - throw new IllegalArgumentException( - "AIO Invalid encoded pkcs8 Private Key configuration. " - + "" + e.getMessage(), e); - } - } else { - return null; - } - } - - -} 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 55cd68c9..2a9c4147 100644 --- a/ims/src/main/java/com/adobe/aio/util/WorkspaceUtil.java +++ b/ims/src/main/java/com/adobe/aio/util/WorkspaceUtil.java @@ -12,19 +12,15 @@ 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 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.*; @@ -76,16 +72,8 @@ public static Workspace.Builder getWorkspaceBuilder(Map configMa 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(); - } + return getOAuthContextBuilder(configMap).build(); } public static OAuthContext.Builder getOAuthContextBuilder(Map configMap) { @@ -97,36 +85,6 @@ public static OAuthContext.Builder getOAuthContextBuilder(Map co 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); } diff --git a/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java b/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java deleted file mode 100644 index 4a91b29f..00000000 --- a/ims/src/test/java/com/adobe/aio/ims/JwtTokenBuilderTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.adobe.aio.ims; - -import java.security.KeyPair; -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.Jwt; -import io.jsonwebtoken.Jwts; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class JwtTokenBuilderTest { - - @Test - void wrongContext() { - class MockContext implements Context {} - Workspace workspace = Workspace.builder().authContext(new MockContext()).build(); - Exception ex = assertThrows(IllegalStateException.class, () -> new JwtTokenBuilder(workspace)); - assertEquals("AuthContext in workspace not of type `JwtContext`.", ex.getMessage()); - } - - @Test - void invalidJwtContext() { - Workspace workspace = Workspace.builder().authContext(JwtContext.builder().build()).build(); - assertThrows(IllegalStateException.class, () -> new JwtTokenBuilder(workspace)); - } - - @Test - void build() throws Exception{ - KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); - kpg.initialize(2048); - KeyPair kp = kpg.generateKeyPair(); - PrivateKey privateKey = kp.getPrivate(); - PublicKey publicKey = kp.getPublic(); - - 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 jwt = Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(actual); - - JwtContext jwtContext = (JwtContext) workspace.getAuthContext(); - Claims claims = jwt.getBody(); - assertEquals(workspace.getImsOrgId(), claims.getIssuer(), "Issuer specified."); - assertEquals(jwtContext.getTechnicalAccountId(), claims.getSubject(), "Subject specified."); - - String audience = workspace.getImsUrl() + "/c/" + workspace.getApiKey(); - assertEquals(audience, claims.getAudience(), "Subject specified."); - - // Scopes - for (String scope : jwtContext.getMetascopes()) { - assertTrue((Boolean) claims.get(workspace.getImsUrl() + scope)); - } - - assertNotNull(claims.getIssuedAt(), "Issued At Time specified."); - assertNotNull(claims.getExpiration(), "Expires Time specified."); - } -} 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 31a712a9..f0cc8948 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 @@ -40,10 +40,6 @@ public void getAccessToken() { assertNotNull(accessToken.getAccessToken()); 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 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 2c150f28..5b2f0c12 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 @@ -4,19 +4,15 @@ import java.util.Set; 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.JwtTokenBuilder; import com.adobe.aio.ims.model.AccessToken; import com.adobe.aio.util.Constants; import com.adobe.aio.workspace.Workspace; -import feign.FeignException; import org.junit.jupiter.api.BeforeEach; 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 org.mockserver.client.MockServerClient; import org.mockserver.junit.jupiter.MockServerExtension; @@ -46,7 +42,7 @@ void getInvalidAuthContext() { when(workspace.getAuthContext()).thenReturn(mock(Context.class)); ImsService service = new FeignImsService(workspace); Exception ex = assertThrows(IllegalStateException.class, service::getAccessToken); - assertEquals("AuthContext in workspace not of type `OAuthContext` or `JwtContext`.", ex.getMessage()); + assertEquals("AuthContext in workspace not of type `OAuthContext`.", ex.getMessage()); } @Test @@ -93,112 +89,4 @@ void getOAuthAccessToken(MockServerClient client) { } - @Test - void getJwtInvalidJwtAuthContext() { - Context context = JwtContext.builder().build(); - when(workspace.getAuthContext()).thenReturn(context); - ImsService service = new FeignImsService(workspace); - assertThrows(IllegalStateException.class, service::getAccessToken); - } - - @Test - void getJwtExchangeAccessTokenError(MockServerClient client) { - final String imsUrl = "http://localhost:" + client.getPort(); - final String apiKey = "API_KEY"; - final String clientSecret = "CLIENT_SECRET"; - final String jwtToken = "JWT_TOKEN_400"; - JwtContext context = mock(JwtContext.class); - 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( - request() - .withMethod("POST") - .withPath("/ims/exchange/jwt") - .withHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") - .withBody("client_id=API_KEY&client_secret=CLIENT_SECRET&jwt_token=JWT_TOKEN_400") - ).respond( - response().withStatusCode(HttpStatusCode.BAD_REQUEST_400.code()) - ); - - try (MockedConstruction ignored = mockConstruction(JwtTokenBuilder.class, - (mock, mockContext) -> { - // Have to tell the mocks to return the Desired JWT Token value. - when(mock.build()).thenReturn(jwtToken); - } - )) { - ImsService service = new FeignImsService(workspace); - assertThrows(FeignException.class, service::getAccessToken); - } - verify(context).validate(); - } - - @Test - void getJwtExchangeAccessTokenSuccess(MockServerClient client) { - final String imsUrl = "http://localhost:" + client.getPort(); - final String apiKey = "API_KEY"; - final String clientSecret = "CLIENT_SECRET"; - final String jwtToken = "JWT_TOKEN_200"; - JwtContext context = mock(JwtContext.class); - 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( - request() - .withMethod("POST") - .withPath("/ims/exchange/jwt") - .withHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") - .withBody("client_id=API_KEY&client_secret=CLIENT_SECRET&jwt_token=JWT_TOKEN_200") - ).respond( - response() - .withStatusCode(HttpStatusCode.OK_200.code()) - .withHeader("Content-Type", MediaType.APPLICATION_JSON.toString()) - .withBody("{ \"access_token\": \"ACCESS_TOKEN\", \"token_type\": \"bearer\", \"expires_in\": \"1000\" }") - ); - - try (MockedConstruction ignored = mockConstruction(JwtTokenBuilder.class, - (mock, mockContext) -> { - // Have to tell the mocks to return the Desired JWT Token value. - when(mock.build()).thenReturn(jwtToken); - } - )) { - ImsService service = new FeignImsService(workspace); - AccessToken token = service.getAccessToken(); - assertNotNull(token); - assertEquals("ACCESS_TOKEN", token.getAccessToken()); - } - verify(context).validate(); - } - - @Test - void validateJwtAccessToken(MockServerClient client) { - final String imsUrl = "http://localhost:" + client.getPort(); - final String apiKey = "API_KEY"; - final String accessToken = "ACCESS_TOKEN"; - client.when( - request() - .withMethod("POST") - .withPath("/ims/validate_token/v1") - .withHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") - .withBody("type=access_token&client_id=API_KEY&token=ACCESS_TOKEN") - ).respond( - response() - .withStatusCode(HttpStatusCode.OK_200.code()) - .withHeader("Content-Type", MediaType.APPLICATION_JSON.toString()) - .withBody("{ \"valid\": \"true\" }") - ); - JwtContext context = mock(JwtContext.class); - 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.validateJwtAccessToken(accessToken)); - } } diff --git a/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java b/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java index 08fa6e46..50e8261d 100644 --- a/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java +++ b/ims/src/test/java/com/adobe/aio/util/WorkspaceUtilTest.java @@ -11,50 +11,20 @@ */ 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(); diff --git a/ims/src/test/resources/workspace.jwt.properties b/ims/src/test/resources/workspace.jwt.properties deleted file mode 100644 index 8ecdf9c0..00000000 --- a/ims/src/test/resources/workspace.jwt.properties +++ /dev/null @@ -1,34 +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_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_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 -# 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_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_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 index 591df34d..a19c0ba4 100644 --- a/ims/src/test/resources/workspace.oauth.properties +++ b/ims/src/test/resources/workspace.oauth.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_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 = your Adobe Developer Console oauth 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 From 5b6f4f9003e7c627e43f14f187040925fe2428af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20Vintil=C4=83?= Date: Tue, 17 Jun 2025 00:03:34 +0300 Subject: [PATCH 3/3] CI-5972: Bump version to 3.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d6da3f34..b153ef2f 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ com.adobe.aio aio-lib-java - 2.0.3-SNAPSHOT + 3.0.0-SNAPSHOT pom