Skip to content

Commit

Permalink
ES-2147
Browse files Browse the repository at this point in the history
Signed-off-by: Nandhukumar <[email protected]>
  • Loading branch information
nandhu-kumar committed Jan 20, 2025
2 parents 2f7e2b4 + 4d9d8ac commit cabede5
Show file tree
Hide file tree
Showing 35 changed files with 2,392 additions and 109 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/push-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ jobs:
find ${{ env.SERVICE_LOCATION }} -path '*/target/*' -exec zip ${{ env.BUILD_ARTIFACT }}.zip {} +
- name: Upload the springboot jars
if: ${{ !contains(github.ref, 'master') || !contains(github.ref, 'main') }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.BUILD_ARTIFACT }}
path: ${{ env.BUILD_ARTIFACT }}.zip
Expand Down
2 changes: 1 addition & 1 deletion binding-service-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@
<artifactId>esignet-core</artifactId>
<version>${esignet.core.version}</version>
</dependency>
</dependencies>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.mosip.esignet.api.spi.KeyBinder;
import io.mosip.esignet.core.dto.*;
import io.mosip.esignet.core.exception.EsignetException;
import io.mosip.esignet.core.util.CaptchaHelper;
import io.mosip.esignet.repository.PublicKeyRegistryRepository;
import io.mosip.kernel.keymanagerservice.util.KeymanagerUtil;
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
Expand Down Expand Up @@ -54,12 +55,16 @@ public class KeyBindingServiceImpl implements KeyBindingService {
@Autowired
private KeyBindingHelperService keyBindingHelperService;

@Autowired
private CaptchaHelper captchaHelper;

@Value("${mosip.esignet.binding.encrypt-binding-id:true}")
private boolean encryptBindingId;


@Override
public BindingOtpResponse sendBindingOtp(BindingOtpRequest bindingOtpRequest, Map<String, String> requestHeaders) throws EsignetException {
public BindingOtpResponse sendBindingOtp(BindingOtpRequest bindingOtpRequest, Map<String, String> requestHeaders)
throws EsignetException {
log.debug("sendBindingOtp :: Request headers >> {}", requestHeaders);
SendOtpResult sendOtpResult;
try {
Expand All @@ -69,18 +74,24 @@ public BindingOtpResponse sendBindingOtp(BindingOtpRequest bindingOtpRequest, Ma
log.error("Failed to send binding otp: {}", e);
throw new EsignetException(e.getErrorCode());
}

if (sendOtpResult == null) {
log.error("send-otp Failed wrapper returned null result!");
throw new EsignetException(SEND_OTP_FAILED);
}

BindingOtpResponse otpResponse = new BindingOtpResponse();
otpResponse.setMaskedEmail(sendOtpResult.getMaskedEmail());
otpResponse.setMaskedMobile(sendOtpResult.getMaskedMobile());
return otpResponse;
}

@Override
public BindingOtpResponse sendBindingOtpV2(BindingOtpRequestV2 bindingOtpRequestV2, Map<String, String> requestHeaders)
throws EsignetException {
captchaHelper.validateCaptchaToken(bindingOtpRequestV2.getCaptchaToken(), "binding-otp");
return sendBindingOtp(bindingOtpRequestV2, requestHeaders);
}


private void validateChallengeListAuthFormat(List<AuthChallenge> challengeList){
if(!challengeList.stream().allMatch(challenge->keyBindingWrapper.getSupportedChallengeFormats(challenge.getAuthFactorType()).
contains(challenge.getFormat()))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,9 @@
*/
package io.mosip.esignet;

import static io.mosip.esignet.api.util.ErrorConstants.SEND_OTP_FAILED;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.time.LocalDateTime;
import java.util.*;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.RSAKey;
import io.mosip.esignet.api.dto.AuthChallenge;
Expand All @@ -28,10 +16,14 @@
import io.mosip.esignet.api.exception.KeyBindingException;
import io.mosip.esignet.api.exception.SendOtpException;
import io.mosip.esignet.api.spi.KeyBinder;
import io.mosip.esignet.entity.PublicKeyRegistry;
import io.mosip.esignet.core.dto.*;
import io.mosip.esignet.core.exception.EsignetException;
import io.mosip.esignet.core.constants.ErrorConstants;
import io.mosip.esignet.core.dto.BindingOtpRequest;
import io.mosip.esignet.core.dto.BindingOtpRequestV2;
import io.mosip.esignet.core.dto.BindingOtpResponse;
import io.mosip.esignet.core.dto.WalletBindingRequest;
import io.mosip.esignet.core.exception.EsignetException;
import io.mosip.esignet.core.util.CaptchaHelper;
import io.mosip.esignet.entity.PublicKeyRegistry;
import io.mosip.esignet.repository.PublicKeyRegistryRepository;
import io.mosip.esignet.services.KeyBindingHelperService;
import io.mosip.esignet.services.KeyBindingServiceImpl;
Expand All @@ -47,9 +39,21 @@
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.jwk.JWK;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.time.LocalDateTime;
import java.util.*;

import static io.mosip.esignet.api.util.ErrorConstants.SEND_OTP_FAILED;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@Slf4j
@RunWith(MockitoJUnitRunner.class)
Expand All @@ -70,10 +74,16 @@ public class KeyBindingServiceTest {
@Mock
KeymanagerUtil keymanagerUtil;

CaptchaHelper captchaHelper;

@Mock
RestTemplate restTemplate;

private JWK clientJWK = generateJWK_RSA();

private ObjectMapper objectMapper = new ObjectMapper();


@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Expand All @@ -82,13 +92,17 @@ public void setUp() {
mockKeyBindingWrapperService = mock(KeyBinder.class);
when(mockKeyBindingWrapperService.getSupportedChallengeFormats(Mockito.anyString()))
.thenReturn(Arrays.asList("jwt", "alpha-numeric"));

captchaHelper = new CaptchaHelper(restTemplate, "https://api-internal.camdgc-dev1.mosip.net/v1/captcha/validatecaptcha",
"esignet", List.of("binding-otp"));

ReflectionTestUtils.setField(keyBindingService, "keyBindingWrapper", mockKeyBindingWrapperService);

keyBindingHelperService = mock(KeyBindingHelperService.class);
ReflectionTestUtils.setField(keyBindingHelperService, "saltLength", 10);
ReflectionTestUtils.setField(keyBindingHelperService, "publicKeyRegistryRepository", publicKeyRegistryRepository);
ReflectionTestUtils.setField(keyBindingHelperService, "keymanagerUtil", keymanagerUtil);

ReflectionTestUtils.setField(keyBindingService, "captchaHelper", captchaHelper);
ReflectionTestUtils.setField(keyBindingService, "keyBindingHelperService", keyBindingHelperService);
}

Expand All @@ -106,7 +120,8 @@ public void sendBindingOtp_withValidDetails_thenPass() throws SendOtpException {
BindingOtpResponse otpResponse = keyBindingService.sendBindingOtp(otpRequest, headers);
Assert.assertNotNull(otpResponse);
}



@Test(expected = EsignetException.class)
public void sendBindingOtp_withInvalidRequest_thenFail() throws SendOtpException {
BindingOtpRequest otpRequest = new BindingOtpRequest();
Expand All @@ -119,6 +134,41 @@ public void sendBindingOtp_withInvalidRequest_thenFail() throws SendOtpException
keyBindingService.sendBindingOtp(otpRequest, headers);
}


@Test
public void sendBindingOtpV2_withInvalidCaptcha_thenFail() throws SendOtpException {

BindingOtpRequestV2 otpRequest = new BindingOtpRequestV2();
otpRequest.setIndividualId("8267411571");
otpRequest.setOtpChannels(Arrays.asList("OTP"));
otpRequest.setCaptchaToken("qwerty");

Map<String, String> headers = new HashMap<>();

try {
keyBindingService.sendBindingOtpV2(otpRequest, headers);
} catch (EsignetException e) {
Assert.assertTrue(e.getErrorCode().equals(ErrorConstants.INVALID_CAPTCHA));
}
}

@Test
public void sendBindingOtpV2_withEmptyCaptcha_thenFail() throws SendOtpException {

BindingOtpRequestV2 otpRequest = new BindingOtpRequestV2();
otpRequest.setIndividualId("8267411571");
otpRequest.setOtpChannels(Arrays.asList("OTP"));
otpRequest.setCaptchaToken("");

Map<String, String> headers = new HashMap<>();

try {
keyBindingService.sendBindingOtpV2(otpRequest, headers);
} catch (EsignetException e) {
Assert.assertTrue(e.getErrorCode().equals(ErrorConstants.INVALID_CAPTCHA));
}
}

@Test
public void sendBindingOtp_withNullResponseFromWrapper_thenFail() throws SendOtpException {
BindingOtpRequest otpRequest = new BindingOtpRequest();
Expand Down Expand Up @@ -368,4 +418,5 @@ public static JWK generateJWK_RSA() {
}
return null;
}

}
108 changes: 106 additions & 2 deletions docs/esignet-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4428,6 +4428,112 @@ paths:
- url: 'https://esignet.collab.mosip.net/v1/esignet'
x-stoplight:
id: t315hcecaulyy
/binding/v2/binding-otp:
post:
tags:
- WALLET BACKEND
summary: Send Binding OTP Endpoint
description: Send wallet binding OTP endpoint is invoked by Mimoto server.
operationId: post-binding-otp
parameters:
- name: partner-api-key
in: header
description: 'API key of the binding partner, this will be passed to binder implementation to interact with authentication system.'
schema:
type: string
- name: partner-id
in: header
description: 'Binding partner Identifier, this will be passed to binder implementation to interact with authentication system.'
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
requestTime:
type: string
request:
type: object
properties:
individualId:
type: string
description: User Id (UIN/VID)
otpChannels:
type: array
description: Channels to which OTP should be delivered.
items:
type: string
captchaToken:
type: string
description: 'Captcha token, if enabled.'
required:
- individualId
- otpChannels
required:
- requestTime
- request
examples:
Example 1:
value:
requestTime: '2023-09-22T08:01:13.000Z'
request:
individualId: '24554655645'
otpChannels:
- sms
- email
captchaToken: ALSKDJFURIEOQPZMKFURHFVBH
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
responseTIme:
type: string
response:
type: object
properties:
maskedEmail:
type: string
description: Masked email id of the individualId user.
maskedMobile:
type: string
description: Masked mobile number of the individualId user.
errors:
type: array
items:
type: object
properties:
errorCode:
type: string
enum:
- invalid_otp_channel
- unknown_error
- invalid_individual_id
- send_otp_failed
- invalid_captcha
errorMessage:
type: string
required:
- responseTIme
examples:
Example 1:
value:
responseTIme: '2023-09-22T08:01:16.000Z'
response:
maskedEmail: [email protected]
maskedMobile: XXXXXXX357934
errors: [ ]
security:
- Authorization-send_binding_otp: [ ]
servers:
- url: 'https://esignet.collab.mosip.net/v1/esignet'
x-stoplight:
id: xnl3gyq4v4bh4
/binding/wallet-binding:
post:
tags:
Expand Down Expand Up @@ -5290,8 +5396,6 @@ components:
Expand Down
Loading

0 comments on commit cabede5

Please sign in to comment.