diff --git a/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java b/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java index 500fb41..a5c9084 100644 --- a/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java +++ b/mock-certify-plugin/src/main/java/io.mosip.certify.mock.integration/service/MDocMockVCIssuancePlugin.java @@ -7,61 +7,21 @@ import io.mosip.certify.api.spi.VCIssuancePlugin; import io.mosip.certify.api.util.ErrorConstants; import io.mosip.certify.constants.VCFormats; -import io.mosip.certify.core.exception.CertifyException; import io.mosip.certify.mock.integration.mocks.MdocGenerator; -import io.mosip.esignet.core.dto.OIDCTransaction; -import io.mosip.kernel.core.keymanager.spi.KeyStore; -import io.mosip.kernel.keymanagerservice.constant.KeymanagerConstant; -import io.mosip.kernel.keymanagerservice.entity.KeyAlias; -import io.mosip.kernel.keymanagerservice.helper.KeymanagerDBHelper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cache.CacheManager; import org.springframework.stereotype.Component; -import javax.crypto.Cipher; -import java.security.Key; -import java.time.LocalDateTime; -import java.time.ZoneOffset; import java.util.*; @ConditionalOnProperty(value = "mosip.certify.integration.vci-plugin", havingValue = "MDocMockVCIssuancePlugin") @Component @Slf4j public class MDocMockVCIssuancePlugin implements VCIssuancePlugin { - private static final String AES_CIPHER_FAILED = "aes_cipher_failed"; - private static final String NO_UNIQUE_ALIAS = "no_unique_alias"; - private static final String USERINFO_CACHE = "userinfo"; - - @Autowired - private CacheManager cacheManager; - - @Autowired - private KeyStore keyStore; - - @Autowired - private KeymanagerDBHelper dbHelper; - - @Value("${mosip.certify.cache.security.secretkey.reference-id}") - private String cacheSecretKeyRefId; - - @Value("${mosip.certify.cache.security.algorithm-name}") - private String aesECBTransformation; - - @Value("${mosip.certify.cache.secure.individual-id}") - private boolean secureIndividualId; - - @Value("${mosip.certify.cache.store.individual-id}") - private boolean storeIndividualId; - @Value("${mosip.certify.mock.vciplugin.mdoc.issuer-key-cert:empty}") private String issuerKeyAndCertificate = null; - - private static final String ACCESS_TOKEN_HASH = "accessTokenHash"; - - public static final String CERTIFY_SERVICE_APP_ID = "CERTIFY_SERVICE"; @Autowired private MdocGenerator mdocGenerator; @@ -74,10 +34,13 @@ public VCResult getVerifiableCredentialWithLinkedDataProof(VCReque @Override public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { - String accessTokenHash = identityDetails.get(ACCESS_TOKEN_HASH).toString(); String documentNumber; try { - documentNumber = getIndividualId(getUserInfoTransaction(accessTokenHash)); + if(identityDetails.get("sub") == null){ + log.error("sub field is missing in identityDetails claims. Check the access token or auth configurations."); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + documentNumber = (String) identityDetails.get("sub"); } catch (Exception e) { log.error("Error getting documentNumber", e); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); @@ -113,47 +76,4 @@ private Map mockDataForMsoMdoc(String documentNumber) { }}); return data; } - - /** - * TODO: This function getIndividualId is duplicated with Other VCIPlugin class and can be moved to commons - */ - protected String getIndividualId(OIDCTransaction transaction) { - if(!storeIndividualId) - return null; - return secureIndividualId ? decryptIndividualId(transaction.getIndividualId()) : transaction.getIndividualId(); - } - - private String decryptIndividualId(String encryptedIndividualId) { - try { - Cipher cipher = Cipher.getInstance(aesECBTransformation); - byte[] decodedBytes = Base64.getUrlDecoder().decode(encryptedIndividualId); - cipher.init(Cipher.DECRYPT_MODE, getSecretKeyFromHSM()); - return new String(cipher.doFinal(decodedBytes, 0, decodedBytes.length)); - } catch(Exception e) { - log.error("Error Cipher Operations of provided secret data.", e); - throw new CertifyException(AES_CIPHER_FAILED); - } - } - - private OIDCTransaction getUserInfoTransaction(String accessTokenHash) { - return cacheManager.getCache(USERINFO_CACHE).get(accessTokenHash, OIDCTransaction.class); - } - - private Key getSecretKeyFromHSM() { - String keyAlias = getKeyAlias(CERTIFY_SERVICE_APP_ID, cacheSecretKeyRefId); - if (Objects.nonNull(keyAlias)) { - return keyStore.getSymmetricKey(keyAlias); - } - throw new CertifyException(NO_UNIQUE_ALIAS); - } - - private String getKeyAlias(String keyAppId, String keyRefId) { - Map> keyAliasMap = dbHelper.getKeyAliases(keyAppId, keyRefId, LocalDateTime.now(ZoneOffset.UTC)); - List currentKeyAliases = keyAliasMap.get(KeymanagerConstant.CURRENTKEYALIAS); - if (!currentKeyAliases.isEmpty() && currentKeyAliases.size() == 1) { - return currentKeyAliases.getFirst().getAlias(); - } - log.error("CurrentKeyAlias is not unique. KeyAlias count: {}", currentKeyAliases.size()); - throw new CertifyException(NO_UNIQUE_ALIAS); - } } diff --git a/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java b/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java index 31f29d5..a54c94a 100644 --- a/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java +++ b/mock-certify-plugin/src/test/java/io/mosip/certify/mock/integration/service/MDocMockVCIssuancePluginTest.java @@ -4,22 +4,13 @@ import io.mosip.certify.api.dto.VCResult; import io.mosip.certify.api.exception.VCIExchangeException; import io.mosip.certify.constants.VCFormats; -import io.mosip.certify.core.exception.CertifyException; import io.mosip.certify.mock.integration.mocks.MdocGenerator; -import io.mosip.esignet.core.dto.OIDCTransaction; -import io.mosip.kernel.core.keymanager.spi.KeyStore; -import io.mosip.kernel.keymanagerservice.entity.KeyAlias; -import io.mosip.kernel.keymanagerservice.helper.KeymanagerDBHelper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.*; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; import org.springframework.test.util.ReflectionTestUtils; -import java.security.Key; -import java.time.LocalDateTime; import java.util.*; import static org.junit.Assert.*; @@ -31,26 +22,12 @@ public class MDocMockVCIssuancePluginTest { @InjectMocks private MDocMockVCIssuancePlugin plugin; - @Mock - private CacheManager cacheManager; - @Mock - private KeyStore keyStore; - @Mock - private KeymanagerDBHelper dbHelper; - @Mock - private Cache cache; - @Mock - private Key key; @Mock private MdocGenerator mdocGenerator; @Before public void setUp() { ReflectionTestUtils.setField(plugin, "issuerKeyAndCertificate", "empty"); - ReflectionTestUtils.setField(plugin, "cacheSecretKeyRefId", "refId"); - ReflectionTestUtils.setField(plugin, "aesECBTransformation", "AES/ECB/PKCS5Padding"); - ReflectionTestUtils.setField(plugin, "storeIndividualId", true); - ReflectionTestUtils.setField(plugin, "secureIndividualId", false); } @Test @@ -58,92 +35,44 @@ public void testGetVerifiableCredential_Success() throws Exception { VCRequestDto dto = mock(VCRequestDto.class); when(dto.getFormat()).thenReturn(VCFormats.MSO_MDOC); + // identityDetails must contain "sub" because implementation casts it to String Map identityDetails = new HashMap<>(); + identityDetails.put("sub", "12345"); identityDetails.put("accessTokenHash", "tokenHash"); - OIDCTransaction transaction = mock(OIDCTransaction.class); - when(transaction.getIndividualId()).thenReturn("docNum"); - - when(cacheManager.getCache(anyString())).thenReturn(cache); - when(cache.get(anyString(), eq(OIDCTransaction.class))).thenReturn(transaction); - - when(mdocGenerator.generate(anyMap(), anyString(), anyString())).thenReturn("mockedMdoc"); + when(mdocGenerator.generate(anyMap(), anyString(), anyString())) + .thenReturn("mockedMdoc"); VCResult result = plugin.getVerifiableCredential(dto, "holderId", identityDetails); assertNotNull(result); + // Ensure we compare like types; adjust if VCFormats.MSO_MDOC is not a String assertEquals(VCFormats.MSO_MDOC, result.getFormat()); assertEquals("mockedMdoc", result.getCredential()); } + @Test(expected = VCIExchangeException.class) public void testGetVerifiableCredential_NotImplemented() throws Exception { VCRequestDto dto = mock(VCRequestDto.class); + // Use a format that MDocMockVCIssuancePlugin does not implement + when(dto.getFormat()).thenReturn(VCFormats.LDP_VC); // or any other unsupported format + Map identityDetails = new HashMap<>(); identityDetails.put("accessTokenHash", "tokenHash"); + identityDetails.put("sub", "12345"); plugin.getVerifiableCredential(dto, "holderId", identityDetails); } + @Test(expected = VCIExchangeException.class) public void testGetVerifiableCredentialWithLinkedDataProof_NotImplemented() throws Exception { VCRequestDto dto = mock(VCRequestDto.class); plugin.getVerifiableCredentialWithLinkedDataProof(dto, "holderId", new HashMap<>()); } - @Test - public void testGetIndividualId_SecureFalse() { - OIDCTransaction transaction = mock(OIDCTransaction.class); - when(transaction.getIndividualId()).thenReturn("docNum"); - ReflectionTestUtils.setField(plugin, "secureIndividualId", false); - ReflectionTestUtils.setField(plugin, "storeIndividualId", true); - String result = (String) ReflectionTestUtils.invokeMethod(plugin, "getIndividualId", transaction); - assertEquals("docNum", result); - } - - @Test - public void testGetIndividualId_StoreFalse() { - OIDCTransaction transaction = mock(OIDCTransaction.class); - ReflectionTestUtils.setField(plugin, "storeIndividualId", false); - String result = (String) ReflectionTestUtils.invokeMethod(plugin, "getIndividualId", transaction); - assertNull(result); - } - - @Test(expected = CertifyException.class) - public void testDecryptIndividualId_Exception() { - ReflectionTestUtils.setField(plugin, "aesECBTransformation", "invalid"); - ReflectionTestUtils.invokeMethod(plugin, "decryptIndividualId", "invalid"); - } - - @Test(expected = CertifyException.class) - public void testGetSecretKeyFromHSM_NoAlias() { - when(dbHelper.getKeyAliases(anyString(), anyString(), any(LocalDateTime.class))) - .thenReturn(Collections.singletonMap("currentKeyAlias", new ArrayList<>())); - ReflectionTestUtils.invokeMethod(plugin, "getSecretKeyFromHSM"); - } - - @Test - public void testGetKeyAlias_Success() { - KeyAlias alias = mock(KeyAlias.class); - when(alias.getAlias()).thenReturn("alias"); - List aliases = Collections.singletonList(alias); - Map> map = new HashMap<>(); - map.put("currentKeyAlias", aliases); - when(dbHelper.getKeyAliases(anyString(), anyString(), any(LocalDateTime.class))).thenReturn(map); - String result = (String) ReflectionTestUtils.invokeMethod(plugin, "getKeyAlias", "appId", "refId"); - assertEquals("alias", result); - } - - @Test(expected = CertifyException.class) - public void testGetKeyAlias_NotUnique() { - List aliases = Arrays.asList(mock(KeyAlias.class), mock(KeyAlias.class)); - Map> map = new HashMap<>(); - map.put("currentKeyAlias", aliases); - when(dbHelper.getKeyAliases(anyString(), anyString(), any(LocalDateTime.class))).thenReturn(map); - ReflectionTestUtils.invokeMethod(plugin, "getKeyAlias", "appId", "refId"); - } - @Test public void testMockDataForMsoMdoc() { String docNum = "12345"; @@ -158,16 +87,4 @@ public void testMockDataForMsoMdoc() { assertTrue(data.get("driving_privileges") instanceof Map); assertEquals("A", ((Map) data.get("driving_privileges")).get("vehicle_category_code")); } - - @Test - public void testGetUserInfoTransaction() { - String accessTokenHash = "tokenHash"; - OIDCTransaction transaction = mock(OIDCTransaction.class); - when(cacheManager.getCache(anyString())).thenReturn(cache); - when(cache.get(eq(accessTokenHash), eq(OIDCTransaction.class))).thenReturn(transaction); - - OIDCTransaction result = (OIDCTransaction) ReflectionTestUtils.invokeMethod(plugin, "getUserInfoTransaction", accessTokenHash); - assertNotNull(result); - assertEquals(transaction, result); - } } \ No newline at end of file