io.mosip.pms.oauth.client.service.impl.ClientManagementServiceImpl Maven / Gradle / Ivy
The newest version!
package io.mosip.pms.oauth.client.service.impl;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;
import io.mosip.kernel.core.authmanager.authadapter.model.AuthUserDetails;
import io.mosip.pms.common.entity.*;
import io.mosip.pms.common.entity.ClientDetail;
import io.mosip.pms.common.repository.*;
import io.mosip.pms.device.util.AuditUtil;
import io.mosip.pms.oauth.client.dto.*;
import io.mosip.pms.oidc.client.contant.ClientServiceAuditEnum;
import io.mosip.pms.partner.request.dto.PartnerCertDownloadRequestDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.mosip.kernel.core.logger.spi.Logger;
import io.mosip.kernel.core.util.CryptoUtil;
import io.mosip.kernel.core.util.DateUtils;
import io.mosip.kernel.core.util.HMACUtils2;
import io.mosip.pms.common.constant.ApiAccessibleExceptionConstant;
import io.mosip.pms.common.constant.CommonConstant;
import io.mosip.pms.common.constant.EventType;
import io.mosip.pms.common.dto.ClientPublishDto;
import io.mosip.pms.common.dto.PartnerDataPublishDto;
import io.mosip.pms.common.dto.PolicyPublishDto;
import io.mosip.pms.common.dto.Type;
import io.mosip.pms.common.exception.ApiAccessibleException;
import io.mosip.pms.common.helper.WebSubPublisher;
import io.mosip.pms.common.util.AuthenticationContextRefUtil;
import io.mosip.pms.common.util.MapperUtils;
import io.mosip.pms.common.util.PMSLogger;
import io.mosip.pms.common.util.RestUtil;
import io.mosip.pms.common.util.UserDetailUtil;
import io.mosip.pms.oauth.client.service.ClientManagementService;
import io.mosip.pms.partner.constant.ErrorCode;
import io.mosip.pms.partner.constant.PartnerConstants;
import io.mosip.pms.partner.constant.PartnerServiceAuditEnum;
import io.mosip.pms.partner.exception.PartnerServiceException;
import io.mosip.pms.partner.response.dto.PartnerCertDownloadResponeDto;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.lang.JoseException;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import javax.validation.constraints.NotNull;
@Service
public class ClientManagementServiceImpl implements ClientManagementService {
private static final Logger LOGGER = PMSLogger.getLogger(ClientManagementServiceImpl.class);
private static final String ALLOWED_KYC_ATTRIBUTES = "allowedKycAttributes";
private static final String ATTRIBUTE_NAME = "attributeName";
private static final String ALLOWED_AUTH_TYPES = "allowedAuthTypes";
private static final String AUTH_TYPE = "authType";
private static final String MANDATORY = "mandatory";
private static final String AUTH_POLICY_TYPE = "Auth";
private static final String AUTH_PARTNER_TYPE = "Auth_Partner";
private static final String ERROR_MESSAGE = "errorMessage";
public static final String ACTIVE = "ACTIVE";
public static final String BLANK_STRING = "";
@Autowired
ObjectMapper objectMapper;
@Autowired
ClientDetailRepository clientDetailRepository;
@Autowired
AuthPolicyRepository authPolicyRepository;
@Autowired
PartnerRepository partnerRepository;
@Autowired
PartnerServiceRepository partnerServiceRepository;
@Autowired
PartnerPolicyRequestRepository partnerPolicyRequestRepository;
@Autowired
RestUtil restUtil;
@Autowired
AuditUtil auditUtil;
@Autowired
private Environment environment;
@Autowired
private WebSubPublisher webSubPublisher;
@Autowired
private AuthenticationContextRefUtil authenticationContextClassRefUtil;
@Override
public ClientDetailResponse createOIDCClient(ClientDetailCreateRequest createRequest) throws Exception {
ProcessedClientDetail processedClientDetail = processCreateOIDCClient(createRequest);
ClientDetail clientDetail = processedClientDetail.getClientDetail();
callEsignetService(clientDetail, environment.getProperty("mosip.pms.esignet.oidc-client-create-url"),false);
publishClientData(processedClientDetail.getPartner(), processedClientDetail.getPolicy(), clientDetail);
clientDetailRepository.save(clientDetail);
var response = new ClientDetailResponse();
response.setClientId(clientDetail.getId());
response.setStatus(clientDetail.getStatus());
return response;
}
@Override
public ClientDetailResponse createOAuthClient(ClientDetailCreateRequestV2 createRequest) throws Exception {
ProcessedClientDetail processedClientDetail = processCreateOIDCClient(createRequest);
ClientDetail clientDetail = processedClientDetail.getClientDetail();
callEsignetService(clientDetail, environment.getProperty("mosip.pms.esignet.oauth-client-create-url"), true, createRequest.getClientNameLangMap());
publishClientData(processedClientDetail.getPartner(), processedClientDetail.getPolicy(), clientDetail);
clientDetailRepository.save(clientDetail);
var response = new ClientDetailResponse();
response.setClientId(clientDetail.getId());
response.setStatus(clientDetail.getStatus());
return response;
}
public ProcessedClientDetail processCreateOIDCClient(ClientDetailCreateRequest createRequest) throws NoSuchAlgorithmException {
String publicKey = getJWKString(createRequest.getPublicKey());
String clientId = CryptoUtil.encodeToURLSafeBase64(HMACUtils2.generateHash(publicKey.getBytes()));
Optional result = clientDetailRepository.findById(clientId);
if (result.isPresent()) {
LOGGER.error("createOIDCClient::Client with name {} already exists", createRequest.getName());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.DUPLICATE_CLIENT.getErrorCode(),
ErrorCode.DUPLICATE_CLIENT.getErrorMessage());
}
Optional partner = partnerRepository.findById(createRequest.getAuthPartnerId());
if(partner.isEmpty()) {
LOGGER.error("createOIDCClient::AuthPartner with Id {} doesn't exists", createRequest.getAuthPartnerId());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.INVALID_PARTNERID.getErrorCode(), String
.format(ErrorCode.INVALID_PARTNERID.getErrorMessage(), createRequest.getAuthPartnerId()));
}
if(!partner.get().getPartnerTypeCode().equalsIgnoreCase(AUTH_PARTNER_TYPE)) {
LOGGER.error("createOIDCClient::{} cannot create OIDC Client", partner.get().getPartnerTypeCode());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.INVALID_PARTNER_TYPE.getErrorCode(), String
.format(ErrorCode.INVALID_PARTNER_TYPE.getErrorMessage(), partner.get().getPartnerTypeCode()));
}
//check if Partner is Active or not
if (!partner.get().getIsActive()) {
LOGGER.error("createOIDCClient::Partner is not Active with id {}", clientId);
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.PARTNER_NOT_ACTIVE_EXCEPTION.getErrorCode(),
ErrorCode.PARTNER_NOT_ACTIVE_EXCEPTION.getErrorMessage());
}
Optional policyFromDb = authPolicyRepository.findById(createRequest.getPolicyId());
if (!policyFromDb.isPresent()) {
LOGGER.error("createOIDCClient::Policy with Id {} not exists", createRequest.getPolicyId());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.POLICY_NOT_EXIST.getErrorCode(),
ErrorCode.POLICY_NOT_EXIST.getErrorMessage());
}
AuthPolicy policy = policyFromDb.get();
if(!policy.getPolicy_type().equals(AUTH_POLICY_TYPE)) {
LOGGER.error("createOIDCClient::Policy Type Mismatch. {} policy cannot be used to create OIDC Client",policy.getPolicy_type());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.PARTNER_POLICY_TYPE_MISMATCH.getErrorCode(), String
.format(ErrorCode.PARTNER_POLICY_TYPE_MISMATCH.getErrorMessage()));
}
List policyMappingReqFromDb = partnerPolicyRequestRepository
.findByPartnerIdAndPolicyId(createRequest.getAuthPartnerId(), policyFromDb.get().getId());
if (policyMappingReqFromDb.isEmpty()) {
LOGGER.error("createOIDCClient::Policy and partner mapping not exists for policy {} and partner {}",
createRequest.getPolicyId(), createRequest.getAuthPartnerId());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(),
clientId);
throw new PartnerServiceException(ErrorCode.PARTNER_POLICY_MAPPING_NOT_EXISTS.getErrorCode(),
ErrorCode.PARTNER_POLICY_MAPPING_NOT_EXISTS.getErrorMessage());
}
List approvedMappedPolicy = partnerPolicyRequestRepository
.findByPartnerIdAndPolicyIdAndStatusCode(partner.get().getUserId(), policy.getId(), PartnerConstants.APPROVED);
if (approvedMappedPolicy.isEmpty()) {
LOGGER.error("createOIDCClient::Policy and partner mapping is not approved for policy {} and partner {} and status {}"
, createRequest.getPolicyId(), createRequest.getAuthPartnerId());
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE, createRequest.getName(), clientId);
throw new PartnerServiceException(ErrorCode.PARTNER_POLICY_NOT_APPROVED.getErrorCode(), ErrorCode.PARTNER_POLICY_NOT_APPROVED.getErrorMessage());
}
ClientDetail clientDetail = new ClientDetail();
clientDetail.setPublicKey(publicKey);
clientDetail.setId(clientId);
clientDetail.setName(createRequest.getName());
clientDetail.setRpId(createRequest.getAuthPartnerId());
clientDetail.setPolicyId(createRequest.getPolicyId());
clientDetail.setLogoUri(createRequest.getLogoUri());
clientDetail.setRedirectUris(String.join(",", createRequest.getRedirectUris()));
Set claims = authenticationContextClassRefUtil.getPolicySupportedClaims(getReqAttributeFromPolicyJson(
getPolicyObject(policyFromDb.get().getPolicyFileId()), ALLOWED_KYC_ATTRIBUTES, ATTRIBUTE_NAME, null));
if (claims.isEmpty()) {
LOGGER.error(
"createOIDCClient::Partner has no User Claims");
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE);
throw new PartnerServiceException(ErrorCode.PARTNER_HAVING_NO_CLAIMS.getErrorCode(),
ErrorCode.PARTNER_HAVING_NO_CLAIMS.getErrorMessage());
}
clientDetail.setClaims(String.join(",",claims));
Set acrValues = authenticationContextClassRefUtil.getAuthFactors(getReqAttributeFromPolicyJson(
getPolicyObject(policyFromDb.get().getPolicyFileId()), ALLOWED_AUTH_TYPES, AUTH_TYPE, MANDATORY));
if (acrValues.isEmpty()) {
LOGGER.error(
"createOIDCClient::Partner has no User Claims");
auditUtil.setAuditRequestDto(ClientServiceAuditEnum.CREATE_CLIENT_FAILURE);
throw new PartnerServiceException(ErrorCode.PARTNER_HAVING_NO_ACRVALUES.getErrorCode(),
ErrorCode.PARTNER_HAVING_NO_ACRVALUES.getErrorMessage());
}
clientDetail.setAcrValues( String.join(",",acrValues));
clientDetail.setStatus(ACTIVE);
clientDetail.setGrantTypes(String.join(",", createRequest.getGrantTypes()));
clientDetail.setClientAuthMethods(String.join(",", createRequest.getClientAuthMethods()));
clientDetail.setCreatedDateTime(LocalDateTime.now(ZoneId.of("UTC")));
clientDetail.setCreatedBy(getLoggedInUserId());
ProcessedClientDetail processedClientDetail = new ProcessedClientDetail();
processedClientDetail.setClientDetail(clientDetail);
processedClientDetail.setPartner(policyMappingReqFromDb.get(0).getPartner());
processedClientDetail.setPolicy(policyFromDb.get());
return processedClientDetail;
}
/**
*
* @param policyObject
* @param parentAttribute
* @param childAttribute
* @param childAttribute1
* @return
* @throws Exception
*/
private static Set getReqAttributeFromPolicyJson(@NotNull JSONObject policyObject, String parentAttribute,
String childAttribute, String filterAttribute) {
Set attributes = new HashSet<>();
JSONArray parentAttributeObject = (JSONArray) policyObject.get(parentAttribute);
for (int i = 0; i < parentAttributeObject.size(); i++) {
JSONObject childJsonArray = (JSONObject) parentAttributeObject.get(i);
String key = (String) childJsonArray.get(childAttribute);
if (filterAttribute != null && (boolean) childJsonArray.get(filterAttribute)) {
LOGGER.error("createOIDCClient::Policy is having mandatory auth. So client cannot be created.");
throw new PartnerServiceException(ErrorCode.POLICY_HAVING_MANDATORY_AUTHS.getErrorCode(),
ErrorCode.POLICY_HAVING_MANDATORY_AUTHS.getErrorMessage());
}
attributes.add(key.toLowerCase());
}
return attributes;
}
/**
*
* @param request
* @return
* @throws Exception
*/
@SafeVarargs
@SuppressWarnings("unchecked")
private ClientDetailResponse callEsignetService(ClientDetail request, String calleeApi, Boolean isOAuthClient, Map... clientNameLangMap) {
RequestWrapper createRequestwrapper = new RequestWrapper<>();
createRequestwrapper.setRequestTime(DateUtils.getUTCCurrentDateTimeString(CommonConstant.DATE_FORMAT));
CreateClientRequestDto dto = new CreateClientRequestDto();
dto.setClientId(request.getId());
dto.setClientName(request.getName());
dto.setRelyingPartyId(request.getRpId());
dto.setLogoUri(request.getLogoUri());
try {
dto.setPublicKey(objectMapper.readValue(request.getPublicKey(), Map.class));
} catch (JsonProcessingException e) {
LOGGER.error("Error processing public key JSON: {}", e.getMessage());
}
dto.setUserClaims(convertStringToList(request.getClaims()));
dto.setAuthContextRefs(convertStringToList(request.getAcrValues()));
dto.setRedirectUris(convertStringToList(request.getRedirectUris()));
dto.setGrantTypes(convertStringToList(request.getGrantTypes()));
dto.setClientAuthMethods(convertStringToList(request.getClientAuthMethods()));
if(Boolean.TRUE.equals(isOAuthClient) && clientNameLangMap.length>0) {
CreateClientRequestDtoV2 dtoV2 = new CreateClientRequestDtoV2(dto,clientNameLangMap[0]);
createRequestwrapper.setRequest(dtoV2);
}
else createRequestwrapper.setRequest(dto);
return makeCreateEsignetServiceCall(createRequestwrapper, calleeApi);
}
@SafeVarargs
private void makeUpdateEsignetServiceCall(ClientDetail request, String calleeApi, Boolean isOAuthClient, Map... clientNameLangMap) {
RequestWrapper updateRequestwrapper = new RequestWrapper<>();
updateRequestwrapper.setRequestTime(DateUtils.getUTCCurrentDateTimeString(CommonConstant.DATE_FORMAT));
UpdateClientRequestDto updateRequest = mapUpdateClientRequestDto(request);
if(Boolean.TRUE.equals(isOAuthClient) && clientNameLangMap.length>0) {
UpdateClientRequestDtoV2 updateRequestV2 = new UpdateClientRequestDtoV2(updateRequest, clientNameLangMap[0]);
updateRequestwrapper.setRequest(updateRequestV2);
}
else updateRequestwrapper.setRequest(updateRequest);
List pathsegments = new ArrayList<>();
pathsegments.add(request.getId());
try {
restUtil.putApi(calleeApi, pathsegments, null, null, MediaType.APPLICATION_JSON, updateRequestwrapper, Map.class);
}catch (Exception e) {
LOGGER.error("callIdpService::Error from idp service {} ", e.getMessage(), e);
throw new ApiAccessibleException(ApiAccessibleExceptionConstant.UNABLE_TO_PROCESS.getErrorCode(),
ApiAccessibleExceptionConstant.UNABLE_TO_PROCESS.getErrorMessage() + e.getMessage());
}
}
private UpdateClientRequestDto mapUpdateClientRequestDto(ClientDetail request) {
UpdateClientRequestDto updateRequest = new UpdateClientRequestDto();
updateRequest.setClientAuthMethods(convertStringToList(request.getClientAuthMethods()));
updateRequest.setClientName(request.getName());
updateRequest.setGrantTypes(convertStringToList(request.getGrantTypes()));
updateRequest.setLogoUri(request.getLogoUri());
updateRequest.setRedirectUris(convertStringToList(request.getRedirectUris()));
updateRequest.setStatus(request.getStatus());
updateRequest.setUserClaims(convertStringToList(request.getClaims()));
updateRequest.setAuthContextRefs(convertStringToList(request.getAcrValues()));
return updateRequest;
}
/**
*
* @param request
* @param calleeApi
* @return
*/
private ClientDetailResponse makeCreateEsignetServiceCall(Object request, String calleeApi) {
ClientDetailResponse response = null;
Map idpClientResponse = restUtil.postApi(calleeApi, null, "", "", MediaType.APPLICATION_JSON,
request, Map.class);
try {
response = objectMapper.readValue(objectMapper.writeValueAsString(idpClientResponse.get("response")),
ClientDetailResponse.class);
} catch (Exception e) {
LOGGER.error("callIdpService::Error from idp service {} ", e.getMessage(), e);
throw new ApiAccessibleException(ApiAccessibleExceptionConstant.UNABLE_TO_PROCESS.getErrorCode(),
ApiAccessibleExceptionConstant.UNABLE_TO_PROCESS.getErrorMessage() + e.getMessage());
}
if (response == null && idpClientResponse.containsKey(PartnerConstants.ERRORS)) {
@SuppressWarnings("unchecked")
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy