Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sdk): added support of buyer tokens with different environments #58

Merged
merged 20 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
58ee049
added support of buyer tokens with different environments
xuelianhan007 Nov 1, 2024
9527103
removed null checking in BuyerCheckerService.java
xuelianhan007 Nov 1, 2024
07ef2c0
added unit tests
xuelianhan007 Nov 4, 2024
09a5f12
deleted duplicated lines
xuelianhan007 Nov 4, 2024
bc9cdf1
fix spelling error
xuelianhan007 Nov 4, 2024
acb23ef
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 4, 2024
06a7a05
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 4, 2024
ec7cabb
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 5, 2024
cc62bcd
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 5, 2024
6d0b79b
resolve conflicts
xuelianhan007 Nov 5, 2024
ce960d8
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 5, 2024
3372c8e
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 5, 2024
e62b6a0
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 6, 2024
584c79a
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 6, 2024
cd39492
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 6, 2024
780f148
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 6, 2024
3018a26
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 6, 2024
b337cbd
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 7, 2024
50224ac
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 7, 2024
b7ba70f
Merge branch 'main' of github.com:mycloudnexus/kraken into fix/fix-bu…
xuelianhan007 Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ spec:
- classpath:/mef-sonata/api-specs/api-spec.quote.yaml
- classpath:/mef-sonata/api-specs/api-spec.product.offering.yaml
- classpath:/mef-sonata/api-targets/api-target.order.uni.add.yaml
- classpath:/mef-sonata/api-targets/api-target.order.eline.add.yam
- classpath:/mef-sonata/api-targets/api-target.order.uni.add.yaml
- classpath:/mef-sonata/api-targets/api-target.order.eline.add.yaml
- classpath:/mef-sonata/api-targets/api-target.order.uni.read.yaml
- classpath:/mef-sonata/api-targets/api-target.order.eline.read.yaml
Expand All @@ -37,15 +35,12 @@ spec:
- classpath:/mef-sonata/api-targets/api-target.product.offering.uni.read.yaml
- classpath:/mef-sonata/api-targets/api-target.product.offering.eline.read.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.uni.add.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.eline.add.yam
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.uni.add.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.eline.add.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.uni.read.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.eline.read.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.uni.delete.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.order.eline.delete.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.quote.eline.add.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.quote.eline.add.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.quote.uni.add.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.quote.uni.read.yaml
- classpath:/mef-sonata/api-targets-mappers/api-target-mapper.quote.eline.read.yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ public OAuth2TokenValidatorResult validate(Jwt token) {
return OAuth2TokenValidatorResult.failure(error);
}
}
return null;
return OAuth2TokenValidatorResult.success();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.consoleconnect.kraken.operator.auth;

import com.consoleconnect.kraken.operator.auth.security.JwtTokenVerifier;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;

class JwtTokenVerifierTest {

private static final String RS512_SIGNED_JWT =
"eyJhbGciOiJSUzUxMiJ9.eyJzdWIiOiJ0ZXN0LXN1YmplY3QiLCJleHAiOjE5NzQzMjYxMTl9.LKAx-60EBfD7jC1jb1eKcjO4uLvf3ssISV-8tN-qp7gAjSvKvj4YA9-V2mIb6jcS1X_xGmNy6EIimZXpWaBR3nJmeu-jpe85u4WaW2Ztr8ecAi-dTO7ZozwdtljKuBKKvj4u1nF70zyCNl15AozSG0W1ASrjUuWrJtfyDG6WoZ8VfNMuhtU-xUYUFvscmeZKUYQcJ1KS-oV5tHeF8aNiwQoiPC_9KXCOZtNEJFdq6-uzFdHxvOP2yex5Gbmg5hXonauIFXG2ZPPGdXzm-5xkhBpgM8U7A_6wb3So8wBvLYYm2245QUump63AJRAy8tQpwt4n9MvQxQgS3z9R-NK92A";

private static final String VERIFY_KEY =
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq4yKxb6SNePdDmQi9xFCrP6QvHosErQzryknQTTTffs0t3cy3Er3lIceuhZ7yQNSCDfPFqG8GoyoKhuChRiA5D+J2ab7bqTa1QJKfnCyERoscftgN2fXPHjHoiKbpGV2tMVw8mXl//tePOAiKbMJaBUnlAvJgkk1rVm08dSwpLC1sr2M19euf9jwnRGkMRZuhp9iCPgECRke5T8Ixpv0uQjSmGHnWUKTFlbj8sM83suROR1Ue64JSGScANc5vk3huJ/J97qTC+K2oKj6L8d9O8dpc4obijEOJwpydNvTYDgbiivYeSB00KS9jlBkQ5B2QqLvLVEygDl3dp59nGx6YQIDAQAB";

private static KeyFactory kf;

@BeforeAll
public static void keyFactory() throws NoSuchAlgorithmException {
kf = KeyFactory.getInstance("RSA");
}

@Test
void givenEmptyClaims_whenValidate_thenReturnSuccess() {
JwtTokenVerifier verifier = new JwtTokenVerifier(new HashMap<>());
Jwt token = Mockito.mock(Jwt.class);
OAuth2TokenValidatorResult result = verifier.validate(token);
Assertions.assertTrue(result.getErrors().isEmpty());
}

@SneakyThrows
@Test
void givenNonEmptyClaims_whenValidate_thenReturnErrors() {
NimbusJwtDecoder decoder =
NimbusJwtDecoder.withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build();
Jwt token = decoder.decode(RS512_SIGNED_JWT);

Map<String, Object> claims = new HashMap<>();
claims.put("subject", "test-subject");
JwtTokenVerifier verifier = new JwtTokenVerifier(claims);
OAuth2TokenValidatorResult result = verifier.validate(token);
Assertions.assertFalse(result.getErrors().isEmpty());
}

@SneakyThrows
@Test
void givenNonEmptyClaims_whenValidate_thenReturnSuccess() {
NimbusJwtDecoder decoder =
NimbusJwtDecoder.withPublicKey(key()).signatureAlgorithm(SignatureAlgorithm.RS512).build();
Jwt token = decoder.decode(RS512_SIGNED_JWT);

Map<String, Object> claims = new HashMap<>();
claims.put("sub", "test-subject");
JwtTokenVerifier verifier = new JwtTokenVerifier(claims);
OAuth2TokenValidatorResult result = verifier.validate(token);
Assertions.assertTrue(result.getErrors().isEmpty());
}

private RSAPublicKey key() throws InvalidKeySpecException {
byte[] decoded = Base64.getDecoder().decode(VERIFY_KEY.getBytes());
EncodedKeySpec spec = new X509EncodedKeySpec(decoded);
return (RSAPublicKey) kf.generatePublic(spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.consoleconnect.kraken.operator.controller.dto.BuyerAssetDto;
import com.consoleconnect.kraken.operator.controller.dto.CreateBuyerRequest;
import com.consoleconnect.kraken.operator.controller.mapper.BuyerAssetDtoMapper;
import com.consoleconnect.kraken.operator.controller.model.Environment;
import com.consoleconnect.kraken.operator.controller.model.MgmtProperty;
import com.consoleconnect.kraken.operator.core.dto.UnifiedAssetDto;
import com.consoleconnect.kraken.operator.core.entity.UnifiedAssetEntity;
Expand All @@ -25,6 +26,7 @@
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import lombok.AllArgsConstructor;
Expand All @@ -50,6 +52,7 @@ public class BuyerService extends AssetStatusManager {
private final UnifiedAssetRepository unifiedAssetRepository;
private final AuthDataProperty.AuthServer authServer;
private final MgmtProperty appProperty;
private final EnvironmentService environmentService;

@Transactional
public BuyerAssetDto create(String productId, CreateBuyerRequest buyerOnboard, String createdBy) {
Expand Down Expand Up @@ -142,23 +145,33 @@ public BuyerAssetDto regenerate(
private BuyerAssetDto generateBuyer(
UnifiedAssetDto unifiedAssetDto, String buyerId, Long tokenExpiredInSeconds) {
BuyerAssetDto buyerAssetDto = BuyerAssetDtoMapper.INSTANCE.toBuyerAssetDto(unifiedAssetDto);
BuyerAssetDto.BuyerToken buyerToken = generateBuyerToken(buyerId, tokenExpiredInSeconds);
Map<String, String> labels = buyerAssetDto.getMetadata().getLabels();
String envId = (labels == null ? "" : labels.getOrDefault(LABEL_ENV_ID, ""));
BuyerAssetDto.BuyerToken buyerToken = generateBuyerToken(buyerId, tokenExpiredInSeconds, envId);

buyerAssetDto.setBuyerToken(buyerToken);
return buyerAssetDto;
}

private BuyerAssetDto.BuyerToken generateBuyerToken(String buyerId, Long tokenExpiredInSeconds) {
private BuyerAssetDto.BuyerToken generateBuyerToken(
String buyerId, Long tokenExpiredInSeconds, String envId) {
if (null == tokenExpiredInSeconds || tokenExpiredInSeconds <= 0) {
tokenExpiredInSeconds =
appProperty.getBuyerTokenExpiredSeconds() == null
? Long.valueOf(MgmtProperty.DEFAULT_TOKEN_EXPIRED_SECONDS)
: Long.valueOf(appProperty.getBuyerTokenExpiredSeconds());
}
BuyerAssetDto.BuyerToken buyerToken = new BuyerAssetDto.BuyerToken();
Map<String, Object> claims = new HashMap<>();
if (StringUtils.isNotBlank(envId)) {
Environment environment = environmentService.findOne(envId);
log.info("generateBuyerToken, envId:{}, envName:{}", envId, environment.getName());
claims.put("env", environment.getName());
}
if (authServer.isEnabled()) {
String token =
JwtEncoderToolkit.get(authServer.getJwt())
.generateToken(buyerId, null, tokenExpiredInSeconds);
.generateToken(buyerId, claims, tokenExpiredInSeconds);
buyerToken.setExpiredAt(
Date.from(ZonedDateTime.now().plusSeconds(tokenExpiredInSeconds).toInstant()));
buyerToken.setAccessToken(token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.consoleconnect.kraken.operator.config.TestApplication;
import com.consoleconnect.kraken.operator.controller.dto.BuyerAssetDto;
import com.consoleconnect.kraken.operator.controller.dto.CreateBuyerRequest;
import com.consoleconnect.kraken.operator.controller.model.Environment;
import com.consoleconnect.kraken.operator.controller.service.EnvironmentService;
import com.consoleconnect.kraken.operator.core.dto.Tuple2;
import com.consoleconnect.kraken.operator.core.dto.UnifiedAssetDto;
import com.consoleconnect.kraken.operator.core.enums.AssetKindEnum;
Expand All @@ -18,6 +20,7 @@
import com.consoleconnect.kraken.operator.test.AbstractIntegrationTest;
import com.consoleconnect.kraken.operator.test.MockIntegrationTest;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.MethodOrderer;
Expand All @@ -36,13 +39,14 @@
@ContextConfiguration(classes = {TestApplication.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@ActiveProfiles("test-rs256")
class BuyerControllerTest extends AbstractIntegrationTest {
class BuyerControllerTest extends AbstractIntegrationTest implements EnvCreator {
private static final String PRODUCT_ID = "product.mef.sonata.api";
public static final String BASE_URL = String.format("/products/%s/buyers", PRODUCT_ID);
public static final String BUYER_ID = "consolecore-poping-company";

private final WebTestClientHelper webTestClient;
@Autowired private UnifiedAssetService unifiedAssetService;
@Getter @Autowired EnvironmentService environmentService;

@Autowired
public BuyerControllerTest(WebTestClient webTestClient) {
Expand All @@ -52,9 +56,10 @@ public BuyerControllerTest(WebTestClient webTestClient) {
@Test
@Order(2)
void givenBuyer_whenCreate_thenOK() {
Environment envStage = createStage(PRODUCT_ID);
CreateBuyerRequest requestEntity = new CreateBuyerRequest();
requestEntity.setBuyerId(BUYER_ID);
requestEntity.setEnvId("stage");
requestEntity.setEnvId(envStage.getId());
requestEntity.setCompanyName("console connect");

String resp =
Expand Down Expand Up @@ -107,7 +112,8 @@ void givenBuyer_whenSearch_thenOK() {
void givenDuplicatedBuyer_whenCreate_thenNot200() {
CreateBuyerRequest requestEntity = new CreateBuyerRequest();
requestEntity.setBuyerId(BUYER_ID);
requestEntity.setEnvId("stage");
Environment envStage = createStage(PRODUCT_ID);
requestEntity.setEnvId(envStage.getId());
requestEntity.setCompanyName("console connect");

webTestClient.requestAndVerify(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,4 @@ links:
group: mef.sonata.api-target.address.validate
- targetAssetKey: mef.sonata.api-target-mapper.address.retrieve
relationship: implementation.target-mapper
group: mef.sonata.api-target.address.retrieve



group: mef.sonata.api-target.address.retrieve
Loading