Skip to content

Commit

Permalink
ES-1101 (#157)
Browse files Browse the repository at this point in the history
Signed-off-by: ase-101 <[email protected]>
  • Loading branch information
ase-101 authored May 17, 2024
1 parent c67284c commit 433c158
Show file tree
Hide file tree
Showing 18 changed files with 531 additions and 9 deletions.
9 changes: 9 additions & 0 deletions signup-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,20 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>io.mosip.esignet</groupId>
<artifactId>esignet-integration-api</artifactId>
<version>1.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>oauth2-oidc-sdk</artifactId>
<version>11.10.1</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.mosip.signup.config;

import io.mosip.signup.services.IdentityVerificationHandshakeHandler;
import io.mosip.signup.services.IdentityVerificationWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

@Autowired
private IdentityVerificationWebSocketHandler identityVerificationWebSocketHandler;

@Autowired
private IdentityVerificationHandshakeHandler identityVerificationHandshakeHandler;

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
webSocketHandlerRegistry.addHandler(identityVerificationWebSocketHandler,"/identity-verification")
.setHandshakeHandler(identityVerificationHandshakeHandler);
//By default, only same origin requests are allowed
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.mosip.signup.controllers;

import com.fasterxml.jackson.databind.JsonNode;
import io.mosip.esignet.core.dto.RequestWrapper;
import io.mosip.esignet.core.dto.ResponseWrapper;
import io.mosip.esignet.core.util.IdentityProviderUtil;
import io.mosip.signup.dto.*;
import io.mosip.signup.exception.SignUpException;
import io.mosip.signup.helper.AuditHelper;
import io.mosip.signup.services.IdentityVerificationService;
import io.mosip.signup.util.AuditEvent;
import io.mosip.signup.util.AuditEventType;
import io.mosip.signup.util.ErrorConstants;
import io.mosip.signup.util.SignUpConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

import static io.mosip.signup.util.SignUpConstants.EMTPY;

@Slf4j
@RestController
@RequestMapping("/identity-verification")
public class IdentityVerificationController {

@Autowired
AuditHelper auditHelper;

@Autowired
IdentityVerificationService identityVerificationService;

@PostMapping("/initiate")
public ResponseWrapper<InitiateIdentityVerificationResponse> initiateIdentityVerification(
@Valid @RequestBody RequestWrapper<InitiateIdentityVerificationRequest> requestWrapper,
HttpServletResponse response){
ResponseWrapper<InitiateIdentityVerificationResponse> responseWrapper = new ResponseWrapper<>();
try{
responseWrapper.setResponse(identityVerificationService.initiateIdentityVerification(requestWrapper.getRequest(), response));
}catch (SignUpException signUpException){
auditHelper.sendAuditTransaction(AuditEvent.INITIATE_IDENTITY_VERIFICATION, AuditEventType.ERROR, null, signUpException);
throw signUpException;
}
auditHelper.sendAuditTransaction(AuditEvent.INITIATE_IDENTITY_VERIFICATION, AuditEventType.SUCCESS, null, null);
responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime());
return responseWrapper;
}

@GetMapping("/identity-verifier/{id}")
public ResponseWrapper<JsonNode> getIdentityVerifierDetails(@PathVariable String id,
@Valid @NotBlank(message = ErrorConstants.INVALID_TRANSACTION)
@CookieValue(value = SignUpConstants.IDV_TRANSACTION_ID, defaultValue = EMTPY) String transactionId) {
ResponseWrapper<JsonNode> responseWrapper = new ResponseWrapper<>();
responseWrapper.setResponse(identityVerificationService.getIdentityVerifierDetails(transactionId, id));
auditHelper.sendAuditTransaction(AuditEvent.IDENTITY_VERIFIER, AuditEventType.SUCCESS, transactionId, null);
responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime());
return responseWrapper;
}

@PostMapping("/slot")
public ResponseWrapper<SlotResponse> getSlot(@Valid @RequestBody RequestWrapper<SlotRequest> requestWrapper,
@Valid @NotBlank(message = ErrorConstants.INVALID_TRANSACTION)
@CookieValue(value = SignUpConstants.IDV_TRANSACTION_ID, defaultValue = EMTPY) String transactionId) {
ResponseWrapper<SlotResponse> responseWrapper = new ResponseWrapper<>();
responseWrapper.setResponse(identityVerificationService.getSlot(transactionId, requestWrapper.getRequest()));
auditHelper.sendAuditTransaction(AuditEvent.IDENTITY_VERIFICATION_SLOT, AuditEventType.SUCCESS, transactionId, null);
responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime());
return responseWrapper;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.mosip.signup.dto;

import lombok.Data;

import java.io.Serializable;

@Data
public class IdentityVerificationTransaction implements Serializable {

private String individualId;
private String slotId;
private String verifierId;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.mosip.signup.dto;

import lombok.Data;

import java.io.Serializable;
import java.util.Map;

@Data
public class IdentityVerifierDetail implements Serializable {

private String id;
private Map<String, String> displayName;
private String processType;
private boolean active;
private String logoUrl;
private boolean retryOnFailure;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.mosip.signup.dto;


import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data
public class InitiateIdentityVerificationRequest {

@NotBlank
private String authorizationCode;

@NotBlank
private String state;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.mosip.signup.dto;

import lombok.Data;

import java.util.List;

@Data
public class InitiateIdentityVerificationResponse {

IdentityVerifierDetail[] identityVerifiers;
}
12 changes: 12 additions & 0 deletions signup-service/src/main/java/io/mosip/signup/dto/SlotRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.mosip.signup.dto;

import lombok.Data;

@Data
public class SlotRequest {

private String verifierId;
private String consent;
private String disabilityType;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.mosip.signup.dto;

import lombok.Data;

@Data
public class SlotResponse {

private String slotId;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package io.mosip.signup.services;

import io.mosip.esignet.core.util.IdentityProviderUtil;
import io.mosip.signup.dto.IdentityVerificationTransaction;
import io.mosip.signup.dto.IdentityVerifierDetail;
import io.mosip.signup.dto.RegistrationTransaction;
import io.mosip.signup.helper.CryptoHelper;
import io.mosip.signup.util.SignUpConstants;
Expand All @@ -19,6 +21,8 @@
@Service
public class CacheUtilService {

public static final String COMMON_KEY = "KEY";

@Autowired
CacheManager cacheManager;

Expand Down Expand Up @@ -54,6 +58,16 @@ public String setActiveKeyAlias(String key, String alias) {
return alias;
}

@Cacheable(value = SignUpConstants.IDENTITY_VERIFIERS, key = "#key")
public IdentityVerifierDetail[] setIdentityVerifierDetails(String key, IdentityVerifierDetail[] identityVerifierDetails) {
return identityVerifierDetails;
}

@Cacheable(value = SignUpConstants.IDENTITY_VERIFICATION, key = "#transactionId")
public IdentityVerificationTransaction setIdentityVerificationTransaction(String transactionId,
IdentityVerificationTransaction identityVerificationTransaction) {
return identityVerificationTransaction;
}

//----- cache update is separated
//----- we are not using @cacheput as @cacheput extends the TTL on cache entry
Expand All @@ -71,7 +85,7 @@ public void updateStatusCheckTransaction(String transactionId,

//---Getter---
public RegistrationTransaction getChallengeGeneratedTransaction(String transactionId) {
return cacheManager.getCache(SignUpConstants.CHALLENGE_GENERATED).get(transactionId, RegistrationTransaction.class); //NOSONAR getCache() will not be returning null here.
return cacheManager.getCache(SignUpConstants.CHALLENGE_GENERATED).get(transactionId, RegistrationTransaction.class); //NOSONAR getCache() will not be returning null here.
}

public RegistrationTransaction getChallengeVerifiedTransaction(String transactionId) {
Expand All @@ -95,4 +109,12 @@ public String getSecretKey(String keyAlias) {
public String getActiveKeyAlias() {
return cacheManager.getCache(SignUpConstants.KEY_ALIAS).get(CryptoHelper.ALIAS_CACHE_KEY, String.class); //NOSONAR getCache() will not be returning null here.
}

public IdentityVerifierDetail[] getIdentityVerifierDetails() {
return cacheManager.getCache(SignUpConstants.IDENTITY_VERIFIERS).get(COMMON_KEY, IdentityVerifierDetail[].class); //NOSONAR getCache() will not be returning null here.
}

public IdentityVerificationTransaction getIdentityVerificationTransaction(String transactionId) {
return cacheManager.getCache(SignUpConstants.IDENTITY_VERIFICATION).get(transactionId, IdentityVerificationTransaction.class); //NOSONAR getCache() will not be returning null here.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.mosip.signup.services;

import io.mosip.signup.dto.IdentityVerificationTransaction;
import io.mosip.signup.util.ErrorConstants;
import io.mosip.signup.util.SignUpConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeFailureException;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

import java.security.Principal;
import java.util.List;
import java.util.Map;
import java.util.Optional;


@Slf4j
@Component
public class IdentityVerificationHandshakeHandler extends DefaultHandshakeHandler {

@Autowired
CacheUtilService cacheUtilService;

@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
Map<String, Object> attributes) {
HttpHeaders headers = request.getHeaders();

String cookieName = SignUpConstants.IDV_TRANSACTION_ID+"=";
Optional<String> transactionCookie = headers.getOrEmpty(HttpHeaders.COOKIE)
.stream()
.filter( cookie -> cookie.startsWith(cookieName))
.findFirst();

if(!transactionCookie.isPresent())
throw new HandshakeFailureException(ErrorConstants.INVALID_TRANSACTION);

IdentityVerificationTransaction transaction = cacheUtilService.getIdentityVerificationTransaction(
transactionCookie.get().substring(cookieName.length()));

List<String> values = headers.getOrEmpty("SlotId");
if(values.isEmpty() || !values.get(0).equals(transaction.getSlotId())) {
log.error("SlotId in the handshake header doesn't match the slotId in the transaction");
throw new HandshakeFailureException(ErrorConstants.INVALID_TRANSACTION);
}

return new Principal() {
@Override
public String getName() {
return transaction.getSlotId();
}
};
}
}
Loading

0 comments on commit 433c158

Please sign in to comment.