From 332564a85d9a2ba477e6508c81b3bc25122624c2 Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Wed, 21 Feb 2024 16:02:38 +0530 Subject: [PATCH 1/4] added a new fetchRegistryObjectByPSUT method to get the registry object usig psut Signed-off-by: Mohd Kaif Siddique --- .../service/SunbirdRCVCIssuancePlugin.java | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java index 0d83ea5..41ad381 100644 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.esignet.api.exception.VCIExchangeException; import io.mosip.esignet.api.util.ErrorConstants; +import io.mosip.esignet.sunbirdrc.integration.dto.RegistrySearchRequestDto; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; @@ -66,6 +67,10 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { private static final String CREDENTIAL_OBJECT_KEY = "credential"; + private final String FILTER_EQUALS_OPERATOR="eq"; + + private final String PSUT_TOKEN="psut"; + @Autowired Environment env; @@ -78,6 +83,12 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { @Value("${mosip.esignet.vciplugin.sunbird-rc.issue-credential-url}") String issueCredentialUrl; + @Value("${mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.registry-search-url}") + private String registrySearchUrl; + + @Value("${mosip.esignet.vciplugin.sunbird-rc.use-psut}") + private boolean usePsut; + @Value("#{'${mosip.esignet.vciplugin.sunbird-rc.supported-credential-types}'.split(',')}") List supportedCredentialTypes; @@ -135,13 +146,19 @@ public VCResult getVerifiableCredentialWithLinkedDataProof(VCReque Template template=credentialTypeTemplates.get(supportedType); validateContextUrl(template,contextList); } - String osid = (identityDetails.containsKey("sub")) ? (String) identityDetails.get("sub") : null; - if (osid == null) { - log.error("Invalid request: osid is null"); + + String registrySearchField = (identityDetails.containsKey("sub")) ? (String) identityDetails.get("sub") : null; + if (registrySearchField == null) { + log.error("Invalid request: registrySearchField is null"); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } - String registryUrl=credentialTypeConfigMap.get(requestedCredentialType).get(REGISTRY_GET_URL); - Map responseRegistryMap =fetchRegistryObject(registryUrl+osid); + Map responseRegistryMap; + if(usePsut){ + responseRegistryMap= fetchRegistryObjectByPSUT(registrySearchUrl,registrySearchField); + }else { + String registryUrl=credentialTypeConfigMap.get(requestedCredentialType).get(REGISTRY_GET_URL); + responseRegistryMap =fetchRegistryObject(registryUrl+ registrySearchField); + } Map credentialRequestMap = createCredentialIssueRequest(requestedCredentialType, responseRegistryMap,vcRequestDto,holderId); Map vcResponseMap =sendCredentialIssueRequest(credentialRequestMap); @@ -152,7 +169,6 @@ public VCResult getVerifiableCredentialWithLinkedDataProof(VCReque return vcResult; } - @Override public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { throw new VCIExchangeException(ErrorConstants.NOT_IMPLEMENTED); @@ -171,6 +187,40 @@ private Map fetchRegistryObject(String entityUrl) throws VCIExcha } } + private Map fetchRegistryObjectByPSUT(String registrySearchUrl, String psut) throws VCIExchangeException { + + RegistrySearchRequestDto registrySearchRequestDto=new RegistrySearchRequestDto(); + registrySearchRequestDto.setOffset(0); + registrySearchRequestDto.setLimit(2); + Map> filter=new HashMap<>(); + Map fullName=new HashMap<>(); + fullName.put(FILTER_EQUALS_OPERATOR,psut); + filter.put(PSUT_TOKEN,fullName); + registrySearchRequestDto.setFilters(filter); + + RequestEntity requestEntity =RequestEntity.post(UriComponentsBuilder.fromUriString(registrySearchUrl).build().toUri()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(registrySearchRequestDto); + + ResponseEntity>> responseEntity = restTemplate.exchange(requestEntity, + new ParameterizedTypeReference>>() {}); + if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) { + List> responseList = responseEntity.getBody(); + if(responseList.size()==1){ + //TODO This need to be removed since it can contain PII + log.debug("getting response {}", responseEntity); + return responseEntity.getBody().get(0); + }else{ + log.error("Registry search returns more than one match, so authentication is considered as failed. Result size: " + responseList.size()); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED ); + } + }else { + log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + + } + private Map createCredentialIssueRequest(String requestedCredentialType, Map registryObjectMap, VCRequestDto vcRequestDto, String holderId) throws VCIExchangeException { Template template=credentialTypeTemplates.get(requestedCredentialType); From 84fa01464c8280c1580f02f258c3b71b913ee29e Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Thu, 22 Feb 2024 17:24:32 +0530 Subject: [PATCH 2/4] review changes Signed-off-by: Mohd Kaif Siddique --- .../service/LoggerAuditService.java | 23 +++++++++++++ .../service/MockKeyBindingWrapperService.java | 34 +++++++++++++++++++ .../service/SunbirdRCVCIssuancePlugin.java | 23 +++++++------ 3 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java create mode 100644 sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java new file mode 100644 index 0000000..f376611 --- /dev/null +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java @@ -0,0 +1,23 @@ +package io.mosip.esignet.sunbirdrc.integration.service; + +import io.mosip.esignet.api.dto.AuditDTO; +import io.mosip.esignet.api.spi.AuditPlugin; +import io.mosip.esignet.api.util.Action; +import io.mosip.esignet.api.util.ActionStatus; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +@ConditionalOnProperty(value = "mosip.esignet.integration.audit-plugin", havingValue = "LoggerAuditService") +@Component +public class LoggerAuditService implements AuditPlugin { + + @Override + public void logAudit(Action action, ActionStatus status, AuditDTO audit, Throwable t) { + + } + + @Override + public void logAudit(String username, Action action, ActionStatus status, AuditDTO audit, Throwable t) { + + } +} diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java new file mode 100644 index 0000000..5cef23a --- /dev/null +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java @@ -0,0 +1,34 @@ +package io.mosip.esignet.sunbirdrc.integration.service; + +import io.mosip.esignet.api.dto.AuthChallenge; +import io.mosip.esignet.api.dto.KeyBindingResult; +import io.mosip.esignet.api.dto.SendOtpResult; +import io.mosip.esignet.api.exception.KeyBindingException; +import io.mosip.esignet.api.exception.SendOtpException; +import io.mosip.esignet.api.spi.KeyBinder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@ConditionalOnProperty(value = "mosip.esignet.integration.key-binder", havingValue = "MockKeyBindingWrapperService") +@Component +public class MockKeyBindingWrapperService implements KeyBinder { + + + @Override + public SendOtpResult sendBindingOtp(String individualId, List otpChannels, Map requestHeaders) throws SendOtpException { + return null; + } + + @Override + public KeyBindingResult doKeyBinding(String individualId, List challengeList, Map publicKeyJWK, String bindAuthFactorType, Map requestHeaders) throws KeyBindingException { + return null; + } + + @Override + public List getSupportedChallengeFormats(String authFactorType) { + return null; + } +} diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java index 41ad381..081a6cf 100644 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -83,11 +83,11 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { @Value("${mosip.esignet.vciplugin.sunbird-rc.issue-credential-url}") String issueCredentialUrl; - @Value("${mosip.esignet.authenticator.sunbird-rc.auth-factor.kba.registry-search-url}") + @Value("${mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-search-url}") private String registrySearchUrl; - @Value("${mosip.esignet.vciplugin.sunbird-rc.use-psut}") - private boolean usePsut; + @Value("${mosip.esignet.vciplugin.sunbird-rc.enable-psut-based-registry-search:false}") + private boolean enablePSUTBasedRegistrySearch; @Value("#{'${mosip.esignet.vciplugin.sunbird-rc.supported-credential-types}'.split(',')}") List supportedCredentialTypes; @@ -153,7 +153,7 @@ public VCResult getVerifiableCredentialWithLinkedDataProof(VCReque throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } Map responseRegistryMap; - if(usePsut){ + if(enablePSUTBasedRegistrySearch){ responseRegistryMap= fetchRegistryObjectByPSUT(registrySearchUrl,registrySearchField); }else { String registryUrl=credentialTypeConfigMap.get(requestedCredentialType).get(REGISTRY_GET_URL); @@ -187,15 +187,15 @@ private Map fetchRegistryObject(String entityUrl) throws VCIExcha } } - private Map fetchRegistryObjectByPSUT(String registrySearchUrl, String psut) throws VCIExchangeException { + private Map fetchRegistryObjectByPSUT(String registrySearchUrl, String psuToken) throws VCIExchangeException { RegistrySearchRequestDto registrySearchRequestDto=new RegistrySearchRequestDto(); registrySearchRequestDto.setOffset(0); registrySearchRequestDto.setLimit(2); Map> filter=new HashMap<>(); - Map fullName=new HashMap<>(); - fullName.put(FILTER_EQUALS_OPERATOR,psut); - filter.put(PSUT_TOKEN,fullName); + Map psut=new HashMap<>(); + psut.put(FILTER_EQUALS_OPERATOR,psuToken); + filter.put(PSUT_TOKEN,psut); registrySearchRequestDto.setFilters(filter); RequestEntity requestEntity =RequestEntity.post(UriComponentsBuilder.fromUriString(registrySearchUrl).build().toUri()) @@ -209,11 +209,12 @@ private Map fetchRegistryObjectByPSUT(String registrySearchUrl, if(responseList.size()==1){ //TODO This need to be removed since it can contain PII log.debug("getting response {}", responseEntity); - return responseEntity.getBody().get(0); }else{ - log.error("Registry search returns more than one match, so authentication is considered as failed. Result size: " + responseList.size()); - throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED ); + log.debug("Registry search returns more than one match,So taking the first. Result size: " + responseList.size()); + log.debug("getting response {}", responseEntity); + //Todo we should find a generic way to sort desc based on created date. The idea is we give out the most recent record as VC } + return responseList.get(0); }else { log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); From da293c3c9e974190f3a7477a9aa38e1966d56f91 Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Thu, 22 Feb 2024 17:31:06 +0530 Subject: [PATCH 3/4] removed unwanted file Signed-off-by: Mohd Kaif Siddique --- .../service/LoggerAuditService.java | 23 ------------- .../service/MockKeyBindingWrapperService.java | 34 ------------------- 2 files changed, 57 deletions(-) delete mode 100644 sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java delete mode 100644 sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java deleted file mode 100644 index f376611..0000000 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/LoggerAuditService.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.mosip.esignet.sunbirdrc.integration.service; - -import io.mosip.esignet.api.dto.AuditDTO; -import io.mosip.esignet.api.spi.AuditPlugin; -import io.mosip.esignet.api.util.Action; -import io.mosip.esignet.api.util.ActionStatus; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; - -@ConditionalOnProperty(value = "mosip.esignet.integration.audit-plugin", havingValue = "LoggerAuditService") -@Component -public class LoggerAuditService implements AuditPlugin { - - @Override - public void logAudit(Action action, ActionStatus status, AuditDTO audit, Throwable t) { - - } - - @Override - public void logAudit(String username, Action action, ActionStatus status, AuditDTO audit, Throwable t) { - - } -} diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java deleted file mode 100644 index 5cef23a..0000000 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockKeyBindingWrapperService.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.mosip.esignet.sunbirdrc.integration.service; - -import io.mosip.esignet.api.dto.AuthChallenge; -import io.mosip.esignet.api.dto.KeyBindingResult; -import io.mosip.esignet.api.dto.SendOtpResult; -import io.mosip.esignet.api.exception.KeyBindingException; -import io.mosip.esignet.api.exception.SendOtpException; -import io.mosip.esignet.api.spi.KeyBinder; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -@ConditionalOnProperty(value = "mosip.esignet.integration.key-binder", havingValue = "MockKeyBindingWrapperService") -@Component -public class MockKeyBindingWrapperService implements KeyBinder { - - - @Override - public SendOtpResult sendBindingOtp(String individualId, List otpChannels, Map requestHeaders) throws SendOtpException { - return null; - } - - @Override - public KeyBindingResult doKeyBinding(String individualId, List challengeList, Map publicKeyJWK, String bindAuthFactorType, Map requestHeaders) throws KeyBindingException { - return null; - } - - @Override - public List getSupportedChallengeFormats(String authFactorType) { - return null; - } -} From 5f3efccbbef245a0c39b7093068597fc8cd663a5 Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Fri, 23 Feb 2024 11:12:37 +0530 Subject: [PATCH 4/4] review changes Signed-off-by: Mohd Kaif Siddique --- .../service/SunbirdRCVCIssuancePlugin.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java index 081a6cf..e7dcf14 100644 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -59,6 +59,8 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { private static final String REGISTRY_GET_URL = "registry-get-url"; + private static final String REGISTRY_SEARCH_URL= "registry-search-url"; + private static final String CRED_SCHEMA_ID = "cred-schema-id"; private static final String CRED_SCHEMA_VESRION = "cred-schema-version"; @@ -83,9 +85,6 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { @Value("${mosip.esignet.vciplugin.sunbird-rc.issue-credential-url}") String issueCredentialUrl; - @Value("${mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-search-url}") - private String registrySearchUrl; - @Value("${mosip.esignet.vciplugin.sunbird-rc.enable-psut-based-registry-search:false}") private boolean enablePSUTBasedRegistrySearch; @@ -154,6 +153,7 @@ public VCResult getVerifiableCredentialWithLinkedDataProof(VCReque } Map responseRegistryMap; if(enablePSUTBasedRegistrySearch){ + String registrySearchUrl=credentialTypeConfigMap.get(requestedCredentialType).get(REGISTRY_SEARCH_URL); responseRegistryMap= fetchRegistryObjectByPSUT(registrySearchUrl,registrySearchField); }else { String registryUrl=credentialTypeConfigMap.get(requestedCredentialType).get(REGISTRY_GET_URL); @@ -187,15 +187,15 @@ private Map fetchRegistryObject(String entityUrl) throws VCIExcha } } - private Map fetchRegistryObjectByPSUT(String registrySearchUrl, String psuToken) throws VCIExchangeException { + private Map fetchRegistryObjectByPSUT(String registrySearchUrl, String psut) throws VCIExchangeException { RegistrySearchRequestDto registrySearchRequestDto=new RegistrySearchRequestDto(); registrySearchRequestDto.setOffset(0); registrySearchRequestDto.setLimit(2); Map> filter=new HashMap<>(); - Map psut=new HashMap<>(); - psut.put(FILTER_EQUALS_OPERATOR,psuToken); - filter.put(PSUT_TOKEN,psut); + Map psutFilter=new HashMap<>(); + psutFilter.put(FILTER_EQUALS_OPERATOR,psut); + filter.put(PSUT_TOKEN,psutFilter); registrySearchRequestDto.setFilters(filter); RequestEntity requestEntity =RequestEntity.post(UriComponentsBuilder.fromUriString(registrySearchUrl).build().toUri()) @@ -288,6 +288,7 @@ private void validateAndCachePropertiesForCredentialType(String credentialType) validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + CRED_SCHEMA_ID,CRED_SCHEMA_ID,configMap); validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + CRED_SCHEMA_VESRION,CRED_SCHEMA_VESRION,configMap); validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + STATIC_VALUE_MAP_ISSUER_ID,STATIC_VALUE_MAP_ISSUER_ID,configMap); + validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + REGISTRY_SEARCH_URL,REGISTRY_SEARCH_URL,configMap); String templateUrl = env.getProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX +"." + credentialType + "." + TEMPLATE_URL); validateAndCacheTemplate(templateUrl,credentialType);