Skip to content

Commit

Permalink
[ES-418] Added password based auth support. (#1132)
Browse files Browse the repository at this point in the history
Signed-off-by: Mahammed Taheer <[email protected]>
  • Loading branch information
mahammedtaheer authored Nov 20, 2023
1 parent 88e95da commit 8e265d5
Show file tree
Hide file tree
Showing 35 changed files with 1,078 additions and 496 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,7 @@ public class IDAMappingConfig implements MappingConfig {
/** The dynamic attributes. */
private Map<String, List<String>> dynamicAttributes;

/** The password. */
private List<String> password;

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.mosip.authentication.common.service.helper.AuditHelper;
import io.mosip.authentication.common.service.helper.AuthTransactionHelper;
import io.mosip.authentication.common.service.helper.IdInfoHelper;
import io.mosip.authentication.common.service.impl.match.IdaIdMapping;
import io.mosip.authentication.common.service.integration.TokenIdManager;
import io.mosip.authentication.common.service.transaction.manager.IdAuthSecurityManager;
import io.mosip.authentication.common.service.util.AuthTypeUtil;
Expand All @@ -47,6 +48,7 @@
import io.mosip.authentication.core.indauth.dto.AuthStatusInfo;
import io.mosip.authentication.core.indauth.dto.IdType;
import io.mosip.authentication.core.indauth.dto.IdentityInfoDTO;
import io.mosip.authentication.core.indauth.dto.KycAuthRequestDTO;
import io.mosip.authentication.core.indauth.dto.EkycAuthRequestDTO;
import io.mosip.authentication.core.logger.IdaLogger;
import io.mosip.authentication.core.partner.dto.PartnerPolicyResponseDTO;
Expand All @@ -58,6 +60,7 @@
import io.mosip.authentication.core.spi.indauth.service.BioAuthService;
import io.mosip.authentication.core.spi.indauth.service.DemoAuthService;
import io.mosip.authentication.core.spi.indauth.service.OTPAuthService;
import io.mosip.authentication.core.spi.indauth.service.PasswordAuthService;
import io.mosip.authentication.core.spi.notification.service.NotificationService;
import io.mosip.authentication.core.spi.partner.service.PartnerService;
import io.mosip.kernel.core.logger.spi.Logger;
Expand Down Expand Up @@ -129,6 +132,9 @@ public class AuthFacadeImpl implements AuthFacade {

@Autowired
private KeyBindedTokenAuthService keyBindedTokenAuthService;

@Autowired
private PasswordAuthService passwordAuthService;

/*
* (non-Javadoc)
Expand Down Expand Up @@ -161,6 +167,14 @@ public AuthResponseDTO authenticateIndividual(AuthRequestDTO authRequestDTO, boo

addKycPolicyAttributes(filterAttributes, kycAuthRequestDTO);
}

if(authRequestDTO instanceof KycAuthRequestDTO) {
KycAuthRequestDTO kycAuthRequestDTO = (KycAuthRequestDTO) authRequestDTO;
// In case of kyc-auth request and password auth is requested
if(AuthTypeUtil.isPassword(kycAuthRequestDTO)) {
filterAttributes.add(IdaIdMapping.PASSWORD.getIdname());
}
}

Map<String, Object> idResDTO = idService.processIdType(idvIdType, idvid, idInfoHelper.isBiometricDataNeeded(authRequestDTO),
markVidConsumed, filterAttributes);
Expand Down Expand Up @@ -312,6 +326,11 @@ private List<AuthStatusInfo> processAuthType(AuthRequestDTO authRequestDTO,
authTxnBuilder, idvidHash);
}

if (!isMatchFailed(authStatusList)) {
processPasswordAuth(authRequestDTO, idInfo, token, isAuth, authStatusList, idType, authTokenId, partnerId,
authTxnBuilder, idvidHash);
}

return authStatusList;
}

Expand Down Expand Up @@ -513,5 +532,39 @@ private void processTokenAuth(AuthRequestDTO authRequestDTO, Map<String, List<Id
}
}
}

/**
*
* @param authRequestDTO
* @param token
* @param isAuth
* @param authStatusList
* @param idType
* @param authTokenId
* @param partnerId
* @param authTxnBuilder
* @param idvidHash
* @throws IdAuthenticationBusinessException
*/
private void processPasswordAuth(AuthRequestDTO authRequestDTO, Map<String, List<IdentityInfoDTO>> idInfo, String token,
boolean isAuth, List<AuthStatusInfo> authStatusList, IdType idType, String authTokenId, String partnerId,
AuthTransactionBuilder authTxnBuilder, String idvidHash) throws IdAuthenticationBusinessException {
if (AuthTypeUtil.isPassword(authRequestDTO)) {
AuthStatusInfo passwordMatchStatus = null;
try {
passwordMatchStatus = passwordAuthService.authenticate(authRequestDTO, token, idInfo, partnerId);
authStatusList.add(passwordMatchStatus);

boolean isStatus = passwordMatchStatus != null && passwordMatchStatus.isStatus();
auditHelper.audit(AuditModules.PASSWORD_AUTH, AuditEvents.PASSWORD_BASED_AUTH_REQUEST, idvidHash,
idType, "authenticateApplicant status(Password) : " + isStatus);
} finally {
boolean isStatus = passwordMatchStatus != null && passwordMatchStatus.isStatus();
logger.info(IdAuthCommonConstants.SESSION_ID, EnvUtil.getAppId(),
AUTH_FACADE, "Password Authentication status : " + isStatus);
authTxnBuilder.addRequestType(RequestType.PASSWORD_AUTH);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import javax.servlet.ServletException;

import io.mosip.authentication.core.indauth.dto.KeyBindedTokenDTO;
import io.mosip.authentication.core.indauth.dto.KycAuthRequestDTO;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
Expand Down Expand Up @@ -843,6 +845,7 @@ protected void checkAllowedAuthTypeForKeyBindedToken(Map<String, Object> request
Object value = Optional.ofNullable(requestBody.get(IdAuthCommonConstants.REQUEST))
.filter(obj -> obj instanceof Map).map(obj -> ((Map<String, Object>) obj).get(KEY_BINDED_TOKEN))
.filter(obj -> obj instanceof List).orElse(Collections.emptyMap());

List<KeyBindedTokenDTO> list = mapper.readValue(mapper.writeValueAsBytes(value),
new TypeReference<List<KeyBindedTokenDTO>>() {
});
Expand All @@ -861,6 +864,19 @@ protected void checkAllowedAuthTypeForKeyBindedToken(Map<String, Object> request
}
}

protected void checkAllowedAuthTypeForPassword(Map<String, Object> requestBody, List<AuthPolicy> authPolicies)
throws IdAuthenticationAppException, IOException {
KycAuthRequestDTO authRequestDTO = mapper.readValue(mapper.writeValueAsBytes(requestBody),
KycAuthRequestDTO.class);

if (AuthTypeUtil.isPassword(authRequestDTO) && !isAllowedAuthType(MatchType.Category.PASSWORD.getType(), authPolicies)) {
throw new IdAuthenticationAppException(
IdAuthenticationErrorConstants.AUTHTYPE_NOT_ALLOWED.getErrorCode(),
String.format(IdAuthenticationErrorConstants.AUTHTYPE_NOT_ALLOWED.getErrorMessage(),
MatchType.Category.PASSWORD.name()));
}
}

/**
* Check allowed auth type for bio.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,12 @@ private Map<String, String> getEntityInfo(Map<String, List<IdentityInfoDTO>> idE
IdAuthenticationErrorConstants.KEY_BINDING_MISSING.getErrorCode(),
String.format(IdAuthenticationErrorConstants.KEY_BINDING_MISSING.getErrorMessage(),
input.getAuthType().getType()));

case PASSWORD:
throw new IdAuthenticationBusinessException(
IdAuthenticationErrorConstants.PASSWORD_MISSING.getErrorCode(),
String.format(IdAuthenticationErrorConstants.PASSWORD_MISSING.getErrorMessage(),
input.getAuthType().getType()));
}
}
return entityInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.mosip.authentication.common.service.impl.match.IdaIdMapping;
import io.mosip.authentication.common.service.integration.MasterDataManager;
import io.mosip.authentication.common.service.integration.OTPManager;
import io.mosip.authentication.common.service.integration.PasswordComparator;
import io.mosip.authentication.common.service.util.BioMatcherUtil;
import io.mosip.authentication.common.service.util.EnvUtil;
import io.mosip.authentication.core.constant.IdAuthCommonConstants;
Expand All @@ -37,6 +38,7 @@
import io.mosip.authentication.core.indauth.dto.RequestDTO;
import io.mosip.authentication.core.spi.bioauth.CbeffDocType;
import io.mosip.authentication.core.spi.indauth.match.AuthType;
import io.mosip.authentication.core.spi.indauth.match.ComparePasswordFunction;
import io.mosip.authentication.core.spi.indauth.match.IdInfoFetcher;
import io.mosip.authentication.core.spi.indauth.match.IdMapping;
import io.mosip.authentication.core.spi.indauth.match.MappingConfig;
Expand Down Expand Up @@ -96,6 +98,9 @@ public class IdInfoFetcherImpl implements IdInfoFetcher {

@Autowired(required = false)
private KeyBindedTokenMatcherUtil keyBindedTokenMatcherUtil;

@Autowired(required = false)
private PasswordComparator passwordComparator;

/**
* Gets the demo normalizer.
Expand Down Expand Up @@ -572,4 +577,15 @@ public List<String> getUserPreferredLanguages(Map<String, List<IdentityInfoDTO>>
}
return Collections.emptyList();
}

/*
* Get Match password Function
*
* @see io.mosip.authentication.core.spi.indauth.match.IdInfoFetcher#
* getMatchPasswordFunction()
*/
@Override
public ComparePasswordFunction getMatchPasswordFunction() {
return passwordComparator::matchPasswordFunction;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package io.mosip.authentication.common.service.impl;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import io.mosip.authentication.common.service.builder.AuthStatusInfoBuilder;
import io.mosip.authentication.common.service.builder.MatchInputBuilder;
import io.mosip.authentication.common.service.config.IDAMappingConfig;
import io.mosip.authentication.common.service.helper.IdInfoHelper;
import io.mosip.authentication.common.service.impl.match.PasswordAuthType;
import io.mosip.authentication.common.service.impl.match.PasswordMatchType;
import io.mosip.authentication.core.constant.IdAuthenticationErrorConstants;
import io.mosip.authentication.core.exception.IdAuthenticationBusinessException;
import io.mosip.authentication.core.indauth.dto.AuthRequestDTO;
import io.mosip.authentication.core.indauth.dto.AuthStatusInfo;
import io.mosip.authentication.core.indauth.dto.IdentityInfoDTO;
import io.mosip.authentication.core.spi.indauth.match.MatchInput;
import io.mosip.authentication.core.spi.indauth.match.MatchOutput;
import io.mosip.authentication.core.spi.indauth.service.PasswordAuthService;
import lombok.NoArgsConstructor;

@Service
@NoArgsConstructor
public class PasswordAuthServiceImpl implements PasswordAuthService {

@Autowired
private IdInfoHelper idInfoHelper;

/** The id info helper. */
@Autowired
private MatchInputBuilder matchInputBuilder;

/** The ida mapping config. */
@Autowired
private IDAMappingConfig idaMappingConfig;

public AuthStatusInfo authenticate(AuthRequestDTO authRequestDTO,String individualId,
Map<String,List<IdentityInfoDTO>> idInfo,String partnerId)
throws IdAuthenticationBusinessException {

if (idInfo == null || idInfo.isEmpty()) {
throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.SERVER_ERROR);
}

List<MatchInput> listMatchInputs = constructMatchInput(authRequestDTO, idInfo);

List<MatchOutput> listMatchOutputs = constructMatchOutput(authRequestDTO, listMatchInputs, idInfo,
partnerId);
// Using AND condition on the match output for Bio auth.
boolean isMatched = !listMatchOutputs.isEmpty() && listMatchOutputs.stream().allMatch(MatchOutput::isMatched);
return AuthStatusInfoBuilder.buildStatusInfo(isMatched, listMatchInputs, listMatchOutputs,
PasswordAuthType.values(), idaMappingConfig);

}

public List<MatchInput> constructMatchInput(AuthRequestDTO authRequestDTO,
Map<String, List<IdentityInfoDTO>> idInfo) {
return matchInputBuilder.buildMatchInput(authRequestDTO, PasswordAuthType.values(), PasswordMatchType.values(),
idInfo);
}

private List<MatchOutput> constructMatchOutput(AuthRequestDTO authRequestDTO, List<MatchInput> listMatchInputs,
Map<String,List<IdentityInfoDTO>> idInfo, String partnerId)
throws IdAuthenticationBusinessException {
return idInfoHelper.matchIdentityData(authRequestDTO, idInfo, listMatchInputs, partnerId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,14 @@ public String getSubType() {
RIGHTIRIS, LEFTIRIS, UNKNOWN_IRIS,
FACE,UNKNOWN_FACE), "DummyType"),


KEY_BINDED_TOKENS("keyBindedTokens"){
public BiFunction<MappingConfig, MatchType, List<String>> getMappingFunction() {
return (mappingConfig, matchType) -> { return Collections.emptyList(); };
}
},

PASSWORD("password", MappingConfig::getPassword),

/** The dynamic demographics ID Mapping. */
DYNAMIC("demographics") {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.mosip.authentication.common.service.impl.match;

import io.mosip.authentication.common.service.impl.AuthTypeImpl;
import io.mosip.authentication.core.indauth.dto.AuthRequestDTO;
import io.mosip.authentication.core.indauth.dto.KycAuthRequestDTO;
import io.mosip.authentication.core.spi.indauth.match.AuthType;
import io.mosip.authentication.core.spi.indauth.match.ComparePasswordFunction;
import io.mosip.authentication.core.spi.indauth.match.IdInfoFetcher;
import io.mosip.authentication.core.spi.indauth.match.MatchType;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public enum PasswordAuthType implements AuthType {

PASSWORD(IdaIdMapping.PASSWORD.getIdname(), AuthType.setOf(PasswordMatchType.PASSWORD), "PASSWORD");

private AuthTypeImpl authTypeImpl;

/**
* Instantiates a new demo auth type.
*
* @param type the type
* @param associatedMatchTypes the associated match types
*/
private PasswordAuthType(String type, Set<MatchType> associatedMatchTypes, String displayName) {
authTypeImpl = new AuthTypeImpl(type, associatedMatchTypes, displayName);
}


@Override
public boolean isAuthTypeInfoAvailable(AuthRequestDTO authRequestDTO) {
if(authRequestDTO instanceof KycAuthRequestDTO) {
KycAuthRequestDTO kycAuthRequestDTO = (KycAuthRequestDTO) authRequestDTO;
return Objects.nonNull(kycAuthRequestDTO.getRequest().getPassword());
}
return false;
}

@Override
public Map<String, Object> getMatchProperties(AuthRequestDTO authRequestDTO, IdInfoFetcher idInfoFetcher,
String language) {
Map<String, Object> valueMap = new HashMap<>();
if(isAuthTypeInfoAvailable(authRequestDTO)) {
ComparePasswordFunction func = idInfoFetcher.getMatchPasswordFunction();
valueMap.put(IdaIdMapping.PASSWORD.getIdname(), func);
}
return valueMap;
}

@Override
public AuthType getAuthTypeImpl() {
return authTypeImpl;
}
}
Loading

0 comments on commit 8e265d5

Please sign in to comment.