From 75fef2993ebd69e04dda3d0066e003cec30c4a87 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Thu, 15 Jun 2023 19:03:30 +0530 Subject: [PATCH 01/13] [ES-3] changes for web auth api's for consent --- consent-service-impl/pom.xml | 33 +++ .../esignet/config/ModelMapperConfig.java | 24 +++ .../mosip/esignet/entity/ConsentDetail.java | 71 +++++++ .../mosip/esignet/entity/ConsentHistory.java | 73 +++++++ .../mosip/esignet/mapper/ConsentMapper.java | 41 ++++ .../mapper/CustomConsentHistoryMapping.java | 16 ++ .../mapper/CustomConsentRequestMapping.java | 15 ++ .../converter/ClaimsToStringConverter.java | 25 +++ .../converter/ListToStringConverter.java | 18 ++ .../converter/MapToStringConverter.java | 28 +++ .../converter/StringToClaimsConverter.java | 27 +++ .../converter/StringToListConverter.java | 20 ++ .../converter/StringToMapConverter.java | 33 +++ .../repository/ConsentHistoryRepository.java | 15 ++ .../esignet/repository/ConsentRepository.java | 14 ++ .../esignet/services/ConsentServiceImpl.java | 84 ++++++++ .../esignet/ConsentDetailRepositoryTest.java | 171 +++++++++++++++ .../mosip/esignet/ConsentServiceImplTest.java | 138 ++++++++++++ .../io/mosip/esignet/TestApplication.java | 36 ++++ .../src/test/resources/bootstrap.properties | 17 ++ .../src/test/resources/schema.sql | 30 +++ db_scripts/mosip_esignet/ddl.sql | 2 + .../mosip_esignet/ddl/esignet-consent.sql | 47 +++++ .../ddl/esignet-consent_history.sql | 45 ++++ esignet-core/pom.xml | 2 +- .../esignet/core/dto/AuthResponseV2.java | 16 ++ .../mosip/esignet/core/dto/ConsentDetail.java | 24 +++ .../core/dto/LinkedConsentRequestV2.java | 31 +++ .../core/dto/LinkedKycAuthResponseV2.java | 10 + .../esignet/core/dto/OIDCTransaction.java | 2 + .../mosip/esignet/core/dto/UserConsent.java | 21 ++ .../esignet/core/dto/UserConsentRequest.java | 9 + .../core/spi/AuthorizationService.java | 8 +- .../esignet/core/spi/ConsentService.java | 27 +++ .../core/spi/LinkedAuthorizationService.java | 15 +- .../io/mosip/esignet/api/util/Action.java | 4 +- .../mosip/esignet/api/util/ConsentAction.java | 6 + esignet-service/pom.xml | 5 + .../controllers/AuthorizationController.java | 15 ++ .../AuthorizationControllerTest.java | 118 ++++++++++- .../services/AuthorizationServiceImpl.java | 67 ++++-- .../services/ConsentHelperService.java | 197 ++++++++++++++++++ .../LinkedAuthorizationServiceImpl.java | 123 +++++++---- .../services/AuthorizationServiceTest.java | 3 + pom.xml | 2 + 45 files changed, 1662 insertions(+), 66 deletions(-) create mode 100644 consent-service-impl/pom.xml create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentHistoryRepository.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java create mode 100644 consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java create mode 100644 consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java create mode 100644 consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java create mode 100644 consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java create mode 100644 consent-service-impl/src/test/resources/bootstrap.properties create mode 100644 consent-service-impl/src/test/resources/schema.sql create mode 100644 db_scripts/mosip_esignet/ddl/esignet-consent.sql create mode 100644 db_scripts/mosip_esignet/ddl/esignet-consent_history.sql create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/AuthResponseV2.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedConsentRequestV2.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsentRequest.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java create mode 100644 esignet-integration-api/src/main/java/io/mosip/esignet/api/util/ConsentAction.java create mode 100644 oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java diff --git a/consent-service-impl/pom.xml b/consent-service-impl/pom.xml new file mode 100644 index 000000000..d7fec3935 --- /dev/null +++ b/consent-service-impl/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + io.mosip.esignet + esignet-parent + 1.0.0-SNAPSHOT + + + consent-service-impl + + + 11 + 11 + UTF-8 + ${project.version} + + + + io.mosip.esignet + esignet-core + ${esignet.core.version} + + + + org.modelmapper + modelmapper + 3.1.1 + + + \ No newline at end of file diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java b/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java new file mode 100644 index 000000000..bb86407a5 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java @@ -0,0 +1,24 @@ +package io.mosip.esignet.config; + + +import io.mosip.esignet.mapper.ConsentMapper; +import io.mosip.esignet.services.ConsentServiceImpl; +import org.modelmapper.ModelMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +public class ModelMapperConfig { + + @Bean + public ModelMapper modelMapper() { + return new ModelMapper(); + } + + @Bean + public ConsentMapper consentMapper() { + return new ConsentMapper(); + } + +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java new file mode 100644 index 000000000..47c2f9c70 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java @@ -0,0 +1,71 @@ +package io.mosip.esignet.entity; + +import lombok.*; +import org.hibernate.Hibernate; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.UUID; + +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLIENT_ID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +public class ConsentDetail { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private UUID id; + + @NotNull(message = INVALID_CLIENT_ID) + @Column(name = "client_id") + private String clientId; + + @NotNull + @Column(name = "psu_token") + private String psuToken; + + @NotNull(message = INVALID_CLAIM) + @Column(name = "claims") + private String claims; + + @NotNull + @Column(name = "authorization_scopes") + private String authorizationScopes; + + @NotNull + @Column(name = "cr_dtimes") + private LocalDateTime createdtimes; + + @Column(name = "expire_dtimes") + private LocalDateTime expiredtimes; + + @Column(name = "signature") + private String signature; + + @Column(name = "hash") + private String hash; + + @Column(name = "accepted_claims") + private String acceptedClaims; + + @Column(name = "permitted_scopes") + private String permittedScopes; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + ConsentDetail consentDetail = (ConsentDetail) o; + return getId() != null && Objects.equals(getId(), consentDetail.getId()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java new file mode 100644 index 000000000..3539fb2f2 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java @@ -0,0 +1,73 @@ +package io.mosip.esignet.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.Hibernate; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.UUID; + +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLIENT_ID; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity +public class ConsentHistory { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private UUID id; + + @NotNull(message = INVALID_CLIENT_ID) + @Column(name = "client_id") + private String clientId; + + @NotNull + @Column(name = "psu_token") + private String psuToken; + + @NotNull(message = INVALID_CLAIM) + @Column(name = "claims") + private String claims; + + @NotNull + @Column(name = "authorization_scopes") + private String authorizationScopes; + + @NotNull + @Column(name = "cr_dtimes") + private LocalDateTime createdtimes; + + @Column(name = "expire_dtimes") + private LocalDateTime expiredtimes; + + @Column(name = "signature") + private String signature; + + @Column(name = "hash") + private String hash; + + @Column(name = "accepted_claims") + private String acceptedClaims; + + @Column(name = "permitted_scopes") + private String permittedScopes; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + ConsentHistory consentDetail = (ConsentHistory) o; + return getId() != null && Objects.equals(getId(), consentDetail.getId()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java new file mode 100644 index 000000000..047e2e362 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java @@ -0,0 +1,41 @@ +package io.mosip.esignet.mapper; + +import io.mosip.esignet.core.dto.ConsentDetail; +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.entity.ConsentHistory; +import io.mosip.esignet.mapper.converter.*; +import org.modelmapper.ModelMapper; + + + +public class ConsentMapper { + private static final ModelMapper modelMapper = new ModelMapper(); + + static { + modelMapper.addConverter(new ClaimsToStringConverter()); + modelMapper.addConverter(new StringToClaimsConverter()); + modelMapper.addConverter(new MapToStringConverter()); + modelMapper.addConverter(new StringToMapConverter()); + modelMapper.addConverter(new ListToStringConverter()); + modelMapper.addConverter(new StringToListConverter()); + modelMapper.addMappings(new CustomConsentRequestMapping()); + modelMapper.addMappings(new CustomConsentHistoryMapping()); + //modelMapper.getConfiguration().setSkipNullEnabled(true); + } + + public static io.mosip.esignet.entity.ConsentDetail toEntity(ConsentDetail consentDetailDTo) { + return modelMapper.map(consentDetailDTo, io.mosip.esignet.entity.ConsentDetail.class); + } + + public static io.mosip.esignet.entity.ConsentDetail toEntity(UserConsent userConsent) { + return modelMapper.map(userConsent, io.mosip.esignet.entity.ConsentDetail.class); + } + + public static ConsentDetail toDto(io.mosip.esignet.entity.ConsentDetail consentDetail) { + return modelMapper.map(consentDetail, ConsentDetail.class); + } + + public static ConsentHistory toConsentHistoryEntity(UserConsent userConsent){ + return modelMapper.map(userConsent, ConsentHistory.class); + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java new file mode 100644 index 000000000..c5cbbe84a --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java @@ -0,0 +1,16 @@ +package io.mosip.esignet.mapper; + +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.entity.ConsentDetail; +import io.mosip.esignet.entity.ConsentHistory; +import org.modelmapper.PropertyMap; + +public class CustomConsentHistoryMapping extends PropertyMap { + @Override + protected void configure() { + // Skip the 'id' field when mapping + skip().setId(null); + } +} + + diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java new file mode 100644 index 000000000..40b0ebf75 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java @@ -0,0 +1,15 @@ +package io.mosip.esignet.mapper; + +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.entity.ConsentDetail; +import org.modelmapper.PropertyMap; + +public class CustomConsentRequestMapping extends PropertyMap { + @Override + protected void configure() { + // Skip the 'id' field when mapping + skip().setId(null); + } +} + + diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java new file mode 100644 index 000000000..62a01aa9e --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java @@ -0,0 +1,25 @@ +package io.mosip.esignet.mapper.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.core.exception.EsignetException; +import lombok.extern.slf4j.Slf4j; +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; + +@Slf4j +public class ClaimsToStringConverter implements Converter { + private static final ObjectMapper objectMapper = new ObjectMapper(); + @Override + public String convert(MappingContext context) { + Claims claims = context.getSource(); + try { + return claims != null ? objectMapper.writeValueAsString(claims) : ""; + } catch (JsonProcessingException e) { + throw new EsignetException(INVALID_CLAIM); + } + } +} \ No newline at end of file diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java new file mode 100644 index 000000000..c43a16521 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java @@ -0,0 +1,18 @@ +package io.mosip.esignet.mapper.converter;/* + * 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/. + */ + +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import java.util.List; + +public class ListToStringConverter implements Converter, String> { + @Override + public String convert(MappingContext, String> context) { + List source = context.getSource(); + return source == null ? "" : String.join(",", context.getSource()); + } +} \ No newline at end of file diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java new file mode 100644 index 000000000..9919704b8 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java @@ -0,0 +1,28 @@ +package io.mosip.esignet.mapper.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.ClaimDetail; +import io.mosip.esignet.core.exception.EsignetException; +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import java.util.Map; + +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_PERMITTED_SCOPE; + +public class MapToStringConverter implements Converter,String> { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public String convert(MappingContext, String> mappingContext) { + Map map = mappingContext.getSource(); + try{ + return map!=null?objectMapper.writeValueAsString(map):""; + }catch (JsonProcessingException e) { + throw new EsignetException(INVALID_PERMITTED_SCOPE); + } + } +} \ No newline at end of file diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java new file mode 100644 index 000000000..60b43ceb5 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java @@ -0,0 +1,27 @@ +package io.mosip.esignet.mapper.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.core.exception.EsignetException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; + +@Slf4j +public class StringToClaimsConverter implements Converter +{ + private static final ObjectMapper objectMapper = new ObjectMapper(); + @Override + public Claims convert(MappingContext context) { + String claims = context.getSource(); + try { + return StringUtils.isNotBlank(claims) ? objectMapper.readValue(claims, Claims.class) : null; + } catch (JsonProcessingException e) { + throw new EsignetException(INVALID_CLAIM); + } + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java new file mode 100644 index 000000000..bd0a0d8f5 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java @@ -0,0 +1,20 @@ +package io.mosip.esignet.mapper.converter;/* + * 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/. + */ + +import org.apache.commons.lang3.StringUtils; +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import java.util.Arrays; +import java.util.List; + +public class StringToListConverter implements Converter> { + @Override + public List convert(MappingContext> context) { + String source = context.getSource(); + return StringUtils.isEmpty(source) ? List.of(): Arrays.asList(context.getSource().split(",")); + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java new file mode 100644 index 000000000..bd8908353 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java @@ -0,0 +1,33 @@ +package io.mosip.esignet.mapper.converter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.core.exception.EsignetException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.modelmapper.Converter; +import org.modelmapper.spi.MappingContext; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; +import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_PERMITTED_SCOPE; + +@Slf4j +public class StringToMapConverter implements Converter> { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public Map convert(MappingContext> mappingContext) { + String authorizeScopes= mappingContext.getSource(); + try{ + return StringUtils.isNotBlank(authorizeScopes) ? objectMapper.readValue(authorizeScopes,Map.class): Collections.emptyMap(); + } catch (JsonProcessingException e) { + throw new EsignetException(INVALID_PERMITTED_SCOPE); + } + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentHistoryRepository.java b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentHistoryRepository.java new file mode 100644 index 000000000..11daeaae1 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentHistoryRepository.java @@ -0,0 +1,15 @@ +/* + * 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.repository; + + + +import io.mosip.esignet.entity.ConsentHistory; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ConsentHistoryRepository extends JpaRepository{ + +} \ No newline at end of file diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java new file mode 100644 index 000000000..a8cfe4bef --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java @@ -0,0 +1,14 @@ +package io.mosip.esignet.repository; + +import io.mosip.esignet.entity.ConsentDetail; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.Optional; +import java.util.UUID; +@Repository +public interface ConsentRepository extends JpaRepository { + Optional findFirstByClientIdAndPsuTokenOrderByCreatedtimesDesc(String clientId, String psuToken); + Optional findByClientIdAndPsuToken(String clientId, String psuToken); + void deleteByClientIdAndPsuToken(String clientId, String psuToken); + +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java new file mode 100644 index 000000000..b66aecff4 --- /dev/null +++ b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java @@ -0,0 +1,84 @@ +package io.mosip.esignet.services; + + +import io.mosip.esignet.api.spi.AuditPlugin; +import io.mosip.esignet.api.util.Action; +import io.mosip.esignet.api.util.ActionStatus; +import io.mosip.esignet.core.dto.ConsentDetail; +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.core.dto.UserConsentRequest; +import io.mosip.esignet.core.spi.ConsentService; +import io.mosip.esignet.core.util.AuditHelper; +import io.mosip.esignet.entity.ConsentHistory; +import io.mosip.esignet.mapper.ConsentMapper; +import io.mosip.esignet.repository.ConsentHistoryRepository; +import io.mosip.esignet.repository.ConsentRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.util.Optional; + +@Service +@Slf4j +public class ConsentServiceImpl implements ConsentService { + + @Autowired + private ConsentRepository consentRepository; + + @Autowired + private ConsentHistoryRepository consentHistoryRepository; + + @Autowired + private AuditPlugin auditWrapper; + + @Value("${mosip.esignet.audit.claim-name:preferred_username}") + private String claimName; + + @Override + public Optional getUserConsent(UserConsentRequest userConsentRequest) { + + Optional consentOptional = consentRepository. + findByClientIdAndPsuToken(userConsentRequest.getClientId(), + userConsentRequest.getPsuToken()); + if (consentOptional.isPresent()) { + ConsentDetail consentDetailDto = ConsentMapper.toDto( consentOptional.get()); + + return Optional.of(consentDetailDto); + } + auditWrapper.logAudit(AuditHelper.getClaimValue(SecurityContextHolder.getContext(), claimName), + Action.GET_USER_CONSENT, ActionStatus.SUCCESS, + AuditHelper.buildAuditDto(userConsentRequest.getClientId()), null); + return Optional.empty(); + } + + @Override + @Transactional + public ConsentDetail saveUserConsent(UserConsent userConsent) { + Optional ClientDetailOptional = + consentRepository.findByClientIdAndPsuToken(userConsent.getClientId(), userConsent.getPsuToken()); + if(ClientDetailOptional.isPresent()) { + consentRepository.deleteByClientIdAndPsuToken(userConsent.getClientId(), userConsent.getPsuToken()); + } + LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); + //convert ConsentRequest to Entity + ConsentHistory consentHistory = ConsentMapper.toConsentHistoryEntity(userConsent); + consentHistory.setCreatedtimes(now); + consentHistoryRepository.save(consentHistory); + + io.mosip.esignet.entity.ConsentDetail consentDetail =ConsentMapper.toEntity(userConsent); + consentDetail.setCreatedtimes(now); + + ConsentDetail consentDetailDto =ConsentMapper.toDto(consentRepository.save(consentDetail)); + auditWrapper.logAudit(AuditHelper.getClaimValue(SecurityContextHolder.getContext(), claimName), + Action.SAVE_USER_CONSENT, ActionStatus.SUCCESS, + AuditHelper.buildAuditDto(userConsent.getClientId()), null); + return consentDetailDto; + } +} diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java new file mode 100644 index 000000000..0098fe06e --- /dev/null +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java @@ -0,0 +1,171 @@ +package io.mosip.esignet; + +import io.mosip.esignet.entity.ConsentDetail; +import io.mosip.esignet.repository.ConsentRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.validation.ConstraintViolationException; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.UUID; + +@RunWith(SpringRunner.class) +@DataJpaTest +public class ConsentDetailRepositoryTest { + + @Autowired + private ConsentRepository consentRepository; + + @Test + public void createConsent_withValidDetail_thenPass() { + + ConsentDetail consentDetail =new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + LocalDateTime date = LocalDateTime.of(2019, 12, 12, 12, 12, 12); + consentDetail.setClientId("123"); + consentDetail.setPsuToken("abc"); + consentDetail.setClaims("claims"); + consentDetail.setAuthorizationScopes("authorizationScopes"); + consentDetail.setCreatedtimes(date); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + consentDetail.setHash("hash"); + consentDetail.setAcceptedClaims("claim"); + consentDetail.setPermittedScopes("scope"); + consentDetail =consentRepository.save(consentDetail); + Assert.assertNotNull(consentDetail); + + Optional result; + + result = consentRepository.findFirstByClientIdAndPsuTokenOrderByCreatedtimesDesc("123", "abc"); + Assert.assertTrue(result.isPresent()); + + result = consentRepository.findFirstByClientIdAndPsuTokenOrderByCreatedtimesDesc("123", "abcd"); + Assert.assertFalse(result.isPresent()); + } + + @Test + public void createConsent_withNullClientId_thenFail() { + + ConsentDetail consentDetail = new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + LocalDateTime date = LocalDateTime.of(2019, 12, 12, 12, 12, 12); + consentDetail.setId(uuid); + consentDetail.setClientId(null); + consentDetail.setPsuToken("abc"); + consentDetail.setClaims("claims"); + consentDetail.setAuthorizationScopes("authorizationScopes"); + consentDetail.setCreatedtimes(date); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + try { + consentRepository.saveAndFlush(consentDetail); + } catch (ConstraintViolationException e) { + Assert.assertTrue(e.getConstraintViolations().stream() + .anyMatch( v -> v.getPropertyPath().toString().equals("clientId"))); + return; + } + Assert.fail(); + } + + @Test + public void createConsent_withNullPsuValue_thenFail() { + + ConsentDetail consentDetail = new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + LocalDateTime date = LocalDateTime.of(2019, 12, 12, 12, 12, 12); + consentDetail.setId(uuid); + consentDetail.setClientId("123"); + consentDetail.setPsuToken(null); + consentDetail.setClaims("claims"); + consentDetail.setAuthorizationScopes("authorizationScopes"); + consentDetail.setCreatedtimes(date); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + try { + consentRepository.saveAndFlush(consentDetail); + } catch (ConstraintViolationException e) { + Assert.assertTrue(e.getConstraintViolations().stream() + .anyMatch( v -> v.getPropertyPath().toString().equals("psuToken"))); + return; + } + Assert.fail(); + } + + @Test + public void createConsent_withNullClaims_thenFail() { + + ConsentDetail consentDetail = new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + LocalDateTime date = LocalDateTime.of(2019, 12, 12, 12, 12, 12); + consentDetail.setId(uuid); + consentDetail.setClientId("123"); + consentDetail.setPsuToken("abc"); + consentDetail.setClaims(null); + consentDetail.setAuthorizationScopes("authorizationScopes"); + consentDetail.setCreatedtimes(date); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + try { + consentRepository.saveAndFlush(consentDetail); + } catch (ConstraintViolationException e) { + Assert.assertTrue(e.getConstraintViolations().stream() + .anyMatch( v -> v.getPropertyPath().toString().equals("claims"))); + return; + } + Assert.fail(); + } + + @Test + public void createConsent_withNullAuthorizationScopes_thenFail() { + + ConsentDetail consentDetail = new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + LocalDateTime date = LocalDateTime.of(2019, 12, 12, 12, 12, 12); + consentDetail.setId(uuid); + consentDetail.setClientId("123"); + consentDetail.setPsuToken("abc"); + consentDetail.setClaims("claims"); + consentDetail.setAuthorizationScopes(null); + consentDetail.setCreatedtimes(date); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + try { + consentRepository.saveAndFlush(consentDetail); + } catch (ConstraintViolationException e) { + Assert.assertTrue(e.getConstraintViolations().stream() + .anyMatch( v -> v.getPropertyPath().toString().equals("authorizationScopes"))); + return; + } + Assert.fail(); + } + + @Test + public void createConsent_withNullCreatedtimes_thenFail() { + + ConsentDetail consentDetail = new ConsentDetail(); + UUID uuid=UUID.randomUUID(); + consentDetail.setId(uuid); + consentDetail.setClientId("123"); + consentDetail.setPsuToken("abc"); + consentDetail.setClaims("claims"); + consentDetail.setAuthorizationScopes("authorizationScopes"); + consentDetail.setCreatedtimes(null); + consentDetail.setExpiredtimes(LocalDateTime.now()); + consentDetail.setSignature("signature"); + try { + consentRepository.saveAndFlush(consentDetail); + } catch (ConstraintViolationException e) { + Assert.assertTrue(e.getConstraintViolations().stream() + .anyMatch( v -> v.getPropertyPath().toString().equals("createdtimes"))); + return; + } + Assert.fail(); + } + +} diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java new file mode 100644 index 000000000..95d70dc11 --- /dev/null +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java @@ -0,0 +1,138 @@ +package io.mosip.esignet; + +import io.mosip.esignet.api.dto.ClaimDetail; +import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.api.spi.AuditPlugin; +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.core.dto.UserConsentRequest; +import io.mosip.esignet.entity.ConsentDetail; +import io.mosip.esignet.entity.ConsentHistory; +import io.mosip.esignet.repository.ConsentHistoryRepository; +import io.mosip.esignet.repository.ConsentRepository; +import io.mosip.esignet.services.ConsentServiceImpl; +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.modelmapper.MappingException; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +@Slf4j +@RunWith(MockitoJUnitRunner.class) +public class ConsentServiceImplTest { + + + @Mock + ConsentRepository consentRepository; + + @Mock + ConsentHistoryRepository consentHistoryRepository; + + @Mock + AuditPlugin auditWrapper; + + @InjectMocks + ConsentServiceImpl consentService; + + + + @Test + public void getUserConsent_withValidDetails_thenPass() throws Exception{ + ConsentDetail consentDetail = new ConsentDetail(); + consentDetail.setId(UUID.randomUUID()); + consentDetail.setClientId("1234"); + consentDetail.setClaims("{\"userinfo\":{\"given_name\":{\"essential\":true},\"phone_number\":null,\"email\":{\"essential\":true},\"picture\":{\"essential\":false},\"gender\":{\"essential\":false}},\"id_token\":{}}"); + consentDetail.setCreatedtimes(LocalDateTime.now()); + consentDetail.setPsuToken("psuValue"); + consentDetail.setExpiredtimes(LocalDateTime.now()); + + Optional consentOptional = Optional.of(consentDetail); + Mockito.when(consentRepository.findByClientIdAndPsuToken(Mockito.anyString(),Mockito.anyString())).thenReturn(consentOptional); + + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId("1234"); + userConsentRequest.setPsuToken("psuValue"); + + Optional userConsentDto = consentService.getUserConsent(userConsentRequest); + Assert.assertNotNull(userConsentDto); + Assert.assertEquals("1234", userConsentDto.get().getClientId()); + Assert.assertEquals("psuValue", userConsentDto.get().getPsuToken()); + + } + + @Test + public void getUserConsent_withInValidClaimsDetails_thenFail() { + ConsentDetail consentDetail = new ConsentDetail(); + consentDetail.setId(UUID.randomUUID()); + consentDetail.setClientId("1234"); + consentDetail.setCreatedtimes(LocalDateTime.now()); + consentDetail.setClaims("claims"); + consentDetail.setPsuToken("psuValue"); + consentDetail.setExpiredtimes(LocalDateTime.now()); + + Optional consentOptional = Optional.of(consentDetail); + Mockito.when(consentRepository.findByClientIdAndPsuToken(Mockito.anyString(),Mockito.anyString())).thenReturn(consentOptional); + + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId("1234"); + userConsentRequest.setPsuToken("psuValue"); + try{ + Optional userConsentDto = consentService.getUserConsent(userConsentRequest); + Assert.fail(); + }catch (MappingException e){ + Assert.assertTrue(true); + } + } + + @Test + public void saveUserConsent_withValidDetails_thenPass() throws Exception{ + Claims claims = new Claims(); + + Map userinfo = new HashMap<>(); + Map id_token = new HashMap<>(); + ClaimDetail userinfoClaimDetail = new ClaimDetail("value1", new String[]{"value1a", "value1b"}, true); + ClaimDetail idTokenClaimDetail = new ClaimDetail("value2", new String[]{"value2a", "value2b"}, false); + userinfo.put("userinfoKey", userinfoClaimDetail); + id_token.put("idTokenKey", idTokenClaimDetail); + claims.setUserinfo(userinfo); + claims.setId_token(id_token); + + + UserConsent userConsent = new UserConsent(); + userConsent.setClientId("1234"); + userConsent.setPsuToken("psuValue"); + userConsent.setClaims(claims); + + Map authorizeScopes = Map.of("given_name",true,"email",true); + userConsent.setAuthorizationScopes(authorizeScopes); + userConsent.setExpiry_dtimes(LocalDateTime.now()); + userConsent.setSignature("signature"); + + ConsentDetail consentDetail = new ConsentDetail(); + consentDetail.setId(UUID.randomUUID()); + consentDetail.setClientId("1234"); + consentDetail.setClaims("{\"userinfo\":{\"given_name\":{\"essential\":true},\"phone_number\":null,\"email\":{\"essential\":true},\"picture\":{\"essential\":false},\"gender\":{\"essential\":false}},\"id_token\":{}}"); + consentDetail.setCreatedtimes(LocalDateTime.now()); + consentDetail.setPsuToken("psuValue"); + consentDetail.setExpiredtimes(LocalDateTime.now()); + + Mockito.when(consentRepository.save(Mockito.any())).thenReturn(consentDetail); + Mockito.when(consentHistoryRepository.save(Mockito.any())).thenReturn(new ConsentHistory()); + Mockito.when(consentRepository.findByClientIdAndPsuToken(Mockito.any(),Mockito.any())).thenReturn(Optional.empty()); + io.mosip.esignet.core.dto.ConsentDetail userConsentDtoDetail = consentService.saveUserConsent(userConsent); + Assert.assertNotNull(userConsentDtoDetail); + Assert.assertEquals("1234", userConsentDtoDetail.getClientId()); + + } + + +} diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java b/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java new file mode 100644 index 000000000..455fc1808 --- /dev/null +++ b/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java @@ -0,0 +1,36 @@ +package io.mosip.esignet; + +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 lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ActiveProfiles; + +@Slf4j +@SpringBootApplication +@ActiveProfiles(value = {"test"}) +public class TestApplication { + public static void main(String[] args) { + SpringApplication.run(TestApplication.class, args); + } + + @Bean + public AuditPlugin loggerAuditWrapper() { + return new AuditPlugin() { + @Override + public void logAudit(Action action, ActionStatus status, AuditDTO audit, Throwable t) { + //do nothing + } + + @Override + public void logAudit(String username, Action action, ActionStatus status, AuditDTO audit, Throwable t) { + //do nothing + } + }; + } + +} diff --git a/consent-service-impl/src/test/resources/bootstrap.properties b/consent-service-impl/src/test/resources/bootstrap.properties new file mode 100644 index 000000000..a4d9bc37e --- /dev/null +++ b/consent-service-impl/src/test/resources/bootstrap.properties @@ -0,0 +1,17 @@ +spring.profiles.active=test +server.port=8088 +##----------------------------------------- Database properties ------------------------------------------- + +spring.jpa.defer-datasource-initialization=false +spring.jpa.hibernate.ddl-auto=none +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.format_sql=true +#Enabling H2 console +spring.h2.console.enabled=false +spring.datasource.url=jdbc:h2:mem:mosip_idp +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=test +spring.datasource.password=test + +spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/consent-service-impl/src/test/resources/schema.sql b/consent-service-impl/src/test/resources/schema.sql new file mode 100644 index 000000000..4e1388419 --- /dev/null +++ b/consent-service-impl/src/test/resources/schema.sql @@ -0,0 +1,30 @@ +create table consent_history ( + id UUID NOT NULL, + client_id VARCHAR NOT NULL, + psu_token VARCHAR NOT NULL, + claims VARCHAR NOT NULL, + authorization_scopes VARCHAR NOT NULL, + cr_dtimes TIMESTAMP DEFAULT NOW() NOT NULL, + expire_dtimes TIMESTAMP, + signature VARCHAR, + hash VARCHAR, + accepted_claims VARCHAR, + permitted_scopes VARCHAR, + PRIMARY KEY (id) +); +create table consent_detail ( + id UUID NOT NULL, + client_id VARCHAR NOT NULL, + psu_token VARCHAR NOT NULL, + claims VARCHAR NOT NULL, + authorization_scopes VARCHAR NOT NULL, + cr_dtimes TIMESTAMP DEFAULT NOW() NOT NULL, + expire_dtimes TIMESTAMP, + signature VARCHAR, + hash VARCHAR, + accepted_claims VARCHAR, + permitted_scopes VARCHAR, + PRIMARY KEY (id), + CONSTRAINT unique_client_token UNIQUE (client_id, psu_token) +); +CREATE INDEX IF NOT EXISTS idx_consent_psu_client ON consent_detail(psu_token, client_id, cr_dtimes); \ No newline at end of file diff --git a/db_scripts/mosip_esignet/ddl.sql b/db_scripts/mosip_esignet/ddl.sql index e8a413073..0ea32c676 100644 --- a/db_scripts/mosip_esignet/ddl.sql +++ b/db_scripts/mosip_esignet/ddl.sql @@ -5,3 +5,5 @@ \ir ddl/esignet-key_policy_def.sql \ir ddl/esignet-key_store.sql \ir ddl/esignet-public_key_registry.sql +\ir ddl/esignet-consent.sql +\ir ddl/esignet-consent_history.sql diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent.sql b/db_scripts/mosip_esignet/ddl/esignet-consent.sql new file mode 100644 index 000000000..ce941e823 --- /dev/null +++ b/db_scripts/mosip_esignet/ddl/esignet-consent.sql @@ -0,0 +1,47 @@ +-- 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/. +-- ------------------------------------------------------------------------------------------------- +-- Database Name: mosip_esignet +-- Table Name : consent_detail +-- Purpose : To store user consent details +-- +-- Create By : Hitesh C +-- Created Date : May-2023 +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ + +create table consent_detail ( + id UUID NOT NULL, + client_id VARCHAR NOT NULL, + psu_token VARCHAR NOT NULL, + claims VARCHAR NOT NULL, + authorization_scopes VARCHAR NOT NULL, + cr_dtimes TIMESTAMP DEFAULT NOW() NOT NULL, + expire_dtimes TIMESTAMP, + signature VARCHAR, + hash VARCHAR, + accepted_claims VARCHAR, + permitted_scopes VARCHAR, + PRIMARY KEY (id), + CONSTRAINT unique_client_token UNIQUE (client_id, psu_token) +); + +CREATE INDEX IF NOT EXISTS idx_consent_psu_client ON consent_detail(psu_token, client_id); + +COMMENT ON TABLE consent_detail IS 'Contains user consent details'; + +COMMENT ON COLUMN consent_detail.id IS 'UUID : Unique id associated with each consent'; +COMMENT ON COLUMN consent_detail.client_id IS 'Client_id: associated with relying party'; +COMMENT ON COLUMN consent_detail.psu_token IS 'PSU token associated with user consent'; +COMMENT ON COLUMN consent_detail.claims IS 'Json of requested and user accepted claims'; +COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of user accepted authorization scope'; +COMMENT ON COLUMN consent_detail.cr_dtimes IS 'Consent creation date'; +COMMENT ON COLUMN consent_detail.expire_dtimes IS 'Expiration date'; +COMMENT ON COLUMN consent_detail.signature IS 'Signature of consent object '; +COMMENT ON COLUMN consent_detail.hash IS 'hash of consent object' +COMMENT ON COLUMN consent_detail.accepted_claims IS 'Accepted Claims by the user' +COMMENT ON COLUMN consent_detail.permitted_scopes IS 'Accepted Scopes by the user' + diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql new file mode 100644 index 000000000..de64fca13 --- /dev/null +++ b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql @@ -0,0 +1,45 @@ +-- 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/. +-- ------------------------------------------------------------------------------------------------- +-- Database Name: mosip_esignet +-- Table Name : consent_history +-- Purpose : To store user consent details +-- +-- Create By : Hitesh C +-- Created Date : May-2023 +-- +-- Modified Date Modified By Comments / Remarks +-- ------------------------------------------------------------------------------------------ +-- ------------------------------------------------------------------------------------------ + +create table consent_history ( + id UUID NOT NULL, + client_id VARCHAR NOT NULL, + psu_token VARCHAR NOT NULL, + claims VARCHAR NOT NULL, + authorization_scopes VARCHAR NOT NULL, + cr_dtimes TIMESTAMP DEFAULT NOW() NOT NULL, + expire_dtimes TIMESTAMP, + signature VARCHAR, + hash VARCHAR, + accepted_claims VARCHAR, + permitted_scopes VARCHAR, + PRIMARY KEY (id) +); +CREATE INDEX IF NOT EXISTS idx_consent_psu_client ON consent_history(psu_token, client_id); + +COMMENT ON TABLE consent_history IS 'Contains user consent details'; + +COMMENT ON COLUMN consent_history.id IS 'UUID : Unique id associated with each consent'; +COMMENT ON COLUMN consent_history.client_id IS 'Client_id: associated with relying party'; +COMMENT ON COLUMN consent_history.psu_token IS 'PSU token associated with user consent'; +COMMENT ON COLUMN consent_history.claims IS 'Json of requested and user accepted claims'; +COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of user accepted authorization scope'; +COMMENT ON COLUMN consent_history.cr_dtimes IS 'Consent creation date'; +COMMENT ON COLUMN consent_history.expire_dtimes IS 'Expiration date'; +COMMENT ON COLUMN consent_history.signature IS 'Signature of consent object '; +COMMENT ON COLUMN consent_history.hash IS 'hash of consent object' +COMMENT ON COLUMN consent_history.accepted_claims IS 'Accepted Claims by the user' +COMMENT ON COLUMN consent_history.permitted_scopes IS 'Accepted Scopes by the user' + diff --git a/esignet-core/pom.xml b/esignet-core/pom.xml index 1433838f7..bf99f9f3c 100644 --- a/esignet-core/pom.xml +++ b/esignet-core/pom.xml @@ -25,7 +25,7 @@ 2.12.0 2.12.0 2.12.0 - 1.2.1-SNAPSHOT + 1.2.0.1-B2 3.27.0-GA 4.13.2 2.22.0 diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/AuthResponseV2.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/AuthResponseV2.java new file mode 100644 index 000000000..8983230a6 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/AuthResponseV2.java @@ -0,0 +1,16 @@ +/* + * 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.core.dto; + +import io.mosip.esignet.api.util.ConsentAction; +import lombok.Data; + +@Data +public class AuthResponseV2 { + + private String transactionId; + private ConsentAction consentAction; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java new file mode 100644 index 000000000..268778643 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java @@ -0,0 +1,24 @@ +package io.mosip.esignet.core.dto; + +import io.mosip.esignet.api.dto.Claims; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Data +public class ConsentDetail { + private UUID id; + private String clientId; + private String psuToken; + private Claims claims; + Map authorizationScopes; + private LocalDateTime createdtimes; + private LocalDateTime expiredtimes; + private String signature; + private String hash; + private List acceptedClaims; + private List permittedScopes; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedConsentRequestV2.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedConsentRequestV2.java new file mode 100644 index 000000000..bc3d66960 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedConsentRequestV2.java @@ -0,0 +1,31 @@ +/* + * 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.core.dto; + +import io.mosip.esignet.core.constants.ErrorConstants; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +@Data +public class LinkedConsentRequestV2 { + + @NotBlank(message = ErrorConstants.INVALID_TRANSACTION_ID) + private String linkedTransactionId; + + /** + * List of accepted claim names by end-user + */ + private List acceptedClaims; + + /** + * List of permitted authorize scopes + */ + private List permittedAuthorizeScopes; + + private String signature; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java new file mode 100644 index 000000000..d7e4d8d23 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java @@ -0,0 +1,10 @@ +package io.mosip.esignet.core.dto; + +import io.mosip.esignet.api.util.ConsentAction; +import lombok.Data; + +@Data +public class LinkedKycAuthResponseV2 { + private String linkedTransactionId; + private ConsentAction consentAction; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java index 9b9a8ab4b..b0e857119 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/OIDCTransaction.java @@ -6,6 +6,7 @@ package io.mosip.esignet.core.dto; import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.util.LinkCodeQueue; import lombok.Data; @@ -47,4 +48,5 @@ public class OIDCTransaction implements Serializable { String individualId; String oauthDetailsHash; + ConsentAction consentAction; } diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java new file mode 100644 index 000000000..74ef88417 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java @@ -0,0 +1,21 @@ +package io.mosip.esignet.core.dto; + +import io.mosip.esignet.api.dto.Claims; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +@Data +public class UserConsent { + String psuToken; + String clientId; + Claims Claims; + Map authorizationScopes; + LocalDateTime expiry_dtimes; + String signature; + String hash; + List acceptedClaims; + List permittedScopes; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsentRequest.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsentRequest.java new file mode 100644 index 000000000..0cc018f09 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsentRequest.java @@ -0,0 +1,9 @@ +package io.mosip.esignet.core.dto; + +import lombok.Data; + +@Data +public class UserConsentRequest { + String psuToken; + String clientId; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/AuthorizationService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/AuthorizationService.java index 1a8f6c980..46269a926 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/spi/AuthorizationService.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/spi/AuthorizationService.java @@ -7,7 +7,6 @@ import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.EsignetException; -import io.mosip.esignet.core.dto.*; public interface AuthorizationService { @@ -33,6 +32,13 @@ public interface AuthorizationService { */ AuthResponse authenticateUser(AuthRequest authRequest) throws EsignetException; + /** + * Authentication request for the required auth-factors + * @param authRequest + * @return + */ + AuthResponseV2 authenticateUserV2(AuthRequest authRequest) throws EsignetException; + /** * Accepted claims are verified and KYC exchange is performed * Redirects to requested redirect_uri diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java new file mode 100644 index 000000000..08d310e7a --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/spi/ConsentService.java @@ -0,0 +1,27 @@ +package io.mosip.esignet.core.spi; + +import io.mosip.esignet.core.dto.ConsentDetail; +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.core.dto.UserConsentRequest; +import io.mosip.esignet.core.exception.EsignetException; + +import java.util.Optional; + +public interface ConsentService { + /** + * Api to get Latest User consent data from consent registry. + * + * @param userConsentRequest Consent Request object containing client_id and psu_token + * @return the Consent wrapped in an {@link Optional} + */ + Optional getUserConsent(UserConsentRequest userConsentRequest); + + /** + * Api to Add User Consent data in Consent Registry + * + * @param userConsent consentRequest Object + * @return {@link ConsentDetail} Consent Response Object after saving the consent to registry. + * + */ + ConsentDetail saveUserConsent(UserConsent userConsent) throws EsignetException; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/LinkedAuthorizationService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/LinkedAuthorizationService.java index ecfa72a6e..9ffaae048 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/spi/LinkedAuthorizationService.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/spi/LinkedAuthorizationService.java @@ -7,7 +7,6 @@ import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.EsignetException; -import io.mosip.esignet.core.dto.*; import org.springframework.web.context.request.async.DeferredResult; public interface LinkedAuthorizationService { @@ -55,6 +54,13 @@ public interface LinkedAuthorizationService { */ LinkedKycAuthResponse authenticateUser(LinkedKycAuthRequest linkedKycAuthRequest) throws EsignetException; + /** + * Authentication request for the required auth-factors + * @param linkedKycAuthRequest + * @return + */ + LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKycAuthRequest) throws EsignetException; + /** * Accepted claims are verified and KYC exchange is performed * Redirects to requested redirect_uri @@ -62,4 +68,11 @@ public interface LinkedAuthorizationService { */ LinkedConsentResponse saveConsent(LinkedConsentRequest linkedConsentRequest) throws EsignetException; + /** + * Accepted claims are verified and KYC exchange is performed + * Redirects to requested redirect_uri + * @param linkedConsentRequest + */ + LinkedConsentResponse saveConsentV2(LinkedConsentRequestV2 linkedConsentRequest) throws EsignetException; + } diff --git a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java index 3f7c70172..e99dbe396 100644 --- a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java +++ b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/Action.java @@ -20,5 +20,7 @@ public enum Action { LINK_AUTHENTICATE, SAVE_CONSENT, LINK_SEND_OTP, - LINK_AUTH_CODE + LINK_AUTH_CODE, + GET_USER_CONSENT, + SAVE_USER_CONSENT } diff --git a/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/ConsentAction.java b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/ConsentAction.java new file mode 100644 index 000000000..45869719d --- /dev/null +++ b/esignet-integration-api/src/main/java/io/mosip/esignet/api/util/ConsentAction.java @@ -0,0 +1,6 @@ +package io.mosip.esignet.api.util; + +public enum ConsentAction { + CAPTURE, + NOCAPTURE, +} diff --git a/esignet-service/pom.xml b/esignet-service/pom.xml index 88cad077e..44fe448c9 100644 --- a/esignet-service/pom.xml +++ b/esignet-service/pom.xml @@ -66,6 +66,11 @@ binding-service-impl ${project.version} + + io.mosip.esignet + consent-service-impl + ${project.version} + diff --git a/esignet-service/src/main/java/io/mosip/esignet/controllers/AuthorizationController.java b/esignet-service/src/main/java/io/mosip/esignet/controllers/AuthorizationController.java index 59ff4bb9d..24f2cbcaa 100644 --- a/esignet-service/src/main/java/io/mosip/esignet/controllers/AuthorizationController.java +++ b/esignet-service/src/main/java/io/mosip/esignet/controllers/AuthorizationController.java @@ -85,4 +85,19 @@ public ResponseWrapper getAuthorizationCode(@Valid @RequestBod } return responseWrapper; } + + @PostMapping("/v2/authenticate") + public ResponseWrapper authenticateEndUserV2(@Valid @RequestBody RequestWrapper + requestWrapper) throws EsignetException { + ResponseWrapper responseWrapper = new ResponseWrapper<>(); + responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime()); + try { + AuthResponseV2 authResponse = authorizationService.authenticateUserV2(requestWrapper.getRequest()); + responseWrapper.setResponse(authResponse); + } catch (EsignetException ex) { + auditWrapper.logAudit(Action.AUTHENTICATE, ActionStatus.ERROR, AuditHelper.buildAuditDto(requestWrapper.getRequest().getTransactionId(), null), ex); + throw ex; + } + return responseWrapper; + } } diff --git a/esignet-service/src/test/java/io/mosip/esignet/controllers/AuthorizationControllerTest.java b/esignet-service/src/test/java/io/mosip/esignet/controllers/AuthorizationControllerTest.java index 29d98e245..cc39be3c4 100644 --- a/esignet-service/src/test/java/io/mosip/esignet/controllers/AuthorizationControllerTest.java +++ b/esignet-service/src/test/java/io/mosip/esignet/controllers/AuthorizationControllerTest.java @@ -6,19 +6,20 @@ package io.mosip.esignet.controllers; import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.AuthChallenge; import io.mosip.esignet.api.spi.AuditPlugin; -import io.mosip.esignet.core.dto.OAuthDetailRequest; -import io.mosip.esignet.core.dto.OAuthDetailResponse; -import io.mosip.esignet.core.dto.RequestWrapper; +import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.spi.AuthorizationService; import io.mosip.esignet.core.util.AuthenticationContextClassRefUtil; import io.mosip.esignet.core.constants.ErrorConstants; +import io.mosip.esignet.core.util.IdentityProviderUtil; import io.mosip.esignet.services.AuthorizationHelperService; import io.mosip.esignet.services.CacheUtilService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -29,7 +30,9 @@ import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import static io.mosip.esignet.core.constants.Constants.UTC_DATETIME_PATTERN; import static org.mockito.Mockito.when; @@ -351,4 +354,113 @@ public void getOauthDetails_withAuthorizeAndOpenIdScope_returnSuccessResponse() .andExpect(status().isOk()) .andExpect(jsonPath("$.response.transactionId").value("qwertyId")); } + + @Test + public void authenticateEndUser_withValidDetails_returnSuccessResponse() throws Exception { + AuthRequest authRequest = new AuthRequest(); + authRequest.setIndividualId("1234567890"); + authRequest.setTransactionId("quewertyId"); + + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setChallenge("12345"); + authChallenge.setAuthFactorType("OTP"); + authChallenge.setFormat("numeric"); + + List authChallengeList = new ArrayList<>(); + authChallengeList.add(authChallenge); + authRequest.setChallengeList(authChallengeList); + + RequestWrapper wrapper = new RequestWrapper<>(); + wrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + wrapper.setRequest(authRequest); + + AuthResponseV2 authResponseV2 = new AuthResponseV2(); + authResponseV2.setTransactionId("quewertyId"); + when(authorizationService.authenticateUserV2(authRequest)).thenReturn(authResponseV2); + mockMvc.perform(post("/authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(wrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response.transactionId").value("quewertyId")); + } + + @Test + public void authenticateEndUser_withInvalidTimestamp_returnErrorResponse() throws Exception { + AuthRequest authRequest = new AuthRequest(); + authRequest.setIndividualId("1234567890"); + authRequest.setTransactionId("1234567890"); + + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setChallenge("1234567890"); + authChallenge.setAuthFactorType("OTP"); + authChallenge.setFormat("alpha-numeric"); + + List authChallengeList = new ArrayList<>(); + authChallengeList.add(authChallenge); + + authRequest.setChallengeList(authChallengeList); + + ZonedDateTime requestTime = ZonedDateTime.now(ZoneOffset.UTC); + requestTime = requestTime.plusMinutes(10); + + RequestWrapper wrapper = new RequestWrapper<>(); + wrapper.setRequestTime(requestTime.format(DateTimeFormatter.ofPattern(UTC_DATETIME_PATTERN))); + wrapper.setRequest(authRequest); + when(authorizationService.authenticateUserV2(authRequest)).thenReturn(new AuthResponseV2()); + mockMvc.perform(post("/authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(wrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_REQUEST)) + .andExpect(jsonPath("$.errors[0].errorMessage").value("requestTime: invalid_request")); + } + + @Test + public void authenticateEndUser_withInvalidTransectionId_returnErrorResponse() throws Exception { + AuthRequest authRequest = new AuthRequest(); + authRequest.setIndividualId("1234567890"); + + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setChallenge("1234567890"); + authChallenge.setAuthFactorType("PWD"); + authChallenge.setFormat("alpha-numeric"); + + List authChallengeList = new ArrayList<>(); + authChallengeList.add(authChallenge); + authRequest.setChallengeList(authChallengeList); + + RequestWrapper wrapper = new RequestWrapper<>(); + wrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + wrapper.setRequest(authRequest); + + + mockMvc.perform(post("/authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(wrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_TRANSACTION_ID)) + .andExpect(jsonPath("$.errors[0].errorMessage").value("request.transactionId: invalid_transaction_id")); + } + + @Test + public void authenticateEndUser_withInvalidAuthChallenge_returnErrorResponse() throws Exception { + AuthRequest authRequest = new AuthRequest(); + authRequest.setIndividualId("1234567890"); + authRequest.setTransactionId("1234567890"); + + + RequestWrapper wrapper = new RequestWrapper<>(); + wrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + wrapper.setRequest(authRequest); + + mockMvc.perform(post("/authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(wrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_CHALLENGE_LIST)) + .andExpect(jsonPath("$.errors[0].errorMessage").value("request.challengeList: invalid_no_of_challenges")); + } } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 6325f3599..0280441d0 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -14,6 +14,7 @@ import io.mosip.esignet.api.spi.Authenticator; import io.mosip.esignet.api.util.Action; import io.mosip.esignet.api.util.ActionStatus; +import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.Constants; import io.mosip.esignet.core.constants.ErrorConstants; import io.mosip.esignet.core.dto.*; @@ -21,22 +22,27 @@ import io.mosip.esignet.core.exception.InvalidTransactionException; import io.mosip.esignet.core.spi.AuthorizationService; import io.mosip.esignet.core.spi.ClientManagementService; -import io.mosip.esignet.core.util.*; +import io.mosip.esignet.core.util.AuditHelper; +import io.mosip.esignet.core.util.AuthenticationContextClassRefUtil; +import io.mosip.esignet.core.util.IdentityProviderUtil; +import io.mosip.esignet.core.util.LinkCodeQueue; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; -import static io.mosip.esignet.core.spi.TokenService.ACR; import static io.mosip.esignet.core.constants.Constants.*; +import static io.mosip.esignet.core.spi.TokenService.ACR; import static io.mosip.esignet.core.util.IdentityProviderUtil.ALGO_SHA3_256; import static io.mosip.esignet.core.util.IdentityProviderUtil.ALGO_SHA_256; @Slf4j @Service +@Primary public class AuthorizationServiceImpl implements AuthorizationService { @Autowired @@ -60,6 +66,9 @@ public class AuthorizationServiceImpl implements AuthorizationService { @Autowired private ObjectMapper objectMapper; + @Autowired + ConsentHelperService consentHelperService; + @Value("#{${mosip.esignet.ui.config.key-values}}") private Map uiConfigMap; @@ -92,7 +101,7 @@ public OAuthDetailResponse getOauthDetails(OAuthDetailRequest oauthDetailReqDto) OAuthDetailResponse oauthDetailResponse = new OAuthDetailResponse(); oauthDetailResponse.setTransactionId(transactionId); oauthDetailResponse.setAuthFactors(authenticationContextClassRefUtil.getAuthFactors( - resolvedClaims.getId_token().get(ACR).getValues() + resolvedClaims.getId_token().get(ACR).getValues() )); Map claimsMap = authorizationHelperService.getClaimNames(resolvedClaims); @@ -140,7 +149,6 @@ public OtpResponse sendOtp(OtpRequest otpRequest) throws EsignetException { return otpResponse; } - @Override public AuthResponse authenticateUser(AuthRequest authRequest) throws EsignetException { OIDCTransaction transaction = cacheUtilService.getPreAuthTransaction(authRequest.getTransactionId()); if(transaction == null) @@ -156,11 +164,10 @@ public AuthResponse authenticateUser(AuthRequest authRequest) throws EsignetExc transaction.setKycToken(kycAuthResult.getKycToken()); transaction.setAuthTimeInSeconds(IdentityProviderUtil.getEpochSeconds()); transaction.setProvidedAuthFactors(providedAuthFactors.stream().map(acrFactors -> acrFactors.stream() - .map(AuthenticationFactor::getType) - .collect(Collectors.toList())).collect(Collectors.toSet())); + .map(AuthenticationFactor::getType) + .collect(Collectors.toList())).collect(Collectors.toSet())); authorizationHelperService.setIndividualId(authRequest.getIndividualId(), transaction); cacheUtilService.setAuthenticatedTransaction(authRequest.getTransactionId(), transaction); - auditWrapper.logAudit(Action.AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(authRequest.getTransactionId(), transaction), null); AuthResponse authRespDto = new AuthResponse(); @@ -168,23 +175,57 @@ public AuthResponse authenticateUser(AuthRequest authRequest) throws EsignetExc return authRespDto; } + @Override + public AuthResponseV2 authenticateUserV2(AuthRequest authRequest) throws EsignetException { + OIDCTransaction transaction = cacheUtilService.getPreAuthTransaction(authRequest.getTransactionId()); + if(transaction == null) + throw new InvalidTransactionException(); + + //Validate provided challenge list auth-factors with resolved auth-factors for the transaction. + Set> providedAuthFactors = authorizationHelperService.getProvidedAuthFactors(transaction, + authRequest.getChallengeList()); + KycAuthResult kycAuthResult = authorizationHelperService.delegateAuthenticateRequest(authRequest.getTransactionId(), + authRequest.getIndividualId(), authRequest.getChallengeList(), transaction); + //cache tokens on successful response + transaction.setPartnerSpecificUserToken(kycAuthResult.getPartnerSpecificUserToken()); + transaction.setKycToken(kycAuthResult.getKycToken()); + transaction.setAuthTimeInSeconds(IdentityProviderUtil.getEpochSeconds()); + transaction.setProvidedAuthFactors(providedAuthFactors.stream().map(acrFactors -> acrFactors.stream() + .map(AuthenticationFactor::getType) + .collect(Collectors.toList())).collect(Collectors.toSet())); + authorizationHelperService.setIndividualId(authRequest.getIndividualId(), transaction); + consentHelperService.processConsent(transaction); + cacheUtilService.setAuthenticatedTransaction(authRequest.getTransactionId(), transaction); + auditWrapper.logAudit(Action.AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(authRequest.getTransactionId(), transaction), null); + + AuthResponseV2 authRespDto = new AuthResponseV2(); + authRespDto.setTransactionId(authRequest.getTransactionId()); + authRespDto.setConsentAction(transaction.getConsentAction()); + return authRespDto; + } + @Override public AuthCodeResponse getAuthCode(AuthCodeRequest authCodeRequest) throws EsignetException { OIDCTransaction transaction = cacheUtilService.getAuthenticatedTransaction(authCodeRequest.getTransactionId()); if(transaction == null) { throw new InvalidTransactionException(); } - - authorizationHelperService.validateAcceptedClaims(transaction, authCodeRequest.getAcceptedClaims()); - authorizationHelperService.validateAuthorizeScopes(transaction, authCodeRequest.getPermittedAuthorizeScopes()); + List acceptedClaims = authCodeRequest.getAcceptedClaims(); + List acceptedScopes = authCodeRequest.getPermittedAuthorizeScopes(); + if(ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())) { + acceptedClaims = transaction.getAcceptedClaims(); + acceptedScopes = transaction.getPermittedScopes(); + } + authorizationHelperService.validateAcceptedClaims(transaction, acceptedClaims); + authorizationHelperService.validateAuthorizeScopes(transaction, acceptedScopes); String authCode = IdentityProviderUtil.generateB64EncodedHash(ALGO_SHA3_256, UUID.randomUUID().toString()); // cache consent with auth-code-hash as key transaction.setCodeHash(authorizationHelperService.getKeyHash(authCode)); - transaction.setAcceptedClaims(authCodeRequest.getAcceptedClaims()); - transaction.setPermittedScopes(authCodeRequest.getPermittedAuthorizeScopes()); + transaction.setAcceptedClaims(acceptedClaims); + transaction.setPermittedScopes(acceptedScopes); + consentHelperService.addUserConsent(transaction, false, null); transaction = cacheUtilService.setAuthCodeGeneratedTransaction(authCodeRequest.getTransactionId(), transaction); - auditWrapper.logAudit(Action.GET_AUTH_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(authCodeRequest.getTransactionId(), transaction), null); AuthCodeResponse authCodeResponse = new AuthCodeResponse(); diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java new file mode 100644 index 000000000..fef75ec37 --- /dev/null +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -0,0 +1,197 @@ +package io.mosip.esignet.services; + +import com.auth0.jwt.interfaces.Claim; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.JWSHeader; +import com.nimbusds.jose.JWSObject; +import com.nimbusds.jose.util.Base64URL; +import com.nimbusds.jwt.JWTClaimsSet; +import io.mosip.esignet.api.dto.ClaimDetail; +import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.api.util.ConsentAction; +import io.mosip.esignet.core.constants.ErrorConstants; +import io.mosip.esignet.core.dto.*; +import io.mosip.esignet.core.exception.EsignetException; +import io.mosip.esignet.core.exception.InvalidTransactionException; +import io.mosip.esignet.core.spi.ConsentService; +import io.mosip.esignet.core.util.IdentityProviderUtil; +import io.mosip.esignet.core.util.KafkaHelperService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.text.ParseException; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static io.mosip.esignet.core.util.IdentityProviderUtil.ALGO_SHA3_256; + +@Slf4j +@Component +public class ConsentHelperService { + + @Autowired + private CacheUtilService cacheUtilService; + + @Autowired + private ConsentService consentService; + + private final ObjectMapper objectMapper=new ObjectMapper(); + + @Autowired + private KafkaHelperService kafkaHelperService; + + @Value("${mosip.esignet.kafka.linked-auth-code.topic}") + private String linkedAuthCodeTopicName; + + public void processConsent(OIDCTransaction transaction) { + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId(transaction.getClientId()); + userConsentRequest.setPsuToken(transaction.getPartnerSpecificUserToken()); + Optional consent = consentService.getUserConsent(userConsentRequest); + + ConsentAction consentAction = consent.isEmpty() ? ConsentAction.CAPTURE : evaluateConsentAction(transaction,consent.get()); + + transaction.setConsentAction(consentAction); + + if(consentAction.equals(ConsentAction.NOCAPTURE)) { + transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); + transaction.setPermittedScopes(consent.get().getPermittedScopes()); + } + } + + + public void addUserConsent(OIDCTransaction transaction, boolean linked, String signature) { + if(ConsentAction.CAPTURE.equals(transaction.getConsentAction())){ + UserConsent userConsent = new UserConsent(); + userConsent.setClientId(transaction.getClientId()); + userConsent.setPsuToken(transaction.getPartnerSpecificUserToken()); + Claims claims = transaction.getRequestedClaims(); + List acceptedClaims = transaction.getAcceptedClaims(); + Claims normalizedClaims = new Claims(); + normalizedClaims.setUserinfo(normalizeClaims(claims.getUserinfo())); + normalizedClaims.setId_token(claims.getId_token()); + + userConsent.setClaims(normalizedClaims); + userConsent.setSignature(signature); + List permittedScopes = transaction.getPermittedScopes(); + List authorizeScope = transaction.getRequestedAuthorizeScopes(); + Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() + .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); + userConsent.setAuthorizationScopes(authorizeScopes); + userConsent.setAcceptedClaims(acceptedClaims); + userConsent.setPermittedScopes(permittedScopes); + try { + userConsent.setHash(hashUserConsent(normalizedClaims, authorizeScopes)); + } catch (JsonProcessingException e) { + throw new EsignetException(ErrorConstants.INVALID_CLAIM); + } + consentService.saveUserConsent(userConsent); + } + } + + + public Map normalizeClaims(Map claims){ + return claims.entrySet().stream().collect( + Collectors.toMap( + Map.Entry::getKey, + entry -> { + ClaimDetail claimDetail = entry.getValue(); + return claimDetail == null ? new ClaimDetail() : claimDetail; + } + ) + ); + } + + public String hashUserConsent(Claims claims,Map authorizeScopes) throws JsonProcessingException { + + Map claimsAndAuthorizeScopes = new LinkedHashMap<>(); + + List> entryList; + Map sortedMap = new LinkedHashMap<>(); + if(claims.getUserinfo()!=null){ + entryList = new ArrayList<>(claims.getUserinfo().entrySet()); + sortClaims(entryList, sortedMap); + + } + //Now for sorting id_token + if(claims.getId_token()!=null) + { + entryList = new ArrayList<>(claims.getId_token().entrySet()); + sortClaims(entryList, sortedMap); + + } + //Now for authorizeScopes + Map sortedAuthorzeScopeMap=new LinkedHashMap<>(); + + List>authorizeScopesList = new ArrayList<>(authorizeScopes.entrySet()); + authorizeScopesList.sort(new Comparator>() { + public int compare(Map.Entry o1, Map.Entry o2) { + return o1.getKey().compareTo(o2.getKey()); + } + }); + for (Map.Entry entry : authorizeScopesList) { + sortedAuthorzeScopeMap.put(entry.getKey(), entry.getValue()); + } + claimsAndAuthorizeScopes.put("claims",sortedMap); + claimsAndAuthorizeScopes.put("authorizeScopes",sortedAuthorzeScopeMap); + String s=claimsAndAuthorizeScopes.toString().trim().replace(" ",""); + return IdentityProviderUtil.generateB64EncodedHash(ALGO_SHA3_256, s); + } + + private static void sortClaims(List> entryList, Map sortedMap) { + entryList.sort(new Comparator<>() { + public int compare(Map.Entry o1, Map.Entry o2) { + return o1.getKey().compareTo(o2.getKey()); + } + }); + for (Map.Entry entry : entryList) { + sortedMap.put(entry.getKey(), entry.getValue()); + } + } + + + private ConsentAction evaluateConsentAction(OIDCTransaction transaction, ConsentDetail consentDetail) { + String hash; + try { + List permittedScopes = transaction.getPermittedScopes(); + List authorizeScope = transaction.getRequestedAuthorizeScopes(); + Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() + .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); + hash = hashUserConsent(transaction.getRequestedClaims(),authorizeScopes ); + } catch (JsonProcessingException e) { + throw new EsignetException(ErrorConstants.INVALID_CLAIM); + } + return consentDetail.getHash().equals(hash) ? ConsentAction.NOCAPTURE : ConsentAction.CAPTURE; + } + + private String generateSignedObject(OIDCTransaction transaction, ConsentDetail consentDetail){ + List acceptedClaims = transaction.getAcceptedClaims(); + List permittedScopes = transaction.getPermittedScopes(); + Collections.sort(acceptedClaims); + Collections.sort(acceptedClaims); + JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() + .claim("acceptedClaims", acceptedClaims) + .claim("authorizeScopes", permittedScopes) + .build(); + String jws = consentDetail.getSignature(); + String[] parts = jws.split("\\."); + + String header = parts[0]; + String signature = parts[1]; + JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.parse(header)); + JWSObject jwsObject = null; + try { + jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) + ,Base64URL.encode(signature) ); + } catch (ParseException e) { + + } + return jwsObject == null ? "": jwsObject.serialize(); + } + +} \ No newline at end of file diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index ed0e4ff32..9b8b13e4e 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -5,49 +5,14 @@ */ package io.mosip.esignet.services; -import static io.mosip.esignet.core.constants.Constants.ESSENTIAL; -import static io.mosip.esignet.core.constants.Constants.LINKED_STATUS; -import static io.mosip.esignet.core.constants.Constants.UTC_DATETIME_PATTERN; -import static io.mosip.esignet.core.constants.Constants.VOLUNTARY; -import static io.mosip.esignet.core.spi.TokenService.ACR; - -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.web.context.request.async.DeferredResult; - import io.mosip.esignet.api.dto.KycAuthResult; import io.mosip.esignet.api.dto.SendOtpResult; import io.mosip.esignet.api.spi.AuditPlugin; import io.mosip.esignet.api.util.Action; import io.mosip.esignet.api.util.ActionStatus; +import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.ErrorConstants; -import io.mosip.esignet.core.dto.AuthenticationFactor; -import io.mosip.esignet.core.dto.ClientDetail; -import io.mosip.esignet.core.dto.LinkAuthCodeRequest; -import io.mosip.esignet.core.dto.LinkCodeRequest; -import io.mosip.esignet.core.dto.LinkCodeResponse; -import io.mosip.esignet.core.dto.LinkStatusRequest; -import io.mosip.esignet.core.dto.LinkTransactionMetadata; -import io.mosip.esignet.core.dto.LinkTransactionRequest; -import io.mosip.esignet.core.dto.LinkTransactionResponse; -import io.mosip.esignet.core.dto.LinkedConsentRequest; -import io.mosip.esignet.core.dto.LinkedConsentResponse; -import io.mosip.esignet.core.dto.LinkedKycAuthRequest; -import io.mosip.esignet.core.dto.LinkedKycAuthResponse; -import io.mosip.esignet.core.dto.OIDCTransaction; -import io.mosip.esignet.core.dto.OtpRequest; -import io.mosip.esignet.core.dto.OtpResponse; +import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.DuplicateLinkCodeException; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.exception.InvalidTransactionException; @@ -58,9 +23,28 @@ import io.mosip.esignet.core.util.IdentityProviderUtil; import io.mosip.esignet.core.util.KafkaHelperService; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.async.DeferredResult; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static io.mosip.esignet.core.constants.Constants.*; +import static io.mosip.esignet.core.spi.TokenService.ACR; @Slf4j @Service +@Primary public class LinkedAuthorizationServiceImpl implements LinkedAuthorizationService { @Autowired @@ -77,7 +61,7 @@ public class LinkedAuthorizationServiceImpl implements LinkedAuthorizationServic @Autowired private KafkaHelperService kafkaHelperService; - + @Autowired private AuditPlugin auditWrapper; @@ -135,7 +119,7 @@ public LinkCodeResponse generateLinkCode(LinkCodeRequest linkCodeRequest) throws linkCodeResponse.setLinkCode(linkCode); linkCodeResponse.setTransactionId(linkCodeRequest.getTransactionId()); linkCodeResponse.setExpireDateTime(expireDateTime == null ? null : - expireDateTime.format(DateTimeFormatter.ofPattern(UTC_DATETIME_PATTERN))); + expireDateTime.format(DateTimeFormatter.ofPattern(UTC_DATETIME_PATTERN))); auditWrapper.logAudit(Action.LINK_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkCodeRequest.getTransactionId(), transaction), null); return linkCodeResponse; } @@ -200,7 +184,6 @@ public LinkedKycAuthResponse authenticateUser(LinkedKycAuthRequest linkedKycAuth OIDCTransaction transaction = cacheUtilService.getLinkedSessionTransaction(linkedKycAuthRequest.getLinkedTransactionId()); if(transaction == null) throw new InvalidTransactionException(); - //Validate provided challenge list auth-factors with resolved auth-factors for the transaction. Set> providedAuthFactors = authorizationHelperService.getProvidedAuthFactors(transaction, linkedKycAuthRequest.getChallengeList()); KycAuthResult kycAuthResult = authorizationHelperService.delegateAuthenticateRequest(linkedKycAuthRequest.getLinkedTransactionId(), @@ -214,27 +197,75 @@ public LinkedKycAuthResponse authenticateUser(LinkedKycAuthRequest linkedKycAuth .map(AuthenticationFactor::getType) .collect(Collectors.toList())).collect(Collectors.toSet())); cacheUtilService.setLinkedAuthenticatedTransaction(linkedKycAuthRequest.getLinkedTransactionId(), transaction); - LinkedKycAuthResponse authRespDto = new LinkedKycAuthResponse(); authRespDto.setLinkedTransactionId(linkedKycAuthRequest.getLinkedTransactionId()); auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(null, transaction), null); return authRespDto; } + @Override + public LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKycAuthRequest) throws EsignetException { + OIDCTransaction transaction = cacheUtilService.getLinkedSessionTransaction(linkedKycAuthRequest.getLinkedTransactionId()); + if(transaction == null) + throw new InvalidTransactionException(); + //Validate provided challenge list auth-factors with resolved auth-factors for the transaction. + Set> providedAuthFactors = authorizationHelperService.getProvidedAuthFactors(transaction, linkedKycAuthRequest.getChallengeList()); + KycAuthResult kycAuthResult = authorizationHelperService.delegateAuthenticateRequest(linkedKycAuthRequest.getLinkedTransactionId(), + linkedKycAuthRequest.getIndividualId(), linkedKycAuthRequest.getChallengeList(), transaction); + //cache tokens on successful response + transaction.setPartnerSpecificUserToken(kycAuthResult.getPartnerSpecificUserToken()); + transaction.setKycToken(kycAuthResult.getKycToken()); + transaction.setAuthTimeInSeconds(IdentityProviderUtil.getEpochSeconds()); + authorizationHelperService.setIndividualId(linkedKycAuthRequest.getIndividualId(), transaction); + transaction.setProvidedAuthFactors(providedAuthFactors.stream().map(acrFactors -> acrFactors.stream() + .map(AuthenticationFactor::getType) + .collect(Collectors.toList())).collect(Collectors.toSet())); + cacheUtilService.setLinkedAuthenticatedTransaction(linkedKycAuthRequest.getLinkedTransactionId(), transaction); + LinkedKycAuthResponseV2 authRespDto = new LinkedKycAuthResponseV2(); + authRespDto.setLinkedTransactionId(linkedKycAuthRequest.getLinkedTransactionId()); + auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(null, transaction), null); + return authRespDto; + } + @Override public LinkedConsentResponse saveConsent(LinkedConsentRequest linkedConsentRequest) throws EsignetException { OIDCTransaction transaction = cacheUtilService.getLinkedAuthTransaction(linkedConsentRequest.getLinkedTransactionId()); - if(transaction == null) { + if(transaction == null || ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())) { throw new InvalidTransactionException(); } - - authorizationHelperService.validateAcceptedClaims(transaction, linkedConsentRequest.getAcceptedClaims()); - authorizationHelperService.validateAuthorizeScopes(transaction, linkedConsentRequest.getPermittedAuthorizeScopes()); + List acceptedClaims = linkedConsentRequest.getAcceptedClaims(); + List permittedAuthorizeScopes = linkedConsentRequest.getPermittedAuthorizeScopes(); + authorizationHelperService.validateAcceptedClaims(transaction, acceptedClaims); + authorizationHelperService.validateAuthorizeScopes(transaction, permittedAuthorizeScopes); // cache consent only, auth-code will be generated on link-auth-code-status API call transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); + cacheUtilService.setLinkedConsentedTransaction(linkedConsentRequest.getLinkedTransactionId(), transaction); + //Publish message after successfully saving the consent + kafkaHelperService.publish(linkedAuthCodeTopicName, linkedConsentRequest.getLinkedTransactionId()); + + LinkedConsentResponse authRespDto = new LinkedConsentResponse(); + authRespDto.setLinkedTransactionId(linkedConsentRequest.getLinkedTransactionId()); + auditWrapper.logAudit(Action.SAVE_CONSENT, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkedConsentRequest.getLinkedTransactionId(), transaction), null); + return authRespDto; + } + @Override + public LinkedConsentResponse saveConsentV2(LinkedConsentRequestV2 linkedConsentRequest) throws EsignetException { + OIDCTransaction transaction = cacheUtilService.getLinkedAuthTransaction(linkedConsentRequest.getLinkedTransactionId()); + if(transaction == null || ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())) { + throw new InvalidTransactionException(); + } + List acceptedClaims = linkedConsentRequest.getAcceptedClaims(); + List permittedAuthorizeScopes = linkedConsentRequest.getPermittedAuthorizeScopes(); + authorizationHelperService.validateAcceptedClaims(transaction, acceptedClaims); + authorizationHelperService.validateAuthorizeScopes(transaction, permittedAuthorizeScopes); + // cache consent only, auth-code will be generated on link-auth-code-status API call + transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); + transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); + + cacheUtilService.setLinkedConsentedTransaction(linkedConsentRequest.getLinkedTransactionId(), transaction); //Publish message after successfully saving the consent kafkaHelperService.publish(linkedAuthCodeTopicName, linkedConsentRequest.getLinkedTransactionId()); @@ -275,7 +306,7 @@ public void getLinkAuthCode(DeferredResult deferredResult, LinkAuthCodeRequest l OIDCTransaction oidcTransaction = cacheUtilService.getConsentedTransaction(linkTransactionMetadata.getLinkedTransactionId()); if(oidcTransaction != null) { - auditWrapper.logAudit(Action.LINK_AUTH_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkAuthCodeRequest.getTransactionId(), oidcTransaction), null); + auditWrapper.logAudit(Action.LINK_AUTH_CODE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(linkAuthCodeRequest.getTransactionId(), oidcTransaction), null); deferredResult.setResult(authorizationHelperService.getLinkAuthStatusResponse(linkTransactionMetadata.getTransactionId(), oidcTransaction)); } else { authorizationHelperService.addEntryInLinkAuthCodeStatusDeferredResultMap(linkTransactionMetadata.getLinkedTransactionId(), deferredResult); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java index eb6255f48..0c0b766e7 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java @@ -58,6 +58,9 @@ public class AuthorizationServiceTest { @Mock AuditPlugin auditWrapper; + @Mock + ConsentHelperService consentHelperService; + @Before public void setUp() { diff --git a/pom.xml b/pom.xml index 812680ff3..4143f9f5a 100644 --- a/pom.xml +++ b/pom.xml @@ -104,6 +104,7 @@ binding-service-impl client-management-service-impl oidc-service-impl + consent-service-impl @@ -341,6 +342,7 @@ maven-compiler-plugin ${maven.compiler.version} + true ${maven.compiler.source} ${maven.compiler.target} From c75f5cf94654c04b58c08c2ae0d816e9a8900872 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Fri, 16 Jun 2023 14:49:45 +0530 Subject: [PATCH 02/13] [ES-3] review comments fix --- consent-service-impl/pom.xml | 3 +++ .../mosip/esignet/config/ModelMapperConfig.java | 5 +++++ .../io/mosip/esignet/entity/ConsentDetail.java | 5 +++++ .../io/mosip/esignet/entity/ConsentHistory.java | 5 +++++ .../io/mosip/esignet/mapper/ConsentMapper.java | 15 +++++++++++---- .../mapper/CustomConsentHistoryMapping.java | 5 +++++ .../mapper/CustomConsentRequestMapping.java | 5 +++++ .../mapper/converter/ClaimsToStringConverter.java | 12 +++++++++++- .../mapper/converter/ListToStringConverter.java | 3 ++- .../mapper/converter/MapToStringConverter.java | 13 ++++++++++--- .../mapper/converter/StringToClaimsConverter.java | 12 +++++++++++- .../mapper/converter/StringToListConverter.java | 3 ++- .../mapper/converter/StringToMapConverter.java | 14 ++++++++++---- .../esignet/repository/ConsentRepository.java | 6 +++++- .../esignet/services/ConsentServiceImpl.java | 5 +++++ .../esignet/ConsentDetailRepositoryTest.java | 9 +++++++-- .../io/mosip/esignet/ConsentServiceImplTest.java | 5 +++++ .../java/io/mosip/esignet/TestApplication.java | 5 +++++ .../io/mosip/esignet/core/dto/ConsentDetail.java | 5 +++++ .../esignet/core/dto/LinkedKycAuthResponseV2.java | 5 +++++ .../esignet/services/ConsentHelperService.java | 6 +++++- 21 files changed, 127 insertions(+), 19 deletions(-) diff --git a/consent-service-impl/pom.xml b/consent-service-impl/pom.xml index d7fec3935..915f9405b 100644 --- a/consent-service-impl/pom.xml +++ b/consent-service-impl/pom.xml @@ -1,4 +1,7 @@ + diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java b/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java index bb86407a5..d57b26b7b 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java @@ -1,3 +1,8 @@ +/* + * 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.config; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java index 47c2f9c70..272562c52 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentDetail.java @@ -1,3 +1,8 @@ +/* + * 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.entity; import lombok.*; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java index 3539fb2f2..52823d34d 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/entity/ConsentHistory.java @@ -1,3 +1,8 @@ +/* + * 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.entity; import lombok.AllArgsConstructor; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java index 047e2e362..92fcf29a7 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java @@ -1,5 +1,11 @@ +/* + * 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.mapper; +import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.esignet.core.dto.ConsentDetail; import io.mosip.esignet.core.dto.UserConsent; import io.mosip.esignet.entity.ConsentHistory; @@ -12,10 +18,11 @@ public class ConsentMapper { private static final ModelMapper modelMapper = new ModelMapper(); static { - modelMapper.addConverter(new ClaimsToStringConverter()); - modelMapper.addConverter(new StringToClaimsConverter()); - modelMapper.addConverter(new MapToStringConverter()); - modelMapper.addConverter(new StringToMapConverter()); + ObjectMapper objectMapper = new ObjectMapper(); + modelMapper.addConverter(new ClaimsToStringConverter(objectMapper)); + modelMapper.addConverter(new StringToClaimsConverter(objectMapper)); + modelMapper.addConverter(new MapToStringConverter(objectMapper)); + modelMapper.addConverter(new StringToMapConverter(objectMapper)); modelMapper.addConverter(new ListToStringConverter()); modelMapper.addConverter(new StringToListConverter()); modelMapper.addMappings(new CustomConsentRequestMapping()); diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java index c5cbbe84a..20b237d9d 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java @@ -1,3 +1,8 @@ +/* + * 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.mapper; import io.mosip.esignet.core.dto.UserConsent; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java index 40b0ebf75..3de2f4f34 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentRequestMapping.java @@ -1,3 +1,8 @@ +/* + * 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.mapper; import io.mosip.esignet.core.dto.UserConsent; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java index 62a01aa9e..961768890 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ClaimsToStringConverter.java @@ -1,3 +1,8 @@ +/* + * 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.mapper.converter; import com.fasterxml.jackson.core.JsonProcessingException; @@ -12,7 +17,12 @@ @Slf4j public class ClaimsToStringConverter implements Converter { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private final ObjectMapper objectMapper; + + public ClaimsToStringConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + @Override public String convert(MappingContext context) { Claims claims = context.getSource(); diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java index c43a16521..ec9664ed5 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/ListToStringConverter.java @@ -1,8 +1,9 @@ -package io.mosip.esignet.mapper.converter;/* +/* * 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.mapper.converter; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java index 9919704b8..5e832d45d 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/MapToStringConverter.java @@ -1,20 +1,27 @@ +/* + * 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.mapper.converter; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import io.mosip.esignet.api.dto.ClaimDetail; import io.mosip.esignet.core.exception.EsignetException; import org.modelmapper.Converter; import org.modelmapper.spi.MappingContext; import java.util.Map; -import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_PERMITTED_SCOPE; public class MapToStringConverter implements Converter,String> { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private final ObjectMapper objectMapper; + + public MapToStringConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } @Override public String convert(MappingContext, String> mappingContext) { diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java index 60b43ceb5..921ac5d18 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToClaimsConverter.java @@ -1,3 +1,8 @@ +/* + * 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.mapper.converter; import com.fasterxml.jackson.core.JsonProcessingException; @@ -14,7 +19,12 @@ @Slf4j public class StringToClaimsConverter implements Converter { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private final ObjectMapper objectMapper; + + public StringToClaimsConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + @Override public Claims convert(MappingContext context) { String claims = context.getSource(); diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java index bd0a0d8f5..2edf94a8c 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToListConverter.java @@ -1,8 +1,9 @@ -package io.mosip.esignet.mapper.converter;/* +/* * 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.mapper.converter; import org.apache.commons.lang3.StringUtils; import org.modelmapper.Converter; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java index bd8908353..b7951e29f 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/converter/StringToMapConverter.java @@ -1,7 +1,11 @@ +/* + * 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.mapper.converter; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.esignet.core.exception.EsignetException; import lombok.extern.slf4j.Slf4j; @@ -10,16 +14,18 @@ import org.modelmapper.spi.MappingContext; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_CLAIM; import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_PERMITTED_SCOPE; @Slf4j public class StringToMapConverter implements Converter> { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private final ObjectMapper objectMapper; + + public StringToMapConverter(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } @Override public Map convert(MappingContext> mappingContext) { diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java index a8cfe4bef..a66553ea8 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/repository/ConsentRepository.java @@ -1,3 +1,8 @@ +/* + * 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.repository; import io.mosip.esignet.entity.ConsentDetail; @@ -7,7 +12,6 @@ import java.util.UUID; @Repository public interface ConsentRepository extends JpaRepository { - Optional findFirstByClientIdAndPsuTokenOrderByCreatedtimesDesc(String clientId, String psuToken); Optional findByClientIdAndPsuToken(String clientId, String psuToken); void deleteByClientIdAndPsuToken(String clientId, String psuToken); diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java index b66aecff4..507a86934 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java @@ -1,3 +1,8 @@ +/* + * 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.services; diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java index 0098fe06e..4375cfb35 100644 --- a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentDetailRepositoryTest.java @@ -1,3 +1,8 @@ +/* + * 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; import io.mosip.esignet.entity.ConsentDetail; @@ -42,10 +47,10 @@ public void createConsent_withValidDetail_thenPass() { Optional result; - result = consentRepository.findFirstByClientIdAndPsuTokenOrderByCreatedtimesDesc("123", "abc"); + result = consentRepository.findByClientIdAndPsuToken("123", "abc"); Assert.assertTrue(result.isPresent()); - result = consentRepository.findFirstByClientIdAndPsuTokenOrderByCreatedtimesDesc("123", "abcd"); + result = consentRepository.findByClientIdAndPsuToken("123", "abcd"); Assert.assertFalse(result.isPresent()); } diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java index 95d70dc11..029dd75b6 100644 --- a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java @@ -1,3 +1,8 @@ +/* + * 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; import io.mosip.esignet.api.dto.ClaimDetail; diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java b/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java index 455fc1808..1a2727be6 100644 --- a/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java +++ b/consent-service-impl/src/test/java/io/mosip/esignet/TestApplication.java @@ -1,3 +1,8 @@ +/* + * 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; import io.mosip.esignet.api.dto.AuditDTO; diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java index 268778643..4752b0b51 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/ConsentDetail.java @@ -1,3 +1,8 @@ +/* + * 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.core.dto; import io.mosip.esignet.api.dto.Claims; diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java index d7e4d8d23..436734f84 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/LinkedKycAuthResponseV2.java @@ -1,3 +1,8 @@ +/* + * 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.core.dto; import io.mosip.esignet.api.util.ConsentAction; diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index fef75ec37..ad976857b 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -1,3 +1,8 @@ +/* + * 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.services; import com.auth0.jwt.interfaces.Claim; @@ -154,7 +159,6 @@ public int compare(Map.Entry o1, Map.Entry Date: Fri, 16 Jun 2023 17:02:28 +0530 Subject: [PATCH 03/13] [ES-3] review comments fixes --- .../java/io/mosip/esignet/ConsentServiceImplTest.java | 2 +- .../java/io/mosip/esignet/core/dto/UserConsent.java | 2 +- .../mosip/esignet/services/ConsentHelperService.java | 1 - .../services/LinkedAuthorizationServiceImpl.java | 11 +++++------ 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java index 029dd75b6..4e22c42cf 100644 --- a/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java +++ b/consent-service-impl/src/test/java/io/mosip/esignet/ConsentServiceImplTest.java @@ -119,7 +119,7 @@ public void saveUserConsent_withValidDetails_thenPass() throws Exception{ Map authorizeScopes = Map.of("given_name",true,"email",true); userConsent.setAuthorizationScopes(authorizeScopes); - userConsent.setExpiry_dtimes(LocalDateTime.now()); + userConsent.setExpirydtimes(LocalDateTime.now()); userConsent.setSignature("signature"); ConsentDetail consentDetail = new ConsentDetail(); diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java index 74ef88417..558051b84 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/UserConsent.java @@ -13,7 +13,7 @@ public class UserConsent { String clientId; Claims Claims; Map authorizationScopes; - LocalDateTime expiry_dtimes; + LocalDateTime expirydtimes; String signature; String hash; List acceptedClaims; diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index ad976857b..87df2d1e9 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -45,7 +45,6 @@ public class ConsentHelperService { @Autowired private ConsentService consentService; - private final ObjectMapper objectMapper=new ObjectMapper(); @Autowired private KafkaHelperService kafkaHelperService; diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index 9b8b13e4e..2921ab9b1 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -230,18 +230,17 @@ public LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKyc @Override public LinkedConsentResponse saveConsent(LinkedConsentRequest linkedConsentRequest) throws EsignetException { OIDCTransaction transaction = cacheUtilService.getLinkedAuthTransaction(linkedConsentRequest.getLinkedTransactionId()); - if(transaction == null || ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())) { + if(transaction == null) { throw new InvalidTransactionException(); } - List acceptedClaims = linkedConsentRequest.getAcceptedClaims(); - List permittedAuthorizeScopes = linkedConsentRequest.getPermittedAuthorizeScopes(); - authorizationHelperService.validateAcceptedClaims(transaction, acceptedClaims); - authorizationHelperService.validateAuthorizeScopes(transaction, permittedAuthorizeScopes); + + authorizationHelperService.validateAcceptedClaims(transaction, linkedConsentRequest.getAcceptedClaims()); + authorizationHelperService.validateAuthorizeScopes(transaction, linkedConsentRequest.getPermittedAuthorizeScopes()); // cache consent only, auth-code will be generated on link-auth-code-status API call transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); - cacheUtilService.setLinkedConsentedTransaction(linkedConsentRequest.getLinkedTransactionId(), transaction); + //Publish message after successfully saving the consent kafkaHelperService.publish(linkedAuthCodeTopicName, linkedConsentRequest.getLinkedTransactionId()); From 5ab83f2dc6f3119be5a5916a71e864999481a803 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Fri, 16 Jun 2023 18:52:03 +0530 Subject: [PATCH 04/13] [ADDED] branch name in github actions to trigger build --- .github/workflows/codeql-analysis.yml | 1 + .github/workflows/push_trigger.yml | 1 + .../esignet/services/AuthorizationServiceImpl.java | 2 +- .../esignet/services/ConsentHelperService.java | 13 +------------ .../services/LinkedAuthorizationServiceImpl.java | 1 - 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 26d6e922d..39d8753b3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,6 +18,7 @@ on: - develop - master - 1.* + - feature-ES-3 pull_request: # # The branches below must be a subset of the branches above branches: diff --git a/.github/workflows/push_trigger.yml b/.github/workflows/push_trigger.yml index f5038f38f..e034c3bca 100644 --- a/.github/workflows/push_trigger.yml +++ b/.github/workflows/push_trigger.yml @@ -10,6 +10,7 @@ on: - 1.* - develop - main + - feature-ES-3 jobs: call-workflow-codeql-analysis: diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 0280441d0..026aaea36 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -42,7 +42,6 @@ @Slf4j @Service -@Primary public class AuthorizationServiceImpl implements AuthorizationService { @Autowired @@ -149,6 +148,7 @@ public OtpResponse sendOtp(OtpRequest otpRequest) throws EsignetException { return otpResponse; } + @Override public AuthResponse authenticateUser(AuthRequest authRequest) throws EsignetException { OIDCTransaction transaction = cacheUtilService.getPreAuthTransaction(authRequest.getTransactionId()); if(transaction == null) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 87df2d1e9..f2280d79b 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -38,20 +38,9 @@ @Slf4j @Component public class ConsentHelperService { - - @Autowired - private CacheUtilService cacheUtilService; - @Autowired private ConsentService consentService; - - @Autowired - private KafkaHelperService kafkaHelperService; - - @Value("${mosip.esignet.kafka.linked-auth-code.topic}") - private String linkedAuthCodeTopicName; - public void processConsent(OIDCTransaction transaction) { UserConsentRequest userConsentRequest = new UserConsentRequest(); userConsentRequest.setClientId(transaction.getClientId()); @@ -192,7 +181,7 @@ private String generateSignedObject(OIDCTransaction transaction, ConsentDetail c jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) ,Base64URL.encode(signature) ); } catch (ParseException e) { - + log.error(e.getLocalizedMessage()); } return jwsObject == null ? "": jwsObject.serialize(); } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index 2921ab9b1..47313c002 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -44,7 +44,6 @@ @Slf4j @Service -@Primary public class LinkedAuthorizationServiceImpl implements LinkedAuthorizationService { @Autowired From 4750ecb8fbb3631cf957b747e3d3ca0f58a3598d Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Fri, 16 Jun 2023 19:07:05 +0530 Subject: [PATCH 05/13] Resolved Merge Conflicts --- .../java/io/mosip/esignet/services/AuthorizationServiceImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 8cd54641e..026aaea36 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -148,6 +148,7 @@ public OtpResponse sendOtp(OtpRequest otpRequest) throws EsignetException { return otpResponse; } + @Override public AuthResponse authenticateUser(AuthRequest authRequest) throws EsignetException { OIDCTransaction transaction = cacheUtilService.getPreAuthTransaction(authRequest.getTransactionId()); if(transaction == null) From 3250d4802660921e9c31da25078c13e79a404d57 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Mon, 19 Jun 2023 08:26:50 +0530 Subject: [PATCH 06/13] [ES-3] Linked Consent related changes --- .../LinkedAuthorizationController.java | 28 +++++++++++ .../services/AuthorizationServiceImpl.java | 2 +- .../services/ConsentHelperService.java | 22 ++++----- .../LinkedAuthorizationServiceImpl.java | 14 +++++- .../LinkedAuthorizationServiceTest.java | 48 +++++++++++++++++++ 5 files changed, 97 insertions(+), 17 deletions(-) diff --git a/esignet-service/src/main/java/io/mosip/esignet/controllers/LinkedAuthorizationController.java b/esignet-service/src/main/java/io/mosip/esignet/controllers/LinkedAuthorizationController.java index 398af0eb0..680ff3710 100644 --- a/esignet-service/src/main/java/io/mosip/esignet/controllers/LinkedAuthorizationController.java +++ b/esignet-service/src/main/java/io/mosip/esignet/controllers/LinkedAuthorizationController.java @@ -107,6 +107,20 @@ public ResponseWrapper authenticate(@Valid @RequestBody R return responseWrapper; } + @PostMapping("/v2/authenticate") + public ResponseWrapper authenticateV2(@Valid @RequestBody RequestWrapper + requestWrapper) throws EsignetException { + ResponseWrapper responseWrapper = new ResponseWrapper(); + responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime()); + try { + responseWrapper.setResponse(linkedAuthorizationService.authenticateUserV2(requestWrapper.getRequest())); + } catch (EsignetException ex) { + auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.ERROR, AuditHelper.buildAuditDto(requestWrapper.getRequest().getLinkedTransactionId(), null), ex); + throw ex; + } + return responseWrapper; + } + @PostMapping("/consent") public ResponseWrapper saveConsent(@Valid @RequestBody RequestWrapper requestWrapper) throws EsignetException { @@ -121,6 +135,20 @@ public ResponseWrapper saveConsent(@Valid @RequestBody Re return responseWrapper; } + @PostMapping("/v2/consent") + public ResponseWrapper saveConsentV2(@Valid @RequestBody RequestWrapper + requestWrapper) throws EsignetException { + ResponseWrapper responseWrapper = new ResponseWrapper(); + responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime()); + try { + responseWrapper.setResponse(linkedAuthorizationService.saveConsentV2(requestWrapper.getRequest())); + } catch (EsignetException ex) { + auditWrapper.logAudit(Action.SAVE_CONSENT, ActionStatus.ERROR, AuditHelper.buildAuditDto(requestWrapper.getRequest().getLinkedTransactionId(), null), ex); + throw ex; + } + return responseWrapper; + } + @PostMapping("/send-otp") public ResponseWrapper sendOtp(@Valid @RequestBody RequestWrapper requestWrapper) throws EsignetException { diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 026aaea36..2c730e87d 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -194,7 +194,7 @@ public AuthResponseV2 authenticateUserV2(AuthRequest authRequest) throws Esignet .map(AuthenticationFactor::getType) .collect(Collectors.toList())).collect(Collectors.toSet())); authorizationHelperService.setIndividualId(authRequest.getIndividualId(), transaction); - consentHelperService.processConsent(transaction); + consentHelperService.processConsent(transaction, false); cacheUtilService.setAuthenticatedTransaction(authRequest.getTransactionId(), transaction); auditWrapper.logAudit(Action.AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(authRequest.getTransactionId(), transaction), null); diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index f2280d79b..4cf85c755 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -40,14 +40,13 @@ public class ConsentHelperService { @Autowired private ConsentService consentService; - - public void processConsent(OIDCTransaction transaction) { + public void processConsent(OIDCTransaction transaction, boolean linked) { UserConsentRequest userConsentRequest = new UserConsentRequest(); userConsentRequest.setClientId(transaction.getClientId()); userConsentRequest.setPsuToken(transaction.getPartnerSpecificUserToken()); Optional consent = consentService.getUserConsent(userConsentRequest); - ConsentAction consentAction = consent.isEmpty() ? ConsentAction.CAPTURE : evaluateConsentAction(transaction,consent.get()); + ConsentAction consentAction = consent.isEmpty() ? ConsentAction.CAPTURE : evaluateConsentAction(transaction,consent.get(), linked); transaction.setConsentAction(consentAction); @@ -147,7 +146,7 @@ public int compare(Map.Entry o1, Map.Entry permittedScopes = transaction.getPermittedScopes(); @@ -161,11 +160,11 @@ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, Consent return consentDetail.getHash().equals(hash) ? ConsentAction.NOCAPTURE : ConsentAction.CAPTURE; } - private String generateSignedObject(OIDCTransaction transaction, ConsentDetail consentDetail){ - List acceptedClaims = transaction.getAcceptedClaims(); - List permittedScopes = transaction.getPermittedScopes(); - Collections.sort(acceptedClaims); + private String generateSignedObject(ConsentDetail consentDetail) throws ParseException { + List acceptedClaims = consentDetail.getAcceptedClaims(); + List permittedScopes = consentDetail.getPermittedScopes(); Collections.sort(acceptedClaims); + Collections.sort(permittedScopes); JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() .claim("acceptedClaims", acceptedClaims) .claim("authorizeScopes", permittedScopes) @@ -177,13 +176,8 @@ private String generateSignedObject(OIDCTransaction transaction, ConsentDetail c String signature = parts[1]; JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.parse(header)); JWSObject jwsObject = null; - try { - jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) + jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) ,Base64URL.encode(signature) ); - } catch (ParseException e) { - log.error(e.getLocalizedMessage()); - } return jwsObject == null ? "": jwsObject.serialize(); } - } \ No newline at end of file diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index 47313c002..18f33071a 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -64,6 +64,9 @@ public class LinkedAuthorizationServiceImpl implements LinkedAuthorizationServic @Autowired private AuditPlugin auditWrapper; + @Autowired + private ConsentHelperService consentHelperService; + @Value("${mosip.esignet.link-code-expire-in-secs}") private int linkCodeExpiryInSeconds; @@ -216,12 +219,19 @@ public LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKyc transaction.setKycToken(kycAuthResult.getKycToken()); transaction.setAuthTimeInSeconds(IdentityProviderUtil.getEpochSeconds()); authorizationHelperService.setIndividualId(linkedKycAuthRequest.getIndividualId(), transaction); + consentHelperService.processConsent(transaction, true); transaction.setProvidedAuthFactors(providedAuthFactors.stream().map(acrFactors -> acrFactors.stream() .map(AuthenticationFactor::getType) .collect(Collectors.toList())).collect(Collectors.toSet())); - cacheUtilService.setLinkedAuthenticatedTransaction(linkedKycAuthRequest.getLinkedTransactionId(), transaction); + if(ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())){ + cacheUtilService.setLinkedConsentedTransaction(transaction.getLinkedTransactionId(), transaction); + kafkaHelperService.publish(linkedAuthCodeTopicName, transaction.getLinkedTransactionId()); + } else { + cacheUtilService.setLinkedAuthenticatedTransaction(linkedKycAuthRequest.getLinkedTransactionId(), transaction); + } LinkedKycAuthResponseV2 authRespDto = new LinkedKycAuthResponseV2(); authRespDto.setLinkedTransactionId(linkedKycAuthRequest.getLinkedTransactionId()); + authRespDto.setConsentAction(transaction.getConsentAction()); auditWrapper.logAudit(Action.LINK_AUTHENTICATE, ActionStatus.SUCCESS, AuditHelper.buildAuditDto(null, transaction), null); return authRespDto; } @@ -262,7 +272,7 @@ public LinkedConsentResponse saveConsentV2(LinkedConsentRequestV2 linkedConsentR // cache consent only, auth-code will be generated on link-auth-code-status API call transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); - + consentHelperService.addUserConsent(transaction, true, linkedConsentRequest.getSignature()); cacheUtilService.setLinkedConsentedTransaction(linkedConsentRequest.getLinkedTransactionId(), transaction); //Publish message after successfully saving the consent kafkaHelperService.publish(linkedAuthCodeTopicName, linkedConsentRequest.getLinkedTransactionId()); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java index 5505cfb8b..58737ce1f 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java @@ -11,6 +11,7 @@ import io.mosip.esignet.api.exception.SendOtpException; import io.mosip.esignet.api.spi.AuditPlugin; import io.mosip.esignet.api.spi.Authenticator; +import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.ErrorConstants; import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.dto.Error; @@ -69,6 +70,9 @@ public class LinkedAuthorizationServiceTest { @Mock AuditPlugin auditWrapper; + @Mock + ConsentHelperService consentHelperService; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -328,6 +332,50 @@ public void authenticateUser_withInvalidTransaction_thenFail() { } } + @Test + public void authenticateUserV2_withValidInput_thenPass() throws KycAuthException { + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId("link-transaction-id"); + + OIDCTransaction oidcTransaction = createIdpTransaction(new String[]{"mosip:idp:acr:generated-code", "mosip:idp:acr:static-code"}); + oidcTransaction.setConsentAction(ConsentAction.NOCAPTURE); + oidcTransaction.setLinkedTransactionId("link-transaction-id"); + Mockito.when(cacheUtilService.getLinkedSessionTransaction(linkedKycAuthRequest.getLinkedTransactionId())).thenReturn(oidcTransaction); + + List> allAuthFactors=new ArrayList<>(); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:generated-code")); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:static-code")); + when(authenticationContextClassRefUtil.getAuthFactors(new String[]{"mosip:idp:acr:generated-code", + "mosip:idp:acr:static-code"})).thenReturn(allAuthFactors); + + KycAuthResult kycAuthResult = new KycAuthResult(); + kycAuthResult.setKycToken("test-kyc-token"); + kycAuthResult.setPartnerSpecificUserToken("test-psut"); + when(authenticationWrapper.doKycAuth(anyString(), anyString(), any())).thenReturn(kycAuthResult); + + linkedKycAuthRequest.setIndividualId("23423434234"); + List authChallenges = new ArrayList<>(); + authChallenges.add(getAuthChallengeDto("OTP")); + linkedKycAuthRequest.setChallengeList(authChallenges); + + LinkedKycAuthResponseV2 authResponse = linkedAuthorizationService.authenticateUserV2(linkedKycAuthRequest); + Assert.assertNotNull(authResponse); + Assert.assertEquals(linkedKycAuthRequest.getLinkedTransactionId(), authResponse.getLinkedTransactionId()); + } + + @Test + public void authenticateUserV2_withInvalidTransaction_thenFail() { + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId("link-transaction-id"); + + try { + linkedAuthorizationService.authenticateUser(linkedKycAuthRequest); + Assert.fail(); + } catch (InvalidTransactionException ex) { + Assert.assertEquals(ErrorConstants.INVALID_TRANSACTION, ex.getErrorCode()); + } + } + @Test public void saveConsent_withValidInput_thenPass() { Mockito.when(cacheUtilService.getLinkedAuthTransaction("link-transaction-id")).thenReturn(new OIDCTransaction()); From 242d2f6c8f25bd51c618d6f1d75a1dc1ac8f6e12 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Mon, 19 Jun 2023 13:10:32 +0530 Subject: [PATCH 07/13] review comment fixes --- .../services/LinkedAuthorizationServiceImpl.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java index 18f33071a..35b89deb0 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/LinkedAuthorizationServiceImpl.java @@ -224,6 +224,7 @@ public LinkedKycAuthResponseV2 authenticateUserV2(LinkedKycAuthRequest linkedKyc .map(AuthenticationFactor::getType) .collect(Collectors.toList())).collect(Collectors.toSet())); if(ConsentAction.NOCAPTURE.equals(transaction.getConsentAction())){ + validateConsent(transaction, transaction.getAcceptedClaims(), transaction.getPermittedScopes()); cacheUtilService.setLinkedConsentedTransaction(transaction.getLinkedTransactionId(), transaction); kafkaHelperService.publish(linkedAuthCodeTopicName, transaction.getLinkedTransactionId()); } else { @@ -242,9 +243,7 @@ public LinkedConsentResponse saveConsent(LinkedConsentRequest linkedConsentReque if(transaction == null) { throw new InvalidTransactionException(); } - - authorizationHelperService.validateAcceptedClaims(transaction, linkedConsentRequest.getAcceptedClaims()); - authorizationHelperService.validateAuthorizeScopes(transaction, linkedConsentRequest.getPermittedAuthorizeScopes()); + validateConsent(transaction, linkedConsentRequest.getAcceptedClaims(), linkedConsentRequest.getPermittedAuthorizeScopes()); // cache consent only, auth-code will be generated on link-auth-code-status API call transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); @@ -267,8 +266,7 @@ public LinkedConsentResponse saveConsentV2(LinkedConsentRequestV2 linkedConsentR } List acceptedClaims = linkedConsentRequest.getAcceptedClaims(); List permittedAuthorizeScopes = linkedConsentRequest.getPermittedAuthorizeScopes(); - authorizationHelperService.validateAcceptedClaims(transaction, acceptedClaims); - authorizationHelperService.validateAuthorizeScopes(transaction, permittedAuthorizeScopes); + validateConsent(transaction, linkedConsentRequest.getAcceptedClaims(), linkedConsentRequest.getPermittedAuthorizeScopes()); // cache consent only, auth-code will be generated on link-auth-code-status API call transaction.setAcceptedClaims(linkedConsentRequest.getAcceptedClaims()); transaction.setPermittedScopes(linkedConsentRequest.getPermittedAuthorizeScopes()); @@ -320,4 +318,10 @@ public void getLinkAuthCode(DeferredResult deferredResult, LinkAuthCodeRequest l authorizationHelperService.addEntryInLinkAuthCodeStatusDeferredResultMap(linkTransactionMetadata.getLinkedTransactionId(), deferredResult); } } + + + private void validateConsent(OIDCTransaction transaction, List acceptedClaims, List permittedScopes) { + authorizationHelperService.validateAcceptedClaims(transaction, acceptedClaims); + authorizationHelperService.validateAuthorizeScopes(transaction, permittedScopes); + } } From 623511cc5f26165b1d5d973a2d758a1cee59c857 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Tue, 20 Jun 2023 05:55:04 +0530 Subject: [PATCH 08/13] [BUGFIX] fixed issue with consent NOCAPTURE and transaction not completing [ADDED] support methods for performing signature verification --- .../PublicKeyRegistryServiceImpl.java | 34 +++++++++++ .../esignet/config/ModelMapperConfig.java | 8 --- .../mosip/esignet/mapper/ConsentMapper.java | 4 +- .../mapper/CustomConsentHistoryMapping.java | 1 - .../esignet/services/ConsentServiceImpl.java | 7 +-- .../mosip_esignet/ddl/esignet-consent.sql | 6 +- .../ddl/esignet-consent_history.sql | 8 +-- .../esignet/core/dto/PublicKeyRegistry.java | 19 +++++++ .../core/spi/PublicKeyRegistryService.java | 14 +++++ .../services/ConsentHelperService.java | 56 ++++++++++++------- 10 files changed, 115 insertions(+), 42 deletions(-) create mode 100644 binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java create mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java diff --git a/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java b/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java new file mode 100644 index 000000000..ef7ad1ca4 --- /dev/null +++ b/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java @@ -0,0 +1,34 @@ +/* + * 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.services; + +import io.mosip.esignet.core.dto.PublicKeyRegistry; +import io.mosip.esignet.core.spi.PublicKeyRegistryService; +import io.mosip.esignet.repository.PublicKeyRegistryRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Slf4j +@Service +public class PublicKeyRegistryServiceImpl implements PublicKeyRegistryService { + @Autowired + private PublicKeyRegistryRepository publicKeyRegistryRepository; + @Override + public Optional findLatestPublicKeyByPsuTokenAndAuthFactor(String psuToken, String authFactor) { + Optional optionalPublicKeyRegistry = publicKeyRegistryRepository.findLatestByPsuTokenAndAuthFactor(psuToken,authFactor); + if(optionalPublicKeyRegistry.isPresent()) { + PublicKeyRegistry publicKeyRegistry = new PublicKeyRegistry(); + publicKeyRegistry.setPublicKey(optionalPublicKeyRegistry.get().getPublicKey()); + publicKeyRegistry.setPsuToken(optionalPublicKeyRegistry.get().getPsuToken()); + publicKeyRegistry.setAuthFactor(optionalPublicKeyRegistry.get().getAuthFactor()); + return Optional.of(publicKeyRegistry); + } + return Optional.empty(); + } +} diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java b/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java index d57b26b7b..32c99cd43 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/config/ModelMapperConfig.java @@ -6,12 +6,9 @@ package io.mosip.esignet.config; -import io.mosip.esignet.mapper.ConsentMapper; -import io.mosip.esignet.services.ConsentServiceImpl; import org.modelmapper.ModelMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @Configuration public class ModelMapperConfig { @@ -21,9 +18,4 @@ public ModelMapper modelMapper() { return new ModelMapper(); } - @Bean - public ConsentMapper consentMapper() { - return new ConsentMapper(); - } - } diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java index 92fcf29a7..5c7ed9448 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/ConsentMapper.java @@ -15,6 +15,9 @@ public class ConsentMapper { + + private ConsentMapper(){} + private static final ModelMapper modelMapper = new ModelMapper(); static { @@ -27,7 +30,6 @@ public class ConsentMapper { modelMapper.addConverter(new StringToListConverter()); modelMapper.addMappings(new CustomConsentRequestMapping()); modelMapper.addMappings(new CustomConsentHistoryMapping()); - //modelMapper.getConfiguration().setSkipNullEnabled(true); } public static io.mosip.esignet.entity.ConsentDetail toEntity(ConsentDetail consentDetailDTo) { diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java index 20b237d9d..6e1b5d1ad 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/mapper/CustomConsentHistoryMapping.java @@ -6,7 +6,6 @@ package io.mosip.esignet.mapper; import io.mosip.esignet.core.dto.UserConsent; -import io.mosip.esignet.entity.ConsentDetail; import io.mosip.esignet.entity.ConsentHistory; import org.modelmapper.PropertyMap; diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java index 507a86934..0714721cb 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java @@ -24,9 +24,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import javax.transaction.Transactional; import java.time.LocalDateTime; -import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Optional; @@ -64,11 +62,10 @@ public Optional getUserConsent(UserConsentRequest userConsentRequ } @Override - @Transactional public ConsentDetail saveUserConsent(UserConsent userConsent) { - Optional ClientDetailOptional = + Optional clientDetailOptional = consentRepository.findByClientIdAndPsuToken(userConsent.getClientId(), userConsent.getPsuToken()); - if(ClientDetailOptional.isPresent()) { + if(clientDetailOptional.isPresent()) { consentRepository.deleteByClientIdAndPsuToken(userConsent.getClientId(), userConsent.getPsuToken()); } LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent.sql b/db_scripts/mosip_esignet/ddl/esignet-consent.sql index ce941e823..ad7873f60 100644 --- a/db_scripts/mosip_esignet/ddl/esignet-consent.sql +++ b/db_scripts/mosip_esignet/ddl/esignet-consent.sql @@ -41,7 +41,7 @@ COMMENT ON COLUMN consent_detail.authorization_scopes IS 'Json string of user ac COMMENT ON COLUMN consent_detail.cr_dtimes IS 'Consent creation date'; COMMENT ON COLUMN consent_detail.expire_dtimes IS 'Expiration date'; COMMENT ON COLUMN consent_detail.signature IS 'Signature of consent object '; -COMMENT ON COLUMN consent_detail.hash IS 'hash of consent object' -COMMENT ON COLUMN consent_detail.accepted_claims IS 'Accepted Claims by the user' -COMMENT ON COLUMN consent_detail.permitted_scopes IS 'Accepted Scopes by the user' +COMMENT ON COLUMN consent_detail.hash IS 'hash of consent object'; +COMMENT ON COLUMN consent_detail.accepted_claims IS 'Accepted Claims by the user'; +COMMENT ON COLUMN consent_detail.permitted_scopes IS 'Accepted Scopes by the user'; diff --git a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql index de64fca13..ef824227a 100644 --- a/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql +++ b/db_scripts/mosip_esignet/ddl/esignet-consent_history.sql @@ -27,7 +27,7 @@ create table consent_history ( permitted_scopes VARCHAR, PRIMARY KEY (id) ); -CREATE INDEX IF NOT EXISTS idx_consent_psu_client ON consent_history(psu_token, client_id); +CREATE INDEX IF NOT EXISTS idx_consent_history_psu_client ON consent_history(psu_token, client_id); COMMENT ON TABLE consent_history IS 'Contains user consent details'; @@ -39,7 +39,7 @@ COMMENT ON COLUMN consent_history.authorization_scopes IS 'Json string of user a COMMENT ON COLUMN consent_history.cr_dtimes IS 'Consent creation date'; COMMENT ON COLUMN consent_history.expire_dtimes IS 'Expiration date'; COMMENT ON COLUMN consent_history.signature IS 'Signature of consent object '; -COMMENT ON COLUMN consent_history.hash IS 'hash of consent object' -COMMENT ON COLUMN consent_history.accepted_claims IS 'Accepted Claims by the user' -COMMENT ON COLUMN consent_history.permitted_scopes IS 'Accepted Scopes by the user' +COMMENT ON COLUMN consent_history.hash IS 'hash of consent object'; +COMMENT ON COLUMN consent_history.accepted_claims IS 'Accepted Claims by the user'; +COMMENT ON COLUMN consent_history.permitted_scopes IS 'Accepted Scopes by the user'; diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java new file mode 100644 index 000000000..99ccfe159 --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java @@ -0,0 +1,19 @@ +/* + * 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.core.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class PublicKeyRegistry { + private String authFactor; + private String psuToken; + private String publicKey; +} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java new file mode 100644 index 000000000..8b6583b3e --- /dev/null +++ b/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java @@ -0,0 +1,14 @@ +/* + * 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.core.spi; + +import io.mosip.esignet.core.dto.PublicKeyRegistry; + +import java.util.Optional; + +public interface PublicKeyRegistryService { + Optional findLatestPublicKeyByPsuTokenAndAuthFactor(String psuToken, String authFactor); +} diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 4cf85c755..bd3363b35 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -5,29 +5,27 @@ */ package io.mosip.esignet.services; -import com.auth0.jwt.interfaces.Claim; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSObject; +import com.nimbusds.jose.*; +import com.nimbusds.jose.crypto.RSASSAVerifier; +import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.util.Base64URL; import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.SignedJWT; import io.mosip.esignet.api.dto.ClaimDetail; import io.mosip.esignet.api.dto.Claims; import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.ErrorConstants; import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.EsignetException; -import io.mosip.esignet.core.exception.InvalidTransactionException; import io.mosip.esignet.core.spi.ConsentService; +import io.mosip.esignet.core.spi.PublicKeyRegistryService; import io.mosip.esignet.core.util.IdentityProviderUtil; -import io.mosip.esignet.core.util.KafkaHelperService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.security.interfaces.RSAPublicKey; import java.text.ParseException; import java.util.*; import java.util.function.Function; @@ -40,6 +38,10 @@ public class ConsentHelperService { @Autowired private ConsentService consentService; + + @Autowired + PublicKeyRegistryService publicKeyRegistryService; + public void processConsent(OIDCTransaction transaction, boolean linked) { UserConsentRequest userConsentRequest = new UserConsentRequest(); userConsentRequest.setClientId(transaction.getClientId()); @@ -50,7 +52,8 @@ public void processConsent(OIDCTransaction transaction, boolean linked) { transaction.setConsentAction(consentAction); - if(consentAction.equals(ConsentAction.NOCAPTURE)) { + //resolves reported sonar bug. This is a false positive since consent.isPresent() will always evaluate to true + if(consentAction.equals(ConsentAction.NOCAPTURE) && consent.isPresent()) { transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); transaction.setPermittedScopes(consent.get().getPermittedScopes()); } @@ -66,7 +69,7 @@ public void addUserConsent(OIDCTransaction transaction, boolean linked, String s List acceptedClaims = transaction.getAcceptedClaims(); Claims normalizedClaims = new Claims(); normalizedClaims.setUserinfo(normalizeClaims(claims.getUserinfo())); - normalizedClaims.setId_token(claims.getId_token()); + normalizedClaims.setId_token(normalizeClaims(claims.getId_token())); userConsent.setClaims(normalizedClaims); userConsent.setSignature(signature); @@ -153,31 +156,44 @@ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, Consent List authorizeScope = transaction.getRequestedAuthorizeScopes(); Map authorizeScopes = permittedScopes != null ? permittedScopes.stream() .collect(Collectors.toMap(Function.identity(), authorizeScope::contains)) : Collections.emptyMap(); - hash = hashUserConsent(transaction.getRequestedClaims(),authorizeScopes ); + Claims normalizedClaims = new Claims(); + normalizedClaims.setUserinfo(normalizeClaims(transaction.getRequestedClaims().getUserinfo())); + normalizedClaims.setId_token(normalizeClaims(transaction.getRequestedClaims().getId_token())); + hash = hashUserConsent(normalizedClaims, authorizeScopes); } catch (JsonProcessingException e) { throw new EsignetException(ErrorConstants.INVALID_CLAIM); } return consentDetail.getHash().equals(hash) ? ConsentAction.NOCAPTURE : ConsentAction.CAPTURE; } - private String generateSignedObject(ConsentDetail consentDetail) throws ParseException { - List acceptedClaims = consentDetail.getAcceptedClaims(); - List permittedScopes = consentDetail.getPermittedScopes(); + private boolean validateSignature(String psuToken, String jws, String authFactor){ + Optional publicKeyRegistry = publicKeyRegistryService.findLatestPublicKeyByPsuTokenAndAuthFactor(psuToken, authFactor); + if(publicKeyRegistry.isPresent()) { + String publicKey = publicKeyRegistry.get().getPublicKey(); + try { + RSAPublicKey rsaPublicKey = RSAKey.parse(publicKey).toRSAPublicKey(); + JWSVerifier verifier = new RSASSAVerifier(rsaPublicKey); + SignedJWT jwt = SignedJWT.parse(jws); + return jwt.verify(verifier); + } catch (JOSEException | ParseException e) { + log.error("Error in processing public key", e); + } + } + return false; + } + private String generateSignedObject(List acceptedClaims, List permittedScopes, String jws) throws ParseException { Collections.sort(acceptedClaims); Collections.sort(permittedScopes); JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() .claim("acceptedClaims", acceptedClaims) .claim("authorizeScopes", permittedScopes) .build(); - String jws = consentDetail.getSignature(); String[] parts = jws.split("\\."); - String header = parts[0]; String signature = parts[1]; JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.parse(header)); - JWSObject jwsObject = null; - jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) - ,Base64URL.encode(signature) ); - return jwsObject == null ? "": jwsObject.serialize(); + JWSObject jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) + , Base64URL.encode(signature)); + return jwsObject.serialize(); } } \ No newline at end of file From e94ded474c1d3b32cecfd7ab6a709745a149d10b Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Tue, 20 Jun 2023 06:41:47 +0530 Subject: [PATCH 09/13] Transaction changes --- .../java/io/mosip/esignet/services/ConsentServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java index 0714721cb..8dfbd576d 100644 --- a/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java +++ b/consent-service-impl/src/main/java/io/mosip/esignet/services/ConsentServiceImpl.java @@ -24,6 +24,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import javax.transaction.Transactional; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Optional; @@ -62,11 +63,13 @@ public Optional getUserConsent(UserConsentRequest userConsentRequ } @Override + @Transactional public ConsentDetail saveUserConsent(UserConsent userConsent) { Optional clientDetailOptional = consentRepository.findByClientIdAndPsuToken(userConsent.getClientId(), userConsent.getPsuToken()); if(clientDetailOptional.isPresent()) { consentRepository.deleteByClientIdAndPsuToken(userConsent.getClientId(), userConsent.getPsuToken()); + consentRepository.flush(); } LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC); //convert ConsentRequest to Entity From 805a7a47eb2bef6ab0b89786ba812fa2f704936a Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Tue, 20 Jun 2023 07:02:00 +0530 Subject: [PATCH 10/13] [formatting changes] --- .../io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java | 2 ++ .../io/mosip/esignet/core/spi/PublicKeyRegistryService.java | 2 ++ .../java/io/mosip/esignet/services/ConsentHelperService.java | 1 + 3 files changed, 5 insertions(+) diff --git a/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java b/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java index ef7ad1ca4..ea733c08c 100644 --- a/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java +++ b/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java @@ -17,8 +17,10 @@ @Slf4j @Service public class PublicKeyRegistryServiceImpl implements PublicKeyRegistryService { + @Autowired private PublicKeyRegistryRepository publicKeyRegistryRepository; + @Override public Optional findLatestPublicKeyByPsuTokenAndAuthFactor(String psuToken, String authFactor) { Optional optionalPublicKeyRegistry = publicKeyRegistryRepository.findLatestByPsuTokenAndAuthFactor(psuToken,authFactor); diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java index 8b6583b3e..997e1f4c2 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java @@ -10,5 +10,7 @@ import java.util.Optional; public interface PublicKeyRegistryService { + Optional findLatestPublicKeyByPsuTokenAndAuthFactor(String psuToken, String authFactor); + } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index bd3363b35..064ff162b 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -181,6 +181,7 @@ private boolean validateSignature(String psuToken, String jws, String authFactor } return false; } + private String generateSignedObject(List acceptedClaims, List permittedScopes, String jws) throws ParseException { Collections.sort(acceptedClaims); Collections.sort(permittedScopes); From 46a1dad2ba5a02f55b30269eee4088d1ef20248a Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Sat, 24 Jun 2023 14:48:34 +0530 Subject: [PATCH 11/13] [ADDED] additional test cases, fixed sonar reports --- .../PublicKeyRegistryServiceImpl.java | 36 --- .../esignet/core/dto/PublicKeyRegistry.java | 19 -- .../core/spi/PublicKeyRegistryService.java | 16 -- .../LinkedAuthorizationControllerTest.java | 184 +++++++++++++++ .../services/ConsentHelperService.java | 61 ++--- .../services/AuthorizationServiceTest.java | 131 +++++++++++ .../services/ConsentHelperServiceTest.java | 221 ++++++++++++++++++ .../LinkedAuthorizationServiceTest.java | 24 +- 8 files changed, 572 insertions(+), 120 deletions(-) delete mode 100644 binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java delete mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java delete mode 100644 esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java create mode 100644 oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java diff --git a/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java b/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java deleted file mode 100644 index ea733c08c..000000000 --- a/binding-service-impl/src/main/java/io/mosip/esignet/services/PublicKeyRegistryServiceImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.services; - -import io.mosip.esignet.core.dto.PublicKeyRegistry; -import io.mosip.esignet.core.spi.PublicKeyRegistryService; -import io.mosip.esignet.repository.PublicKeyRegistryRepository; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@Slf4j -@Service -public class PublicKeyRegistryServiceImpl implements PublicKeyRegistryService { - - @Autowired - private PublicKeyRegistryRepository publicKeyRegistryRepository; - - @Override - public Optional findLatestPublicKeyByPsuTokenAndAuthFactor(String psuToken, String authFactor) { - Optional optionalPublicKeyRegistry = publicKeyRegistryRepository.findLatestByPsuTokenAndAuthFactor(psuToken,authFactor); - if(optionalPublicKeyRegistry.isPresent()) { - PublicKeyRegistry publicKeyRegistry = new PublicKeyRegistry(); - publicKeyRegistry.setPublicKey(optionalPublicKeyRegistry.get().getPublicKey()); - publicKeyRegistry.setPsuToken(optionalPublicKeyRegistry.get().getPsuToken()); - publicKeyRegistry.setAuthFactor(optionalPublicKeyRegistry.get().getAuthFactor()); - return Optional.of(publicKeyRegistry); - } - return Optional.empty(); - } -} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java b/esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java deleted file mode 100644 index 99ccfe159..000000000 --- a/esignet-core/src/main/java/io/mosip/esignet/core/dto/PublicKeyRegistry.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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.core.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@AllArgsConstructor -@NoArgsConstructor -@Data -public class PublicKeyRegistry { - private String authFactor; - private String psuToken; - private String publicKey; -} diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java b/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java deleted file mode 100644 index 997e1f4c2..000000000 --- a/esignet-core/src/main/java/io/mosip/esignet/core/spi/PublicKeyRegistryService.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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.core.spi; - -import io.mosip.esignet.core.dto.PublicKeyRegistry; - -import java.util.Optional; - -public interface PublicKeyRegistryService { - - Optional findLatestPublicKeyByPsuTokenAndAuthFactor(String psuToken, String authFactor); - -} diff --git a/esignet-service/src/test/java/io/mosip/esignet/controllers/LinkedAuthorizationControllerTest.java b/esignet-service/src/test/java/io/mosip/esignet/controllers/LinkedAuthorizationControllerTest.java index 9311350f3..f22c8fad8 100644 --- a/esignet-service/src/test/java/io/mosip/esignet/controllers/LinkedAuthorizationControllerTest.java +++ b/esignet-service/src/test/java/io/mosip/esignet/controllers/LinkedAuthorizationControllerTest.java @@ -49,9 +49,11 @@ import io.mosip.esignet.core.dto.LinkTransactionRequest; import io.mosip.esignet.core.dto.LinkTransactionResponse; import io.mosip.esignet.core.dto.LinkedConsentRequest; +import io.mosip.esignet.core.dto.LinkedConsentRequestV2; import io.mosip.esignet.core.dto.LinkedConsentResponse; import io.mosip.esignet.core.dto.LinkedKycAuthRequest; import io.mosip.esignet.core.dto.LinkedKycAuthResponse; +import io.mosip.esignet.core.dto.LinkedKycAuthResponseV2; import io.mosip.esignet.core.dto.OtpRequest; import io.mosip.esignet.core.dto.OtpResponse; import io.mosip.esignet.core.dto.RequestWrapper; @@ -565,4 +567,186 @@ public void getLinkAuthCode_withTimeout_thenFail() throws Exception { .andExpect(jsonPath("$.errors").isNotEmpty()) .andExpect(jsonPath("$.errors[0].errorCode").value(RESPONSE_TIMEOUT)); } + + @Test + public void authenticateV2_withValidRequest_thenPass() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId("link-transaction-id"); + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setFormat("format"); + authChallenge.setAuthFactorType("OTP"); + authChallenge.setChallenge("challenge"); + linkedKycAuthRequest.setChallengeList(Arrays.asList(authChallenge)); + linkedKycAuthRequest.setIndividualId("individualId"); + requestWrapper.setRequest(linkedKycAuthRequest); + + Mockito.when(linkedAuthorizationService.authenticateUserV2(Mockito.any(LinkedKycAuthRequest.class))).thenReturn(new LinkedKycAuthResponseV2()); + + mockMvc.perform(post("/linked-authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response").exists()) + .andExpect(jsonPath("$.errors").isEmpty()); + } + + @Test + public void authenticateV2_withException_thenFail() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId("link-transaction-id"); + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setFormat("format"); + authChallenge.setAuthFactorType("OTP"); + authChallenge.setChallenge("challenge"); + linkedKycAuthRequest.setChallengeList(Arrays.asList(authChallenge)); + linkedKycAuthRequest.setIndividualId("individualId"); + requestWrapper.setRequest(linkedKycAuthRequest); + + Mockito.when(linkedAuthorizationService.authenticateUserV2(Mockito.any(LinkedKycAuthRequest.class))).thenThrow(EsignetException.class); + + mockMvc.perform(post("/linked-authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()); + } + + @Test + public void authenticateV2_withInvalidTransactionId_thenFail() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId(" "); + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setFormat("format"); + authChallenge.setAuthFactorType("OTP"); + authChallenge.setChallenge("challenge"); + linkedKycAuthRequest.setChallengeList(Arrays.asList(authChallenge)); + linkedKycAuthRequest.setIndividualId("individualId"); + requestWrapper.setRequest(linkedKycAuthRequest); + + mockMvc.perform(post("/linked-authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_TRANSACTION_ID)); + } + + @Test + public void authenticateV2_withInvalidIndividualId_thenFail() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId("txn-id"); + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setFormat("format"); + authChallenge.setAuthFactorType("OTP"); + authChallenge.setChallenge("challenge"); + linkedKycAuthRequest.setChallengeList(Arrays.asList(authChallenge)); + linkedKycAuthRequest.setIndividualId(""); + requestWrapper.setRequest(linkedKycAuthRequest); + + mockMvc.perform(post("/linked-authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_IDENTIFIER)); + } + + @Test + public void authenticateV2_withInvalidChallengeList_thenFail() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedKycAuthRequest linkedKycAuthRequest = new LinkedKycAuthRequest(); + linkedKycAuthRequest.setLinkedTransactionId("txn-id"); + linkedKycAuthRequest.setIndividualId("individualId"); + requestWrapper.setRequest(linkedKycAuthRequest); + + mockMvc.perform(post("/linked-authorization/v2/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_CHALLENGE_LIST)); + + linkedKycAuthRequest.setChallengeList(new ArrayList<>()); + mockMvc.perform(post("/linked-authorization/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(ErrorConstants.INVALID_CHALLENGE_LIST)); + + AuthChallenge authChallenge = new AuthChallenge(); + linkedKycAuthRequest.setChallengeList(Arrays.asList(authChallenge)); + MvcResult mvcResult = mockMvc.perform(post("/linked-authorization/authenticate") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()).andReturn(); + + List errorCodes = Arrays.asList(INVALID_AUTH_FACTOR_TYPE, INVALID_CHALLENGE, INVALID_CHALLENGE_FORMAT); + ResponseWrapper responseWrapper = objectMapper.readValue(mvcResult.getResponse().getContentAsString(), ResponseWrapper.class); + Assert.assertTrue(responseWrapper.getErrors().size() == 3); + Assert.assertTrue(errorCodes.contains(((Error)responseWrapper.getErrors().get(0)).getErrorCode())); + Assert.assertTrue(errorCodes.contains(((Error)responseWrapper.getErrors().get(1)).getErrorCode())); + Assert.assertTrue(errorCodes.contains(((Error)responseWrapper.getErrors().get(2)).getErrorCode())); + } + + @Test + public void saveConsentV2_withValidRequest_thenPass() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedConsentRequestV2 linkedConsentRequestV2 = new LinkedConsentRequestV2(); + linkedConsentRequestV2.setLinkedTransactionId("link-transaction-id"); + requestWrapper.setRequest(linkedConsentRequestV2); + + LinkedConsentResponse linkedConsentResponse = new LinkedConsentResponse(); + Mockito.when(linkedAuthorizationService.saveConsentV2(Mockito.any(LinkedConsentRequestV2.class))).thenReturn(linkedConsentResponse); + + mockMvc.perform(post("/linked-authorization/v2/consent") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.response").exists()) + .andExpect(jsonPath("$.errors").isEmpty()); + } + + @Test + public void saveConsentV2_withException_thenFail() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedConsentRequestV2 linkedConsentRequestV2 = new LinkedConsentRequestV2(); + linkedConsentRequestV2.setLinkedTransactionId("link-transaction-id"); + requestWrapper.setRequest(linkedConsentRequestV2); + + Mockito.when(linkedAuthorizationService.saveConsentV2(Mockito.any(LinkedConsentRequestV2.class))).thenThrow(EsignetException.class); + + mockMvc.perform(post("/linked-authorization/v2/consent") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()); + } + + @Test + public void saveConsentV2_withInvalidTransactionId_thenFail() throws Exception { + RequestWrapper requestWrapper = new RequestWrapper<>(); + requestWrapper.setRequestTime(IdentityProviderUtil.getUTCDateTime()); + LinkedConsentRequestV2 linkedConsentRequestV2 = new LinkedConsentRequestV2(); + linkedConsentRequestV2.setLinkedTransactionId(" "); + requestWrapper.setRequest(linkedConsentRequestV2); + + mockMvc.perform(post("/linked-authorization/v2/consent") + .content(objectMapper.writeValueAsString(requestWrapper)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.errors").isNotEmpty()) + .andExpect(jsonPath("$.errors[0].errorCode").value(INVALID_TRANSACTION_ID)); + } } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 064ff162b..7130f360d 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -6,27 +6,21 @@ package io.mosip.esignet.services; import com.fasterxml.jackson.core.JsonProcessingException; -import com.nimbusds.jose.*; -import com.nimbusds.jose.crypto.RSASSAVerifier; -import com.nimbusds.jose.jwk.RSAKey; -import com.nimbusds.jose.util.Base64URL; -import com.nimbusds.jwt.JWTClaimsSet; -import com.nimbusds.jwt.SignedJWT; import io.mosip.esignet.api.dto.ClaimDetail; import io.mosip.esignet.api.dto.Claims; import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.ErrorConstants; -import io.mosip.esignet.core.dto.*; +import io.mosip.esignet.core.dto.ConsentDetail; +import io.mosip.esignet.core.dto.OIDCTransaction; +import io.mosip.esignet.core.dto.UserConsent; +import io.mosip.esignet.core.dto.UserConsentRequest; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.spi.ConsentService; -import io.mosip.esignet.core.spi.PublicKeyRegistryService; import io.mosip.esignet.core.util.IdentityProviderUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.security.interfaces.RSAPublicKey; -import java.text.ParseException; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -39,9 +33,6 @@ public class ConsentHelperService { @Autowired private ConsentService consentService; - @Autowired - PublicKeyRegistryService publicKeyRegistryService; - public void processConsent(OIDCTransaction transaction, boolean linked) { UserConsentRequest userConsentRequest = new UserConsentRequest(); userConsentRequest.setClientId(transaction.getClientId()); @@ -52,8 +43,7 @@ public void processConsent(OIDCTransaction transaction, boolean linked) { transaction.setConsentAction(consentAction); - //resolves reported sonar bug. This is a false positive since consent.isPresent() will always evaluate to true - if(consentAction.equals(ConsentAction.NOCAPTURE) && consent.isPresent()) { + if(consentAction.equals(ConsentAction.NOCAPTURE)) { //NOSONAR consent is already evaluated to be not null transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); transaction.setPermittedScopes(consent.get().getPermittedScopes()); } @@ -145,8 +135,15 @@ public int compare(Map.Entry o1, Map.Entry entry : entryList) { - sortedMap.put(entry.getKey(), entry.getValue()); + sortedMap.put(entry.getKey(), sortClaimDetail(entry.getValue())); + } + } + + private static ClaimDetail sortClaimDetail(ClaimDetail claimDetail){ + if(claimDetail!= null && claimDetail.getValues() != null) { + Arrays.sort(claimDetail.getValues()); } + return claimDetail; } private ConsentAction evaluateConsentAction(OIDCTransaction transaction, ConsentDetail consentDetail, boolean linked) { @@ -165,36 +162,4 @@ private ConsentAction evaluateConsentAction(OIDCTransaction transaction, Consent } return consentDetail.getHash().equals(hash) ? ConsentAction.NOCAPTURE : ConsentAction.CAPTURE; } - - private boolean validateSignature(String psuToken, String jws, String authFactor){ - Optional publicKeyRegistry = publicKeyRegistryService.findLatestPublicKeyByPsuTokenAndAuthFactor(psuToken, authFactor); - if(publicKeyRegistry.isPresent()) { - String publicKey = publicKeyRegistry.get().getPublicKey(); - try { - RSAPublicKey rsaPublicKey = RSAKey.parse(publicKey).toRSAPublicKey(); - JWSVerifier verifier = new RSASSAVerifier(rsaPublicKey); - SignedJWT jwt = SignedJWT.parse(jws); - return jwt.verify(verifier); - } catch (JOSEException | ParseException e) { - log.error("Error in processing public key", e); - } - } - return false; - } - - private String generateSignedObject(List acceptedClaims, List permittedScopes, String jws) throws ParseException { - Collections.sort(acceptedClaims); - Collections.sort(permittedScopes); - JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() - .claim("acceptedClaims", acceptedClaims) - .claim("authorizeScopes", permittedScopes) - .build(); - String[] parts = jws.split("\\."); - String header = parts[0]; - String signature = parts[1]; - JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.parse(header)); - JWSObject jwsObject = new JWSObject(jwsHeader.toBase64URL(), Base64URL.encode(claimsSet.toJSONObject().toJSONString()) - , Base64URL.encode(signature)); - return jwsObject.serialize(); - } } \ No newline at end of file diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java index 0c0b766e7..d2a179b0c 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java @@ -512,6 +512,137 @@ public void authenticate_multipleRegisteredAcrsWithInvalidMultiFactor_thenPass() Assert.assertTrue(ex.getErrorCode().equals(ErrorConstants.AUTH_FACTOR_MISMATCH)); } } + + @Test + public void authenticateV2_withInvalidTransaction_thenFail() { + String transactionId = "test-transaction"; + when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(null); + + AuthRequest authRequest = new AuthRequest(); + authRequest.setTransactionId(transactionId); + try { + authorizationServiceImpl.authenticateUserV2(authRequest); + Assert.fail(); + } catch (EsignetException ex) { + Assert.assertTrue(ex.getErrorCode().equals(ErrorConstants.INVALID_TRANSACTION)); + } + } + + @Test + public void authenticateV2_multipleRegisteredAcrsWithSingleFactor_thenPass() throws EsignetException, KycAuthException { + String transactionId = "test-transaction"; + when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(createIdpTransaction( + new String[]{"mosip:idp:acr:generated-code", "mosip:idp:acr:static-code"})); + + List> allAuthFactors=new ArrayList<>(); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:generated-code")); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:static-code")); + when(authenticationContextClassRefUtil.getAuthFactors(new String[]{"mosip:idp:acr:generated-code", + "mosip:idp:acr:static-code"})).thenReturn(allAuthFactors); + + KycAuthResult kycAuthResult = new KycAuthResult(); + kycAuthResult.setKycToken("test-kyc-token"); + kycAuthResult.setPartnerSpecificUserToken("test-psut"); + when(authenticationWrapper.doKycAuth(anyString(), anyString(), any())).thenReturn(kycAuthResult); + + AuthRequest authRequest = new AuthRequest(); + authRequest.setTransactionId(transactionId); + authRequest.setIndividualId("23423434234"); + List authChallenges = new ArrayList<>(); + authChallenges.add(getAuthChallengeDto("OTP")); + authRequest.setChallengeList(authChallenges); + + AuthResponseV2 authResponseV2 = authorizationServiceImpl.authenticateUserV2(authRequest); + Assert.assertNotNull(authResponseV2); + Assert.assertEquals(transactionId, authResponseV2.getTransactionId()); + } + + @Test + public void authenticateV2_multipleRegisteredAcrsWithInvalidSingleFactor_thenFail() throws EsignetException { + String transactionId = "test-transaction"; + when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(createIdpTransaction( + new String[]{"mosip:idp:acr:generated-code", "mosip:idp:acr:static-code"})); + + List> allAuthFactors=new ArrayList<>(); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:generated-code")); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:static-code")); + when(authenticationContextClassRefUtil.getAuthFactors(new String[]{"mosip:idp:acr:generated-code", + "mosip:idp:acr:static-code"})).thenReturn(allAuthFactors); + + AuthRequest authRequest = new AuthRequest(); + authRequest.setTransactionId(transactionId); + authRequest.setIndividualId("23423434234"); + List authChallenges = new ArrayList<>(); + authChallenges.add(getAuthChallengeDto("BIO")); + authRequest.setChallengeList(authChallenges); + + try { + authorizationServiceImpl.authenticateUserV2(authRequest); + Assert.fail(); + } catch (EsignetException ex) { + Assert.assertTrue(ex.getErrorCode().equals(ErrorConstants.AUTH_FACTOR_MISMATCH)); + } + } + + @Test + public void authenticateV2_multipleRegisteredAcrsWithMultiFactor_thenPass() throws EsignetException, KycAuthException { + String transactionId = "test-transaction"; + String consentAction="Capture"; + when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(createIdpTransaction( + new String[]{"mosip:idp:acr:biometrics-generated-code", "mosip:idp:acr:static-code"})); + + List> allAuthFactors=new ArrayList<>(); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:biometrics-generated-code")); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:static-code")); + when(authenticationContextClassRefUtil.getAuthFactors(new String[]{"mosip:idp:acr:biometrics-generated-code", + "mosip:idp:acr:static-code"})).thenReturn(allAuthFactors); + + KycAuthResult kycAuthResult = new KycAuthResult(); + kycAuthResult.setKycToken("test-kyc-token"); + kycAuthResult.setPartnerSpecificUserToken("test-psut"); + when(authenticationWrapper.doKycAuth(anyString(), anyString(), any())).thenReturn(kycAuthResult); + + AuthRequest authRequest = new AuthRequest(); + authRequest.setTransactionId(transactionId); + authRequest.setIndividualId("23423434234"); + List authChallenges = new ArrayList<>(); + authChallenges.add(getAuthChallengeDto("OTP")); + authChallenges.add(getAuthChallengeDto("BIO")); + authRequest.setChallengeList(authChallenges); + + AuthResponseV2 authResponseV2 = authorizationServiceImpl.authenticateUserV2(authRequest); + Assert.assertNotNull(authResponseV2); + Assert.assertEquals(transactionId, authResponseV2.getTransactionId()); + //Assert.assertEquals(consentAction,authResponseV2.getConsentAction()); + } + + @Test + public void authenticateV2_multipleRegisteredAcrsWithInvalidMultiFactor_thenFail() throws EsignetException { + String transactionId = "test-transaction"; + when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(createIdpTransaction( + new String[]{"mosip:idp:acr:biometrics-generated-code", "mosip:idp:acr:linked-wallet"})); + + List> allAuthFactors=new ArrayList<>(); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:biometrics-generated-code")); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:linked-wallet")); + when(authenticationContextClassRefUtil.getAuthFactors(new String[]{"mosip:idp:acr:biometrics-generated-code", + "mosip:idp:acr:linked-wallet"})).thenReturn(allAuthFactors); + + AuthRequest authRequest = new AuthRequest(); + authRequest.setTransactionId(transactionId); + authRequest.setIndividualId("23423434234"); + List authChallenges = new ArrayList<>(); + authChallenges.add(getAuthChallengeDto("OTP")); + authChallenges.add(getAuthChallengeDto("PIN")); + authRequest.setChallengeList(authChallenges); + + try { + authorizationServiceImpl.authenticateUserV2(authRequest); + Assert.fail(); + } catch (EsignetException ex) { + Assert.assertTrue(ex.getErrorCode().equals(ErrorConstants.AUTH_FACTOR_MISMATCH)); + } + } @Test public void getAuthCode_withValidInput_thenPass() { diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java new file mode 100644 index 000000000..615352753 --- /dev/null +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/ConsentHelperServiceTest.java @@ -0,0 +1,221 @@ +/* + * 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.services; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.dto.ClaimDetail; +import io.mosip.esignet.api.dto.Claims; +import io.mosip.esignet.api.util.ConsentAction; +import io.mosip.esignet.core.dto.ConsentDetail; +import io.mosip.esignet.core.dto.OIDCTransaction; +import io.mosip.esignet.core.dto.UserConsentRequest; +import io.mosip.esignet.core.spi.ConsentService; +import io.mosip.esignet.core.util.KafkaHelperService; +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.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + + +@RunWith(MockitoJUnitRunner.class) +public class ConsentHelperServiceTest { + + + @Mock + ConsentService consentService; + + @Mock + KafkaHelperService kafkaHelperService; + + @Mock + PasswordEncoder passwordEncoder; + + @InjectMocks + ConsentHelperService consentHelperService; + + @Autowired + ObjectMapper objectMapper; + + + @Test + public void addUserConsent_withValidLinkedTransaction_thenPass() + { + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setAuthTransactionId("123"); + oidcTransaction.setAcceptedClaims(List.of("name","email")); + oidcTransaction.setPermittedScopes(null); + oidcTransaction.setConsentAction(ConsentAction.CAPTURE); + + Claims claims = new Claims(); + Map userinfo = new HashMap<>(); + Map id_token = new HashMap<>(); + ClaimDetail userinfoNameClaimDetail = new ClaimDetail("name", new String[]{"value1a", "value1b"}, true); + ClaimDetail idTokenClaimDetail = new ClaimDetail("token", new String[]{"value2a", "value2b"}, false); + userinfo.put("name", userinfoNameClaimDetail); + userinfo.put("email",null); + id_token.put("idTokenKey", idTokenClaimDetail); + claims.setUserinfo(userinfo); + claims.setId_token(id_token); + + oidcTransaction.setRequestedClaims(claims); + consentHelperService.addUserConsent(oidcTransaction, true, null); + + } + + @Test + public void addUserConsent_withValidWebTransaction_thenPass() + { + OIDCTransaction oidcTransaction = new OIDCTransaction(); + oidcTransaction.setAuthTransactionId("123"); + oidcTransaction.setAcceptedClaims(List.of("name","email")); + oidcTransaction.setPermittedScopes(null); + oidcTransaction.setConsentAction(ConsentAction.CAPTURE); + + Claims claims = new Claims(); + Map userinfo = new HashMap<>(); + Map id_token = new HashMap<>(); + ClaimDetail userinfoClaimDetail = new ClaimDetail("value1", new String[]{"value1a", "value1b"}, true); + ClaimDetail idTokenClaimDetail = new ClaimDetail("value2", new String[]{"value2a", "value2b"}, false); + userinfo.put("userinfoKey", userinfoClaimDetail); + id_token.put("idTokenKey", idTokenClaimDetail); + claims.setUserinfo(userinfo); + claims.setId_token(id_token); + + oidcTransaction.setRequestedClaims(claims); + + Mockito.when(consentService.saveUserConsent(Mockito.any())).thenReturn(new ConsentDetail()); + + consentHelperService.addUserConsent(oidcTransaction, false, ""); + } + + @Test + public void processConsent_withValidConsentAndConsentActionAsNoCapture_thenPass() throws JsonProcessingException { + + OIDCTransaction oidcTransaction=new OIDCTransaction(); + oidcTransaction.setClientId("abc"); + oidcTransaction.setPartnerSpecificUserToken("123"); + oidcTransaction.setRequestedAuthorizeScopes(List.of("openid","profile")); + oidcTransaction.setPermittedScopes(List.of("openid","profile")); + + Claims claims = new Claims(); + Map userinfo = new HashMap<>(); + Map id_token = new HashMap<>(); + ClaimDetail userinfoNameClaimDetail = new ClaimDetail("name", new String[]{"value1a", "value1b"}, true); + ClaimDetail idTokenClaimDetail = new ClaimDetail("token", new String[]{"value2a", "value2b"}, false); + userinfo.put("name", userinfoNameClaimDetail); + userinfo.put("email",null); + id_token.put("idTokenKey", idTokenClaimDetail); + claims.setUserinfo(userinfo); + claims.setId_token(id_token); + + oidcTransaction.setRequestedClaims(claims); + + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId(oidcTransaction.getClientId()); + userConsentRequest.setPsuToken(oidcTransaction.getPartnerSpecificUserToken()); + + ConsentDetail consentDetail = new ConsentDetail(); + consentDetail.setClientId("123"); + consentDetail.setSignature("signature"); + consentDetail.setAuthorizationScopes(Map.of("openid",true,"profile",true)); + consentDetail.setClaims(claims); + Claims normalizedClaims = new Claims(); + normalizedClaims.setUserinfo(consentHelperService.normalizeClaims(claims.getUserinfo())); + normalizedClaims.setId_token(consentHelperService.normalizeClaims(claims.getId_token())); + String hashCode =consentHelperService.hashUserConsent(normalizedClaims,consentDetail.getAuthorizationScopes()); + consentDetail.setHash(hashCode); + + Mockito.when(consentService.getUserConsent(userConsentRequest)).thenReturn(Optional.of(consentDetail)); + + consentHelperService.processConsent(oidcTransaction,true); + + Assert.assertEquals(oidcTransaction.getConsentAction(),ConsentAction.NOCAPTURE); + Assert.assertEquals(oidcTransaction.getAcceptedClaims(),consentDetail.getAcceptedClaims()); + Assert.assertEquals(oidcTransaction.getPermittedScopes(),consentDetail.getPermittedScopes()); + } + + @Test + public void processConsent_withValidConsentAndConsentActionAsCapture_thenPass() throws JsonProcessingException { + + OIDCTransaction oidcTransaction=new OIDCTransaction(); + oidcTransaction.setClientId("abc"); + oidcTransaction.setPartnerSpecificUserToken("123"); + oidcTransaction.setRequestedAuthorizeScopes(List.of("openid","profile")); + oidcTransaction.setPermittedScopes(List.of("openid","profile")); + + Claims claims = new Claims(); + Map userinfo = new HashMap<>(); + Map id_token = new HashMap<>(); + ClaimDetail userinfoNameClaimDetail = new ClaimDetail("name", new String[]{"value1a", "value1b"}, true); + ClaimDetail idTokenClaimDetail = new ClaimDetail("token", new String[]{"value2a", "value2b"}, false); + userinfo.put("name", userinfoNameClaimDetail); + userinfo.put("email",null); + id_token.put("idTokenKey", idTokenClaimDetail); + claims.setUserinfo(userinfo); + claims.setId_token(id_token); + + oidcTransaction.setRequestedClaims(claims); + + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId(oidcTransaction.getClientId()); + userConsentRequest.setPsuToken(oidcTransaction.getPartnerSpecificUserToken()); + + ConsentDetail consentDetail = new ConsentDetail(); + consentDetail.setClientId("123"); + consentDetail.setSignature("signature"); + consentDetail.setAuthorizationScopes(Map.of("openid",true,"profile",true)); + + Claims consentClaims = new Claims(); + userinfo = new HashMap<>(); + id_token = new HashMap<>(); + userinfoNameClaimDetail = new ClaimDetail("gender", new String[]{"value1a", "value1b"}, false); + idTokenClaimDetail = new ClaimDetail("token", new String[]{"value1a", "value2b"}, false); + userinfo.put("gender", userinfoNameClaimDetail); + userinfo.put("email",null); + id_token.put("idTokenKey", idTokenClaimDetail); + consentClaims.setUserinfo(userinfo); + consentClaims.setId_token(id_token); + + consentDetail.setClaims(consentClaims); + String hashCode =consentHelperService.hashUserConsent(consentClaims,consentDetail.getAuthorizationScopes()); + consentDetail.setHash(hashCode); + + Mockito.when(consentService.getUserConsent(userConsentRequest)).thenReturn(Optional.of(consentDetail)); + consentHelperService.processConsent(oidcTransaction,true); + + Assert.assertEquals(oidcTransaction.getConsentAction(),ConsentAction.CAPTURE); + + } + + @Test + public void processConsent_withEmptyConsent_thenPass(){ + + OIDCTransaction oidcTransaction=new OIDCTransaction(); + oidcTransaction.setClientId("abc"); + oidcTransaction.setPartnerSpecificUserToken("123"); + + UserConsentRequest userConsentRequest = new UserConsentRequest(); + userConsentRequest.setClientId(oidcTransaction.getClientId()); + userConsentRequest.setPsuToken(oidcTransaction.getPartnerSpecificUserToken()); + + Mockito.when(consentService.getUserConsent(userConsentRequest)).thenReturn(Optional.empty()); + + consentHelperService.processConsent(oidcTransaction,true); + Assert.assertEquals(oidcTransaction.getConsentAction(),ConsentAction.CAPTURE); + + } +} \ No newline at end of file diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java index 58737ce1f..514745f64 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/LinkedAuthorizationServiceTest.java @@ -13,8 +13,8 @@ import io.mosip.esignet.api.spi.Authenticator; import io.mosip.esignet.api.util.ConsentAction; import io.mosip.esignet.core.constants.ErrorConstants; -import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.dto.Error; +import io.mosip.esignet.core.dto.*; import io.mosip.esignet.core.exception.DuplicateLinkCodeException; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.exception.InvalidTransactionException; @@ -398,6 +398,28 @@ public void saveConsent_withInvalidTransaction_thenFail() { } } + @Test + public void saveConsentV2_withValidInput_thenPass() { + Mockito.when(cacheUtilService.getLinkedAuthTransaction("link-transaction-id")).thenReturn(new OIDCTransaction()); + LinkedConsentRequestV2 linkedConsentRequestV2 = new LinkedConsentRequestV2(); + linkedConsentRequestV2.setLinkedTransactionId("link-transaction-id"); + LinkedConsentResponse linkedConsentResponse = linkedAuthorizationService.saveConsentV2(linkedConsentRequestV2); + Assert.assertNotNull(linkedConsentResponse); + Assert.assertEquals(linkedConsentRequestV2.getLinkedTransactionId(), linkedConsentResponse.getLinkedTransactionId()); + } + + @Test + public void saveConsentV2_withInvalidTransaction_thenFail() { + LinkedConsentRequestV2 linkedConsentRequestV2 = new LinkedConsentRequestV2(); + linkedConsentRequestV2.setLinkedTransactionId("link-transaction-id"); + try { + linkedAuthorizationService.saveConsentV2(linkedConsentRequestV2); + Assert.fail(); + } catch (InvalidTransactionException ex) { + Assert.assertEquals(ErrorConstants.INVALID_TRANSACTION, ex.getErrorCode()); + } + } + @Test public void linkStatus_withValidInput_thenPass() { LinkStatusRequest linkStatusRequest = new LinkStatusRequest(); From c88f65a7e128a2b21bdc5e2a5d39ef2a23300bd7 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Tue, 27 Jun 2023 12:04:55 +0530 Subject: [PATCH 12/13] [CHORES] Bumped version from 1.0.0 to 1.1.0 --- binding-service-impl/pom.xml | 2 +- client-management-service-impl/pom.xml | 2 +- consent-service-impl/pom.xml | 2 +- esignet-core/pom.xml | 2 +- esignet-integration-api/pom.xml | 4 ++-- esignet-service/pom.xml | 4 ++-- oidc-service-impl/pom.xml | 2 +- .../io/mosip/esignet/services/ConsentHelperService.java | 6 +++--- pom.xml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/binding-service-impl/pom.xml b/binding-service-impl/pom.xml index 557018e0b..6791fb508 100644 --- a/binding-service-impl/pom.xml +++ b/binding-service-impl/pom.xml @@ -8,7 +8,7 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT io.mosip.esignet diff --git a/client-management-service-impl/pom.xml b/client-management-service-impl/pom.xml index 99a0449a8..3d4810278 100644 --- a/client-management-service-impl/pom.xml +++ b/client-management-service-impl/pom.xml @@ -6,7 +6,7 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT io.mosip.esignet diff --git a/consent-service-impl/pom.xml b/consent-service-impl/pom.xml index 915f9405b..60ba82662 100644 --- a/consent-service-impl/pom.xml +++ b/consent-service-impl/pom.xml @@ -9,7 +9,7 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT consent-service-impl diff --git a/esignet-core/pom.xml b/esignet-core/pom.xml index bf99f9f3c..413ee5534 100644 --- a/esignet-core/pom.xml +++ b/esignet-core/pom.xml @@ -9,7 +9,7 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT io.mosip.esignet diff --git a/esignet-integration-api/pom.xml b/esignet-integration-api/pom.xml index 15d783be9..30a9104ec 100644 --- a/esignet-integration-api/pom.xml +++ b/esignet-integration-api/pom.xml @@ -6,12 +6,12 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT io.mosip.esignet esignet-integration-api - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT esignet-integration-api e-Signet integration Library diff --git a/esignet-service/pom.xml b/esignet-service/pom.xml index 44fe448c9..e0c1744b4 100644 --- a/esignet-service/pom.xml +++ b/esignet-service/pom.xml @@ -8,12 +8,12 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT io.mosip.esignet esignet-service - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT esignet-service e-Signet OIDC Service diff --git a/oidc-service-impl/pom.xml b/oidc-service-impl/pom.xml index d7d617e58..38ae7f778 100644 --- a/oidc-service-impl/pom.xml +++ b/oidc-service-impl/pom.xml @@ -6,7 +6,7 @@ io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT io.mosip.esignet diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java index 7130f360d..75813cada 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/ConsentHelperService.java @@ -43,9 +43,9 @@ public void processConsent(OIDCTransaction transaction, boolean linked) { transaction.setConsentAction(consentAction); - if(consentAction.equals(ConsentAction.NOCAPTURE)) { //NOSONAR consent is already evaluated to be not null - transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); - transaction.setPermittedScopes(consent.get().getPermittedScopes()); + if(consentAction.equals(ConsentAction.NOCAPTURE)) { + transaction.setAcceptedClaims(consent.get().getAcceptedClaims()); //NOSONAR consent is already evaluated to be not null + transaction.setPermittedScopes(consent.get().getPermittedScopes()); //NOSONAR consent is already evaluated to be not null } } diff --git a/pom.xml b/pom.xml index 4143f9f5a..0c82f97e1 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ 4.0.0 io.mosip.esignet esignet-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT pom esignet Parent project of MOSIP e-Signet From 5d10b1e685091bd7b503c99ef00b786fb56188c4 Mon Sep 17 00:00:00 2001 From: Hitesh Jain Date: Tue, 27 Jun 2023 17:44:03 +0530 Subject: [PATCH 13/13] github actions cleanup --- .github/workflows/codeql-analysis.yml | 1 - .github/workflows/push_trigger.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 39d8753b3..26d6e922d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -18,7 +18,6 @@ on: - develop - master - 1.* - - feature-ES-3 pull_request: # # The branches below must be a subset of the branches above branches: diff --git a/.github/workflows/push_trigger.yml b/.github/workflows/push_trigger.yml index e034c3bca..f5038f38f 100644 --- a/.github/workflows/push_trigger.yml +++ b/.github/workflows/push_trigger.yml @@ -10,7 +10,6 @@ on: - 1.* - develop - main - - feature-ES-3 jobs: call-workflow-codeql-analysis: