diff --git a/sunbird-rc-plugin/README.md b/sunbird-rc-plugin/README.md new file mode 100644 index 0000000..eb7761a --- /dev/null +++ b/sunbird-rc-plugin/README.md @@ -0,0 +1,47 @@ +# sunbird-rc-plugin + +## About +Implementation for all the interfaces defined in esignet-integration-api. This libaray is built as a wrapper for [sunbird-registry-system](sunbird-registry-url) service. + +This library should be added as a runtime dependency to [esignet-service](https://github.com/mosip/esignet) + +## Configurations required to added in esignet-default.properties + +```` +mosip.esignet.integration.scan-base-package=io.mosip.esignet.plugin.sunbirdrc +mosip.esignet.integration.authenticator=SunbirdRCAuthenticationService +mosip.esignet.integration.vci-plugin=SunbirdRCVCIssuancePlugin + + + +##--------------------sunbird registry authentication related demo configuration-------------------------## + +mosip.esignet.authenticator.sunbird-rc.auth-factor.kbi.individual-id-field='policyNumber' +mosip.esignet.authenticator.sunbird-rc.auth-factor.kbi.field-details={{"id":"policyNumber", "type":"text", "format":""},{"id":"name", "type":"text", "format":""},{"id":"dob", "type":"date", "format":"dd/mm/yyyy"}} +mosip.esignet.authenticator.sunbird-rc.auth-factor.kbi.registry-search-url=http://10.3.148.107/registry/api/v1/Insurance/search +mosip.esignet.authenticator.sunbird-rc.kbi.entity-id-field=osid + +##-----------------------------VCI related demo configuration---------------------------------------------## + +mosip.esignet.vciplugin.sunbird-rc.issue-credential-url=http://164.52.205.87/credentials/issue +mosip.esignet.vciplugin.sunbird-rc.supported-credential-types=InsuranceCredential,HealthCardCredential +mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.static-value-map.issuerId=did:web:esignet-mock.dev.mosip.net +mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.template-url=requestTemplete.json +mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-get-url=http://10.3.148.107/api/v1/Insurance/ +mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.cred-schema-id=did:schema:1e4d93df-4047-4dd7-8515-9ad46796009f +mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.cred-schema-version=1.0.0 +mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthCardCredential.static-value-map.issuerId=did:web:esignet-mock.dev.mosip.net +mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthCardCredential.template-url=requestTemplete.json +mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthCardCredential.registry-get-url=http://10.3.148.107/api/v1/Insurance/ +mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthCardCredential.cred-schema-id=did:schema:1e4d93df-4047-4dd7-8515-9ad46796009f +mosip.esignet.vciplugin.sunbird-rc.credential-type.HealthCardCredential.cred-schema-version=1.0.0 +```` + + +Add "bindingtransaction" cache name in "mosip.esignet.cache.names" property. + +## License +This project is licensed under the terms of [Mozilla Public License 2.0](LICENSE). +This integration plugin is compatible with [Sunbird-RC 1.0.0](https://github.com/Sunbird-RC/sunbird-rc-core/tree/v1.0.0) + + diff --git a/sunbird-rc-plugin/pom.xml b/sunbird-rc-plugin/pom.xml new file mode 100644 index 0000000..03d745a --- /dev/null +++ b/sunbird-rc-plugin/pom.xml @@ -0,0 +1,349 @@ + + 4.0.0 + io.mosip.esignet.plugin.sunbirdrc + sunbird-rc-plugin + 0.3.0-SNAPSHOT + jar + + sunbird-rc-plugin + Sunbird-RC plugin implementation that is used for the integration with eSignet + https://github.com/mosip/esignet-plugins + + + + MPL 2.0 + https://www.mozilla.org/en-US/MPL/2.0/ + + + + scm:git:git://github.com/mosip/esignet-plugins.git + scm:git:ssh://github.com:mosip/esignet-plugins.git + https://github.com/mosip/esignet-plugins + HEAD + + + + Mosip + mosip.emailnotifier@gmail.com + io.mosip + https://github.com/mosip/esignet-plugins + + + + UTF-8 + 11 + 11 + 11 + 3.3.0 + 11 + 11 + 2.4 + 2.22.0 + 1.5 + 2.2.1 + 1.6.7 + 3.0.1 + 0.8.5 + 3.3.1 + 1.5.0-SNAPSHOT + + + + + junit + junit + test + 4.13.1 + + + + org.projectlombok + lombok + compile + 1.18.22 + + + + io.mosip.esignet + esignet-integration-api + ${esignet.version} + provided + + + + io.mosip.kernel + kernel-keymanager-service + 1.2.1.0 + provided + lib + + + org.springframework.cloud + spring-cloud-starter-sleuth + + + org.springframework.security + spring-security-test + + + + + info.weboftrust + ld-signatures-java + 1.0.0 + + + org.slf4j + slf4j-api + 1.7.30 + provided + + + + org.apache.velocity + velocity + 1.7 + + + + com.fasterxml.jackson.core + jackson-databind + 2.11.3 + provided + + + org.apache.velocity.tools + velocity-tools-generic + 3.1 + + + + + ossrh + CentralRepository + https://oss.sonatype.org/content/repositories/snapshots + default + + true + + + + central + MavenCentral + default + https://repo1.maven.org/maven2 + + false + + + + danubetech + DanubetechCentral + default + https://repo.danubetech.com/repository/maven-releases/ + + false + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + ${maven-assembly-plugin.version} + + + jar-with-dependencies + + false + + + + make-assembly + package + + single + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + + attach-javadocs + + jar + + + + + none + src/main/java + + + + maven-deploy-plugin + 2.8.1 + + + default-deploy + deploy + + deploy + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + + default-deploy + deploy + + deploy + + + + + ossrh + https://oss.sonatype.org/ + false + + + + + org.apache.maven.plugins + maven-source-plugin + true + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + pl.project13.maven + git-commit-id-plugin + 3.0.1 + + + get-the-git-infos + + revision + + validate + + + + true + ${project.build.outputDirectory}/git.properties + + ^git.build.(time|version)$ + ^git.commit.id.(abbrev|full)$ + + full + ${project.basedir}/.git + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + false + false + + ${argLine} --add-opens + java.xml/jdk.xml.internal=ALL-UNNAMED + --illegal-access=permit + + + + + org.jacoco + jacoco-maven-plugin + ${maven.jacoco.version} + + + + prepare-agent + + + + report + prepare-package + + report + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 3.0.0 + + + make-jar-executable + package + + run + + + + + + + + + + + + + diff --git a/sunbird-rc-plugin/src/main/java/io/mosip/esignet/plugin/sunbirdrc/dto/RegistrySearchRequestDto.java b/sunbird-rc-plugin/src/main/java/io/mosip/esignet/plugin/sunbirdrc/dto/RegistrySearchRequestDto.java new file mode 100644 index 0000000..a3b5368 --- /dev/null +++ b/sunbird-rc-plugin/src/main/java/io/mosip/esignet/plugin/sunbirdrc/dto/RegistrySearchRequestDto.java @@ -0,0 +1,18 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.esignet.plugin.sunbirdrc.dto; + +import lombok.Data; + +import java.util.Map; + +@Data +public class RegistrySearchRequestDto { + + private int offset; + private int limit; + private Map> filters; +} diff --git a/sunbird-rc-plugin/src/main/java/io/mosip/esignet/plugin/sunbirdrc/service/SunbirdRCAuthenticationService.java b/sunbird-rc-plugin/src/main/java/io/mosip/esignet/plugin/sunbirdrc/service/SunbirdRCAuthenticationService.java new file mode 100644 index 0000000..8430891 --- /dev/null +++ b/sunbird-rc-plugin/src/main/java/io/mosip/esignet/plugin/sunbirdrc/service/SunbirdRCAuthenticationService.java @@ -0,0 +1,199 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.esignet.plugin.sunbirdrc.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.*; +import io.mosip.esignet.api.exception.KycAuthException; +import io.mosip.esignet.api.exception.KycExchangeException; +import io.mosip.esignet.api.exception.SendOtpException; +import io.mosip.esignet.api.spi.Authenticator; +import io.mosip.esignet.api.util.ErrorConstants; +import io.mosip.esignet.sunbirdrc.integration.dto.RegistrySearchRequestDto; +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.core.ParameterizedTypeReference; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.annotation.PostConstruct; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.nio.charset.StandardCharsets; +import java.util.*; + + +@ConditionalOnProperty(value = "mosip.esignet.integration.authenticator", havingValue = "SunbirdRCAuthenticationService") +@Component +@Slf4j +public class SunbirdRCAuthenticationService implements Authenticator { + + private final String FILTER_EQUALS_OPERATOR="eq"; + + private final String FIELD_ID_KEY="id"; + + @Value("#{${mosip.esignet.authenticator.sunbird-rc.auth-factor.kbi.field-details}}") + private List> fieldDetailList; + + @Value("${mosip.esignet.authenticator.sunbird-rc.auth-factor.kbi.registry-search-url}") + private String registrySearchUrl; + + @Value("${mosip.esignet.authenticator.sunbird-rc.auth-factor.kbi.individual-id-field}") + private String idField; + + @Value("${mosip.esignet.authenticator.sunbird-rc.kbi.entity-id-field}") + private String entityIdField; + + @Autowired + private RestTemplate restTemplate; + + @Autowired + private ObjectMapper objectMapper; + + + @PostConstruct + public void initialize() throws KycAuthException { + log.info("Started to setup Sunbird-RC Authenticator"); + boolean individualIdFieldIsValid = false; + if(fieldDetailList==null || fieldDetailList.isEmpty()){ + log.error("Invalid configuration for field-details"); + throw new KycAuthException("sunbird-rc authenticator field is not configured properly"); + } + for (Map field : fieldDetailList) { + if (field.containsKey(FIELD_ID_KEY) && field.get(FIELD_ID_KEY).equals(idField)) { + individualIdFieldIsValid = true; + break; + } + } + if (!individualIdFieldIsValid) { + log.error("Invalid configuration: The 'individual-id-field' '{}' is not available in 'field-details'.", idField); + throw new KycAuthException("Invalid configuration: individual-id-field is not available in field-details."); + } + } + + @Validated + @Override + public KycAuthResult doKycAuth(@NotBlank String relyingPartyId, @NotBlank String clientId, + @NotNull @Valid KycAuthDto kycAuthDto) throws KycAuthException { + + log.info("Started to build kyc-auth request with transactionId : {} && clientId : {}", + kycAuthDto.getTransactionId(), clientId); + try { + for (AuthChallenge authChallenge : kycAuthDto.getChallengeList()) { + if(Objects.equals(authChallenge.getAuthFactorType(),"KBI")){ + return validateKnowledgeBasedAuth(kycAuthDto.getIndividualId(),authChallenge); + } + throw new KycAuthException("invalid_challenge_format"); + } + } catch (KycAuthException e) { + throw e; + } catch (Exception e) { + log.error("KYC-auth failed with transactionId : {} && clientId : {}", kycAuthDto.getTransactionId(), + clientId, e); + } + throw new KycAuthException(ErrorConstants.AUTH_FAILED); + } + + @Override + public KycExchangeResult doKycExchange(String relyingPartyId, String clientId, KycExchangeDto kycExchangeDto) + throws KycExchangeException { + throw new KycExchangeException(ErrorConstants.NOT_IMPLEMENTED); + } + + @Override + public SendOtpResult sendOtp(String relyingPartyId, String clientId, SendOtpDto sendOtpDto) + throws SendOtpException { + throw new SendOtpException(ErrorConstants.NOT_IMPLEMENTED); + } + + @Override + public boolean isSupportedOtpChannel(String channel) { + return false; + } + + @Override + public List getAllKycSigningCertificates() { + return new ArrayList<>(); + } + + private KycAuthResult validateKnowledgeBasedAuth(String individualId, AuthChallenge authChallenge) throws KycAuthException { + + KycAuthResult kycAuthResult= new KycAuthResult(); + RegistrySearchRequestDto registrySearchRequestDto =new RegistrySearchRequestDto(); + String encodedChallenge=authChallenge.getChallenge(); + + byte[] decodedBytes = Base64.getUrlDecoder().decode(encodedChallenge); + String challenge = new String(decodedBytes, StandardCharsets.UTF_8); + + try { + registrySearchRequestDto =createRegistrySearchRequestDto(challenge,individualId); + String requestBody = objectMapper.writeValueAsString(registrySearchRequestDto); + RequestEntity requestEntity = RequestEntity + .post(UriComponentsBuilder.fromUriString(registrySearchUrl).build().toUri()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(requestBody); + 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); + kycAuthResult.setKycToken((String)responseList.get(0).get(entityIdField)); + kycAuthResult.setPartnerSpecificUserToken((String)responseList.get(0).get(entityIdField)); + return kycAuthResult; + }else{ + log.error("Registry search returns more than one match, so authentication is considered as failed. Result size: " + responseList.size()); + throw new KycAuthException(ErrorConstants.AUTH_FAILED ); + } + }else { + log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); + throw new KycAuthException(ErrorConstants.AUTH_FAILED); + } + + } catch (Exception e) { + log.error("Failed to do the Authentication: {}",e); + throw new KycAuthException(ErrorConstants.AUTH_FAILED ); + } + } + + private RegistrySearchRequestDto createRegistrySearchRequestDto(String challenge, String individualId) throws KycAuthException, JsonProcessingException { + RegistrySearchRequestDto registrySearchRequestDto =new RegistrySearchRequestDto(); + registrySearchRequestDto.setLimit(2); + registrySearchRequestDto.setOffset(0); + Map> filter=new HashMap<>(); + + Map challengeMap = objectMapper.readValue(challenge, Map.class); + + + for(Map fieldDetailMap: fieldDetailList) { + Map hashMap=new HashMap<>(); + if(!StringUtils.isEmpty(idField) && fieldDetailMap.get(FIELD_ID_KEY).equals(idField)){ + hashMap.put(FILTER_EQUALS_OPERATOR,individualId); + }else{ + if(!challengeMap.containsKey(fieldDetailMap.get(FIELD_ID_KEY))) + { + log.error("Field '{}' is missing in the challenge.", fieldDetailMap.get(FIELD_ID_KEY)); + throw new KycAuthException(ErrorConstants.AUTH_FAILED ); + } + hashMap.put(FILTER_EQUALS_OPERATOR,challengeMap.get(fieldDetailMap.get(FIELD_ID_KEY))); + } + filter.put(fieldDetailMap.get(FIELD_ID_KEY),hashMap); + } + registrySearchRequestDto.setFilters(filter); + return registrySearchRequestDto; + } +} diff --git a/sunbird-rc-plugin/src/test/java/io/mosip/esignet/plugin/sunbirdrc/service/SunbirdRCAuthenticaionServiceTest.java b/sunbird-rc-plugin/src/test/java/io/mosip/esignet/plugin/sunbirdrc/service/SunbirdRCAuthenticaionServiceTest.java new file mode 100644 index 0000000..a046643 --- /dev/null +++ b/sunbird-rc-plugin/src/test/java/io/mosip/esignet/plugin/sunbirdrc/service/SunbirdRCAuthenticaionServiceTest.java @@ -0,0 +1,291 @@ +package io.mosip.esignet.plugin.sunbirdrc.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.*; +import io.mosip.esignet.api.exception.KycAuthException; +import io.mosip.esignet.api.exception.KycExchangeException; +import io.mosip.esignet.api.exception.SendOtpException; +import io.mosip.esignet.api.util.ErrorConstants; +import lombok.extern.slf4j.Slf4j; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatus; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@RunWith(MockitoJUnitRunner.class) +@Slf4j +public class SunbirdRCAuthenticaionServiceTest { + + @Mock + private RestTemplate restTemplate; + + @Mock + private ObjectMapper objectMapper; + + @InjectMocks + private SunbirdRCAuthenticationService sunbirdRCAuthenticationService; + + + + @Test + public void initializeWithValidConfig_thenPass() throws KycAuthException { + + List> fieldDetailList = List.of(Map.of("id","policyNumber","type","string","format","string")); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "fieldDetailList", fieldDetailList); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "idField", "policyNumber"); + sunbirdRCAuthenticationService.initialize(); + + } + + @Test + public void initializeWithInValidConfig_thenFail() { + try { + sunbirdRCAuthenticationService.initialize(); + }catch (KycAuthException e){ + Assert.assertEquals("sunbird-rc authenticator field is not configured properly", e.getMessage()); + } + } + + @Test + public void initializeWithInValidIdField_thenFail() { + List> fieldDetailList = List.of(Map.of("id","policyNumber","type","string","format","string")); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "fieldDetailList", fieldDetailList); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "idField", "policyNumber2"); + try { + sunbirdRCAuthenticationService.initialize(); + }catch (KycAuthException e){ + Assert.assertEquals("Invalid configuration: individual-id-field is not available in field-details.", e.getMessage()); + } + } + + @Test + public void doKycAuthWithValidParams_thenPass() throws KycAuthException, IOException, NoSuchFieldException, IllegalAccessException { + List> fieldDetailList = List.of(Map.of("id","policyNumber","type","string","format","string"),Map.of("id","fullName","type","string","format","string")); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "fieldDetailList", fieldDetailList); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "idField", "policyNumber"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "registrySearchUrl", "url"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "entityIdField", "policyNumber"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService,"objectMapper",new ObjectMapper()); + + // Arrange + String relyingPartyId = "validRelayingPartyId"; + String clientId = "validClientId"; + KycAuthDto kycAuthDto = new KycAuthDto(); // populate with valid data + AuthChallenge authChallenge=new AuthChallenge(); + authChallenge.setFormat("string"); + authChallenge.setAuthFactorType("KBI"); + authChallenge.setChallenge("eyJmdWxsTmFtZSI6IlphaWQgU2lkZGlxdWUiLCJkb2IiOiIyMDAwLTA3LTI2In0="); + + kycAuthDto.setChallengeList(List.of(authChallenge)); + kycAuthDto.setIndividualId("000000"); + + List> responseMap=new ArrayList<>(); + Map map=Map.of("policyNumber","000000","dob","2000-07-26"); + responseMap.add(map); + ResponseEntity>> responseEntity = new ResponseEntity(responseMap, HttpStatus.OK); + Mockito.when(restTemplate.exchange( + Mockito.any(RequestEntity.class), + Mockito.eq(new ParameterizedTypeReference>>() {}) + )).thenReturn(responseEntity); + + Map mockChallengMap=new HashMap<>(); + mockChallengMap.put("fullName","Zaid Siddique"); + mockChallengMap.put("dob","2000-07-26"); + + KycAuthResult result = sunbirdRCAuthenticationService.doKycAuth(relyingPartyId, clientId, kycAuthDto); + Assert.assertNotNull(result); + } + + @Test + public void doKycAuthWithInValidChallenge_thenFail() throws IOException { + + List> fieldDetailList = List.of(Map.of("id","policyNumber","type","string","format","string"),Map.of("id","fullName","type","string","format","string")); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "fieldDetailList", fieldDetailList); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "idField", "policyNumber"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "registrySearchUrl", "url"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "entityIdField", "policyNumber"); + + String relyingPartyId = "validRelayingPartyId"; + String clientId = "validClientId"; + KycAuthDto kycAuthDto = new KycAuthDto(); // populate with valid data + AuthChallenge authChallenge=new AuthChallenge(); + authChallenge.setFormat("string"); + authChallenge.setAuthFactorType("KBI"); + authChallenge.setChallenge("eyJmdWxsTmFtZSI6IlphaWQiLCJkb2IiOiIyMDAwLTA3LTI2In0="); + + kycAuthDto.setChallengeList(List.of(authChallenge)); + kycAuthDto.setIndividualId("000000"); + + Map mockChallengMap=new HashMap<>(); + mockChallengMap.put("fullName","Zaid"); + mockChallengMap.put("dob","2000-07-26"); + Mockito.when(objectMapper.readValue(Mockito.anyString(),Mockito.eq(Map.class))).thenReturn(mockChallengMap); + + try{ + sunbirdRCAuthenticationService.doKycAuth(relyingPartyId, clientId, kycAuthDto); + Assert.fail(); + }catch (KycAuthException e){ + Assert.assertEquals(e.getErrorCode(), ErrorConstants.AUTH_FAILED); + } + + } + + + @Test + public void doKycAuthWithInValidResponse_thenFail() { + List> fieldDetailList = List.of(Map.of("id","policyNumber","type","string","format","string")); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "fieldDetailList", fieldDetailList); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "idField", "policyNumber"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "registrySearchUrl", "url"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "entityIdField", "policyNumber"); + // Arrange + String relyingPartyId = "validRelayingPartyId"; + String clientId = "validClientId"; + KycAuthDto kycAuthDto = new KycAuthDto(); // populate with valid data + AuthChallenge authChallenge=new AuthChallenge(); + authChallenge.setFormat("string"); + authChallenge.setAuthFactorType("KBI"); + authChallenge.setChallenge("eyJmdWxsTmFtZSI6IlphaWQgU2lkZGlxdWUiLCJkb2IiOiIyMDAwLTA3LTI2In0="); + + kycAuthDto.setChallengeList(List.of(authChallenge)); + kycAuthDto.setIndividualId("000000"); + + List> responseMap=new ArrayList<>();Map map=Map.of("policyNumber","654321","dob","654321"); + responseMap.add(map); + ResponseEntity>> responseEntity = new ResponseEntity(responseMap, HttpStatus.FORBIDDEN); + Mockito.when(restTemplate.exchange( + Mockito.any(RequestEntity.class), + Mockito.eq(new ParameterizedTypeReference>>() {}) + )).thenReturn(responseEntity); + + try{ + sunbirdRCAuthenticationService.doKycAuth(relyingPartyId, clientId, kycAuthDto); + Assert.fail(); + }catch (KycAuthException e){ + Assert.assertEquals(e.getErrorCode(), ErrorConstants.AUTH_FAILED); + } + } + + @Test + public void doKycAuthWithResponseSizeMoreThenOne_thenFail() throws IOException { + List> fieldDetailList = List.of(Map.of("id","policyNumber","type","string","format","string"),Map.of("id","fullName","type","string","format","string")); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "fieldDetailList", fieldDetailList); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "idField", "policyNumber"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "registrySearchUrl", "url"); + ReflectionTestUtils.setField(sunbirdRCAuthenticationService, "entityIdField", "policyNumber"); + // Arrange + String relyingPartyId = "validRelayingPartyId"; + String clientId = "validClientId"; + KycAuthDto kycAuthDto = new KycAuthDto(); // populate with valid data + AuthChallenge authChallenge=new AuthChallenge(); + authChallenge.setFormat("string"); + authChallenge.setAuthFactorType("KBI"); + authChallenge.setChallenge("eyJmdWxsTmFtZSI6IlphaWQgU2lkZGlxdWUiLCJkb2IiOiIyMDAwLTA3LTI2In0="); + + kycAuthDto.setChallengeList(List.of(authChallenge)); + kycAuthDto.setIndividualId("000000"); + + List> responseList =new ArrayList<>(); + Map response1=Map.of("response1","654321"); + Map response2=Map.of("response2","654321"); + responseList.add(response1); + responseList.add(response2); + ResponseEntity>> responseEntity = new ResponseEntity(responseList, HttpStatus.OK); + Mockito.when(restTemplate.exchange( + Mockito.any(RequestEntity.class), + Mockito.eq(new ParameterizedTypeReference>>() {}) + )).thenReturn(responseEntity); + + Map mockChallengMap=new HashMap<>(); + mockChallengMap.put("fullName","Zaid Siddique"); + mockChallengMap.put("dob","2000-07-26"); + Mockito.when(objectMapper.readValue(Mockito.anyString(),Mockito.eq(Map.class))).thenReturn(mockChallengMap); + + try{ + sunbirdRCAuthenticationService.doKycAuth(relyingPartyId, clientId, kycAuthDto); + Assert.fail(); + }catch (KycAuthException e){ + Assert.assertEquals(e.getErrorCode(), ErrorConstants.AUTH_FAILED); + } + } + + @Test + public void doKycAuthWithInValidChallengeType_thenFail() { + String relyingPartyId = "validRelayingPartyId"; + String clientId = "validClientId"; + KycAuthDto kycAuthDto = new KycAuthDto(); // populate with valid data + AuthChallenge authChallenge=new AuthChallenge(); + authChallenge.setFormat("string"); + authChallenge.setAuthFactorType("Bio"); + authChallenge.setChallenge("eyJmdWxsTmFtZSI6IlphaWQgU2lkZGlxdWUiLCJkb2IiOiIyMDAwLTA3LTI2In0="); + + kycAuthDto.setChallengeList(List.of(authChallenge)); + kycAuthDto.setIndividualId("000000"); + + try{ + sunbirdRCAuthenticationService.doKycAuth(relyingPartyId, clientId, kycAuthDto); + Assert.fail(); + }catch (KycAuthException e){ + Assert.assertEquals(e.getErrorCode(),"invalid_challenge_format"); + } + } + + @Test + public void doKycAuthWithOutChallenge_thenFail() { + String relyingPartyId = "validRelayingPartyId"; + String clientId = "validClientId"; + KycAuthDto kycAuthDto = new KycAuthDto(); // populate with valid data + kycAuthDto.setIndividualId("000000"); + + try{ + sunbirdRCAuthenticationService.doKycAuth(relyingPartyId, clientId, kycAuthDto); + Assert.fail(); + }catch (KycAuthException e){ + Assert.assertEquals(e.getMessage(),ErrorConstants.AUTH_FAILED); + } + } + + + + @Test + public void doKycExchangeNotImplemented_thenFail() { + try{ + sunbirdRCAuthenticationService.doKycExchange("relyingPartyId","clientId",new KycExchangeDto()); + Assert.fail(); + } catch (KycExchangeException e) { + Assert.assertEquals(e.getErrorCode(), ErrorConstants.NOT_IMPLEMENTED); + } + } + + @Test + public void sendOtpNotImplemented_thenFail() { + try{ + sunbirdRCAuthenticationService.sendOtp("relayingPartyId","clientId",new SendOtpDto()); + Assert.fail(); + } catch (SendOtpException e) { + Assert.assertEquals(e.getErrorCode(), ErrorConstants.NOT_IMPLEMENTED); + } + } + + @Test + public void isSupportedOtpChannel_thenFail() { + boolean result = sunbirdRCAuthenticationService.isSupportedOtpChannel("sms"); + Assert.assertFalse(result); + } + +} diff --git a/sunbird-rc-plugin/src/test/resources/InsuranceCredential.json b/sunbird-rc-plugin/src/test/resources/InsuranceCredential.json new file mode 100644 index 0000000..df4001a --- /dev/null +++ b/sunbird-rc-plugin/src/test/resources/InsuranceCredential.json @@ -0,0 +1,30 @@ +##Here we are injecting DateTool instance from java velocity library to set the expiry date +#set( $defaultLocale = $date.getLocale() ) +#set( $calenderNow = $date.getCalendar() ) +#set( $ISO8601DateTimeWithMillisUTC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" ) +## Adding no. of Days we want to set as expiry,here '5' represent Day and '30' represent no. of days +#set( $expiry =$calenderNow.add(5,30)) +{ +"@context": [ +"https://www.w3.org/2018/credentials/v1", +"https://holashchand.github.io/test_project/insurance-context.json" +], +"type": [ +"VerifiableCredential", +"InsuranceCredential" +], +"issuer": "${issuerId}", +"expirationDate": "${date.format($ISO8601DateTimeWithMillisUTC, $calenderNow, $defaultLocale)}", +"credentialSubject": { +"dob": "${dob}", +"gender": "${gender}", +"mobile": "${mobile}", +"benefits": #if($benefits)$benefits#else#set($benefits = '"[]"') $benefits#end, +"fullName": "${fullName}", +"email": "${email}", +"policyIssuedOn": "${policyIssuedOn}", +"policyExpiresOn": "${policyExpiresOn}", +"policyName": "${policyName}", +"policyNumber": "${policyNumber}" +} +} \ No newline at end of file