mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 17:17:09 +00:00
refactor/put challenge into MappedExpectedChallengeAnswer table.
This commit is contained in:
parent
725b910498
commit
435de19d4a
@ -72,6 +72,7 @@ import code.dynamicMessageDoc.{DynamicMessageDocProvider, JsonDynamicMessageDoc}
|
||||
import code.dynamicResourceDoc.{DynamicResourceDocProvider, JsonDynamicResourceDoc}
|
||||
import code.endpointMapping.{EndpointMappingProvider, EndpointMappingT}
|
||||
import code.endpointTag.EndpointTagT
|
||||
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
|
||||
import code.util.Helper.MdcLoggable
|
||||
import code.views.system.AccountAccess
|
||||
import net.liftweb.mapper.By
|
||||
@ -1154,7 +1155,7 @@ object NewStyle extends MdcLoggable{
|
||||
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
|
||||
detailsPlain: String,
|
||||
chargePolicy: String,
|
||||
challengeType: Option[String],
|
||||
challengeType: Option[TransactionChallengeTypes.Value],
|
||||
scaMethod: Option[SCA],
|
||||
reasons: Option[List[TransactionRequestReason]],
|
||||
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13],
|
||||
@ -1169,7 +1170,7 @@ object NewStyle extends MdcLoggable{
|
||||
transactionRequestCommonBody: TransactionRequestCommonBodyJSON,
|
||||
detailsPlain: String,
|
||||
chargePolicy: String,
|
||||
challengeType: Option[String],
|
||||
challengeType = challengeType.map(_.toString),
|
||||
scaMethod: Option[SCA],
|
||||
reasons: Option[List[TransactionRequestReason]],
|
||||
berlinGroupPayments: Option[SepaCreditTransfersBerlinGroupV13],
|
||||
@ -1334,6 +1335,23 @@ object NewStyle extends MdcLoggable{
|
||||
Connector.connector.vend.validateChallengeAnswer(challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]) map { i =>
|
||||
(unboxFullOrFail(i._1, callContext, s"$InvalidChallengeAnswer "), i._2)
|
||||
}
|
||||
|
||||
def allChallengesSuccessfullyAnswered(
|
||||
bankId: BankId,
|
||||
accountId: AccountId,
|
||||
transReqId: TransactionRequestId,
|
||||
challenges: List[ChallengeTrait],
|
||||
callContext: Option[CallContext]
|
||||
): OBPReturnType[Boolean] =
|
||||
Connector.connector.vend.allChallengesSuccessfullyAnswered(
|
||||
bankId: BankId,
|
||||
accountId: AccountId,
|
||||
transReqId: TransactionRequestId,
|
||||
challenges: List[ChallengeTrait],
|
||||
callContext: Option[CallContext]
|
||||
) map { i =>
|
||||
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponse"), i._2)
|
||||
}
|
||||
|
||||
def validateAndCheckIbanNumber(iban: String, callContext: Option[CallContext]): OBPReturnType[IbanChecker] =
|
||||
Connector.connector.vend.validateAndCheckIbanNumber(iban: String, callContext: Option[CallContext]) map { i =>
|
||||
|
||||
@ -1035,7 +1035,7 @@ trait APIMethods400 {
|
||||
transactionRequestBodyRefundJson.copy(description = newDescription),
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OTP_VIA_API.toString),
|
||||
Some(OTP_VIA_API),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
@ -1091,7 +1091,7 @@ trait APIMethods400 {
|
||||
transactionRequestBodySandboxTan,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OTP_VIA_API.toString),
|
||||
Some(OTP_VIA_API),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
@ -1120,7 +1120,7 @@ trait APIMethods400 {
|
||||
transactionRequestBodySandboxTan,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OTP_VIA_WEB_FORM.toString),
|
||||
Some(OTP_VIA_WEB_FORM),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
@ -1155,7 +1155,7 @@ trait APIMethods400 {
|
||||
transactionRequestBodyCounterparty,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OTP_VIA_API.toString),
|
||||
Some(OTP_VIA_API),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
@ -1207,7 +1207,7 @@ trait APIMethods400 {
|
||||
transactionRequestBodySimple,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OTP_VIA_API.toString),
|
||||
Some(OTP_VIA_API),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
@ -1242,7 +1242,7 @@ trait APIMethods400 {
|
||||
transDetailsSEPAJson,
|
||||
transDetailsSerialized,
|
||||
chargePolicy,
|
||||
Some(OTP_VIA_API.toString),
|
||||
Some(OTP_VIA_API),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
transDetailsSEPAJson.reasons.map(_.map(_.transform)),
|
||||
None,
|
||||
@ -1267,7 +1267,7 @@ trait APIMethods400 {
|
||||
transactionRequestBodyFreeForm,
|
||||
transDetailsSerialized,
|
||||
sharedChargePolicy.toString,
|
||||
Some(OTP_VIA_API.toString),
|
||||
Some(OTP_VIA_API),
|
||||
getScaMethodAtInstance(transactionRequestType.value).toOption,
|
||||
None,
|
||||
None,
|
||||
@ -1276,31 +1276,8 @@ trait APIMethods400 {
|
||||
(createdTransactionRequest, callContext)
|
||||
}
|
||||
}
|
||||
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(createdTransactionRequest.id.value, callContext)
|
||||
} yield {
|
||||
//TODO, remove this `connector` guard logic, the challenges should come from other places.
|
||||
// The OBP mapped V400 payment.challenges are not done yet, the we should use `createChallengesC2` instead of `createChallenges` in createTransactionRequestv400 method,
|
||||
// and get the challenges from connector level, not prepare them here.
|
||||
val challenges : List[ChallengeJson] = if(APIUtil.getPropsValue("connector").openOrThrowException(attemptedToOpenAnEmptyBox).toString.equalsIgnoreCase("mapped")){
|
||||
MappedExpectedChallengeAnswer
|
||||
.findAll(By(MappedExpectedChallengeAnswer.mTransactionRequestId, createdTransactionRequest.id.value))
|
||||
.map(mappedExpectedChallengeAnswer =>
|
||||
ChallengeJson(
|
||||
mappedExpectedChallengeAnswer.challengeId,
|
||||
mappedExpectedChallengeAnswer.transactionRequestId,
|
||||
mappedExpectedChallengeAnswer.expectedUserId,
|
||||
mappedExpectedChallengeAnswer.attemptCounter
|
||||
))
|
||||
} else {
|
||||
if(!("COMPLETED").equals(createdTransactionRequest.status))
|
||||
List(ChallengeJson(
|
||||
createdTransactionRequest.challenge.id,
|
||||
createdTransactionRequest.id.value,
|
||||
u.userId,
|
||||
createdTransactionRequest.challenge.allowed_attempts
|
||||
))
|
||||
else
|
||||
null
|
||||
}
|
||||
(JSONFactory400.createTransactionRequestWithChargeJSON(createdTransactionRequest, challenges), HttpCode.`201`(callContext))
|
||||
}
|
||||
}
|
||||
@ -1415,7 +1392,9 @@ trait APIMethods400 {
|
||||
OTP_VIA_WEB_FORM.toString
|
||||
).exists(_ == existingTransactionRequest.challenge.challenge_type)
|
||||
}
|
||||
|
||||
|
||||
(challenges, callContext) <- NewStyle.function.getChallengesByTransactionRequestId(transReqId.value, callContext)
|
||||
|
||||
(transactionRequest, callContext) <- challengeAnswerJson.answer match {
|
||||
// If the challenge answer is `REJECT` - Currently only to Reject a SEPA transaction request REFUND
|
||||
case "REJECT" =>
|
||||
@ -1467,47 +1446,17 @@ trait APIMethods400 {
|
||||
} yield (transactionRequest, callContext)
|
||||
case _ =>
|
||||
for {
|
||||
// Check the challengeId is valid for this existingTransactionRequest
|
||||
_ <- Helper.booleanToFuture(s"${InvalidTransactionRequestChallengeId}", cc=callContext) {
|
||||
if (APIUtil.isDataFromOBPSide("validateChallengeAnswer")) {
|
||||
MappedExpectedChallengeAnswer
|
||||
.findAll(By(MappedExpectedChallengeAnswer.mTransactionRequestId, transReqId.value))
|
||||
.exists(_.challengeId == challengeAnswerJson.id)
|
||||
}else{
|
||||
existingTransactionRequest.challenge.id.equals(challengeAnswerJson.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
(challengeAnswerIsValidated, callContext) <- NewStyle.function.validateChallengeAnswer(challengeAnswerJson.id, challengeAnswerJson.answer, callContext)
|
||||
|
||||
_ <- Helper.booleanToFuture(s"${InvalidChallengeAnswer.replace("answer may be expired.",s"answer may be expired, current expiration time is ${transactionRequestChallengeTtl} seconds .")} ", cc=callContext) {
|
||||
challengeAnswerIsValidated
|
||||
}
|
||||
|
||||
|
||||
//TODO, this is a temporary solution, we only checked single challenge Id for remote connectors. here is only for the localMapped Connector logic
|
||||
_ <- if (APIUtil.isDataFromOBPSide("validateChallengeAnswer")){
|
||||
for{
|
||||
accountAttributes <- Connector.connector.vend.getAccountAttributesByAccount(bankId, accountId, None)
|
||||
_ <- Helper.booleanToFuture(s"$NextChallengePending", cc=callContext) {
|
||||
val quorum = accountAttributes._1.toList.flatten.find(_.name == "REQUIRED_CHALLENGE_ANSWERS").map(_.value).getOrElse("1").toInt
|
||||
MappedExpectedChallengeAnswer
|
||||
.findAll(By(MappedExpectedChallengeAnswer.mTransactionRequestId, transReqId.value))
|
||||
.count(_.successful == true) match {
|
||||
case number if number >= quorum => true
|
||||
case _ =>
|
||||
MappedTransactionRequestProvider.saveTransactionRequestStatusImpl(transReqId, TransactionRequestStatus.NEXT_CHALLENGE_PENDING.toString)
|
||||
false
|
||||
}
|
||||
}
|
||||
} yield {
|
||||
true
|
||||
}
|
||||
} else{
|
||||
Future{true}
|
||||
(challengeAnswerIsValidated, callContext) <- NewStyle.function.allChallengesSuccessfullyAnswered(bankId, accountId, transReqId, challenges, callContext)
|
||||
_ <- Helper.booleanToFuture(s"$NextChallengePending", cc=callContext) {
|
||||
challengeAnswerIsValidated
|
||||
}
|
||||
|
||||
// All Good, proceed with the Transaction creation...
|
||||
(transactionRequest, callContext) <- TransactionRequestTypes.withName(transactionRequestType.value) match {
|
||||
case TRANSFER_TO_PHONE | TRANSFER_TO_ATM | TRANSFER_TO_ACCOUNT =>
|
||||
NewStyle.function.createTransactionAfterChallengeV300(u, fromAccount, transReqId, transactionRequestType, callContext)
|
||||
@ -1518,7 +1467,7 @@ trait APIMethods400 {
|
||||
}
|
||||
} yield {
|
||||
|
||||
(JSONFactory210.createTransactionRequestWithChargeJSON(transactionRequest), HttpCode.`202`(callContext))
|
||||
(JSONFactory400.createTransactionRequestWithChargeJSON(transactionRequest, challenges), HttpCode.`202`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1186,7 +1186,7 @@ object JSONFactory400 {
|
||||
account_attributes = accountAttributes.map(createAccountAttributeJson)
|
||||
)
|
||||
|
||||
def createTransactionRequestWithChargeJSON(tr : TransactionRequest, challenges: List[ChallengeJson]) : TransactionRequestWithChargeJSON400 = {
|
||||
def createTransactionRequestWithChargeJSON(tr : TransactionRequest, challenges: List[ChallengeTrait]) : TransactionRequestWithChargeJSON400 = {
|
||||
new TransactionRequestWithChargeJSON400(
|
||||
id = stringOrNull(tr.id.value),
|
||||
`type` = stringOrNull(tr.`type`),
|
||||
@ -1202,6 +1202,7 @@ object JSONFactory400 {
|
||||
// Some (mapped) data might not have the challenge. TODO Make this nicer
|
||||
challenges = {
|
||||
try {
|
||||
challenges.map(challenge =>{
|
||||
val otpViaWebFormPath = Constant.HostName + List(
|
||||
"/otp?flow=transaction_request&bankId=",
|
||||
stringOrNull(tr.from.bank_id),
|
||||
@ -1213,7 +1214,7 @@ object JSONFactory400 {
|
||||
"&transactionRequestId=",
|
||||
stringOrNull(tr.id.value),
|
||||
"&id=",
|
||||
stringOrNull(tr.challenge.id)
|
||||
stringOrNull(challenge.challengeId)
|
||||
).mkString("")
|
||||
|
||||
val otpViaApiPath = Constant.HostName + List(
|
||||
@ -1227,14 +1228,20 @@ object JSONFactory400 {
|
||||
"/transaction-requests/",
|
||||
stringOrNull(tr.id.value),
|
||||
"/challenge").mkString("")
|
||||
val link = tr.challenge.challenge_type match {
|
||||
val link = challenge.challengeType match {
|
||||
case challengeType if challengeType == TransactionChallengeTypes.OTP_VIA_WEB_FORM.toString => otpViaWebFormPath
|
||||
case challengeType if challengeType == TransactionChallengeTypes.OTP_VIA_API.toString => otpViaApiPath
|
||||
case _ => ""
|
||||
}
|
||||
challenges.map(
|
||||
e => ChallengeJsonV400(id = stringOrNull(e.challenge_id), user_id = e.expected_user_id, allowed_attempts = e.allowed_attempts, challenge_type = stringOrNull(tr.challenge.challenge_type), link = link)
|
||||
)
|
||||
}
|
||||
ChallengeJsonV400(
|
||||
id = stringOrNull(challenge.challengeId),
|
||||
user_id = challenge.expectedUserId,
|
||||
allowed_attempts = 3, //TODO, this should be fixed later, need to add a field in the MappedExpectedChallengeAnswer table
|
||||
challenge_type = stringOrNull(challenge.challengeType),
|
||||
link = link
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
// catch { case _ : Throwable => ChallengeJSON (id = "", allowed_attempts = 0, challenge_type = "")}
|
||||
catch { case _ : Throwable => null}
|
||||
|
||||
@ -400,6 +400,14 @@ trait Connector extends MdcLoggable {
|
||||
// Validates an answer for a challenge and returns if the answer is correct or not
|
||||
def validateChallengeAnswer(challengeId: String, hashOfSuppliedAnswer: String, callContext: Option[CallContext]): OBPReturnType[Box[Boolean]] = Future{(Full(true), callContext)}
|
||||
|
||||
def allChallengesSuccessfullyAnswered(
|
||||
bankId: BankId,
|
||||
accountId: AccountId,
|
||||
transReqId: TransactionRequestId,
|
||||
challenges: List[ChallengeTrait],
|
||||
callContext: Option[CallContext]
|
||||
): OBPReturnType[Box[Boolean]]= Future{(Full(true), callContext)}
|
||||
|
||||
def validateChallengeAnswerC2(
|
||||
transactionRequestId: Option[String],
|
||||
consentId: Option[String],
|
||||
|
||||
@ -385,6 +385,27 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
(Full(Challenges.ChallengeProvider.vend.validateChallenge(challengeId, hashOfSuppliedAnswer, userId).isDefined), callContext)
|
||||
}
|
||||
|
||||
override def allChallengesSuccessfullyAnswered(
|
||||
bankId: BankId,
|
||||
accountId: AccountId,
|
||||
transReqId: TransactionRequestId,
|
||||
challenges: List[ChallengeTrait],
|
||||
callContext: Option[CallContext]
|
||||
): OBPReturnType[Box[Boolean]] = {
|
||||
for {
|
||||
(accountAttributes, callContext) <- Connector.connector.vend.getAccountAttributesByAccount(bankId, accountId, callContext)
|
||||
quorum = accountAttributes.toList.flatten.find(_.name == "REQUIRED_CHALLENGE_ANSWERS").map(_.value).getOrElse("1").toInt
|
||||
challengeSuccess = challenges.count(_.successful == true) match {
|
||||
case number if number >= quorum => true
|
||||
case _ =>
|
||||
MappedTransactionRequestProvider.saveTransactionRequestStatusImpl(transReqId, TransactionRequestStatus.NEXT_CHALLENGE_PENDING.toString)
|
||||
false
|
||||
}
|
||||
} yield {
|
||||
(Full(challengeSuccess), callContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override def getChargeLevel(bankId: BankId,
|
||||
accountId: AccountId,
|
||||
@ -4898,19 +4919,22 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
users <- getUsersForChallenges(fromAccount.bankId, fromAccount.accountId)
|
||||
//now we support multiple challenges. We can support multiple people to answer the challenges.
|
||||
//So here we return the challengeIds.
|
||||
(challengeIds, callContext) <- Connector.connector.vend.createChallenges(
|
||||
fromAccount.bankId,
|
||||
fromAccount.accountId,
|
||||
users.toList.flatten.map(_.userId),
|
||||
transactionRequestType: TransactionRequestType,
|
||||
transactionRequest.id.value,
|
||||
scaMethod,
|
||||
callContext
|
||||
) map { i =>
|
||||
(challenges, callContext) <- Connector.connector.vend.createChallengesC2(
|
||||
userIds = users.toList.flatten.map(_.userId),
|
||||
challengeType = ChallengeType.OBP_PAYMENT,//TODO, here just hard code, it is TransactionChallengeTypes.Value in createTransactionRequestv400 method
|
||||
transactionRequestId = Some(transactionRequest.id.value),
|
||||
scaMethod = scaMethod,
|
||||
scaStatus = None, //Only use for BerlinGroup Now
|
||||
consentId = None, // Note: consentId and transactionRequestId are exclusive here.
|
||||
authenticationMethodId = None,
|
||||
callContext = callContext
|
||||
) map { i =>
|
||||
(unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponseForCreateChallenge ", 400), i._2)
|
||||
}
|
||||
//TODO, this challengeIds are only for mapped connector now. we only return the first challengeId in the request yet.
|
||||
newChallenge = TransactionRequestChallenge(challengeIds.headOption.getOrElse(""), allowed_attempts = 3, challenge_type = challengeType.getOrElse(TransactionChallengeTypes.OTP_VIA_API.toString))
|
||||
|
||||
//NOTE:this is only for Backward compatibility, now we use the MappedExpectedChallengeAnswer tables instead of the single field in TransactionRequest.
|
||||
//Here only put the dummy date.
|
||||
newChallenge = TransactionRequestChallenge(s"challenges number:${challenges.length}", allowed_attempts = 3, challenge_type = TransactionChallengeTypes.OTP_VIA_API.toString)
|
||||
_ <- Future(saveTransactionRequestChallenge(transactionRequest.id, newChallenge))
|
||||
transactionRequest <- Future(transactionRequest.copy(challenge = newChallenge))
|
||||
} yield {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package code.bankconnectors.akka
|
||||
|
||||
import java.util.Date
|
||||
|
||||
import akka.pattern.ask
|
||||
import code.actorsystem.ObpLookupSystem
|
||||
import code.api.ResourceDocs1_4_0.MessageDocsSwaggerDefinitions
|
||||
@ -12,6 +11,7 @@ import code.api.util.ExampleValue._
|
||||
import code.api.util._
|
||||
import code.bankconnectors._
|
||||
import code.bankconnectors.akka.actor.{AkkaConnectorActorInit, AkkaConnectorHelperActor}
|
||||
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
import com.openbankproject.commons.dto._
|
||||
import com.openbankproject.commons.model._
|
||||
|
||||
@ -56,43 +56,42 @@ object MappedChallengeProvider extends ChallengeProvider {
|
||||
challengeAnswer: String,
|
||||
userId: Option[String]
|
||||
): Box[ChallengeTrait] = {
|
||||
|
||||
val challenge = getChallenge(challengeId).openOrThrowException(s"${ErrorMessages.InvalidChallengeAnswer}")
|
||||
val currentAttemptCounterValue = challenge.attemptCounter
|
||||
//We update the counter anyway.
|
||||
challenge.mAttemptCounter(currentAttemptCounterValue+1).saveMe()
|
||||
|
||||
val createDateTime = challenge.createdAt.get
|
||||
val challengeTTL : Long = Helpers.seconds(APIUtil.transactionRequestChallengeTtl)
|
||||
|
||||
val expiredDateTime: Long = createDateTime.getTime+challengeTTL
|
||||
val currentTime: Long = Platform.currentTime
|
||||
|
||||
//TODO, add column maxAttemptsAllowed (Int) to `mappedexpectedchallengeanswer` table instead of this hardcode number 3
|
||||
if(currentAttemptCounterValue <3){
|
||||
if(expiredDateTime > currentTime) {
|
||||
val currentHashedAnswer = BCrypt.hashpw(challengeAnswer, challenge.salt).substring(0, 44)
|
||||
val expectedHashedAnswer = challenge.expectedAnswer
|
||||
|
||||
userId match {
|
||||
case None =>
|
||||
if(currentHashedAnswer==expectedHashedAnswer) {
|
||||
tryo{challenge.mSuccessful(true).mScaStatus(StrongCustomerAuthenticationStatus.finalised.toString).saveMe()}
|
||||
} else {
|
||||
Failure(s"${ErrorMessages.InvalidChallengeAnswer}")
|
||||
}
|
||||
case Some(id) =>
|
||||
if(currentHashedAnswer==expectedHashedAnswer && id==challenge.expectedUserId) {
|
||||
tryo{challenge.mSuccessful(true).mScaStatus(StrongCustomerAuthenticationStatus.finalised.toString).saveMe()}
|
||||
} else {
|
||||
Failure(s"${ErrorMessages.InvalidChallengeAnswer}")
|
||||
}
|
||||
for{
|
||||
challenge <- getChallenge(challengeId) ?~! s"${ErrorMessages.InvalidTransactionRequestChallengeId}"
|
||||
currentAttemptCounterValue = challenge.attemptCounter
|
||||
//We update the counter anyway.
|
||||
_ = challenge.mAttemptCounter(currentAttemptCounterValue+1).saveMe()
|
||||
createDateTime = challenge.createdAt.get
|
||||
challengeTTL : Long = Helpers.seconds(APIUtil.transactionRequestChallengeTtl)
|
||||
|
||||
expiredDateTime: Long = createDateTime.getTime+challengeTTL
|
||||
currentTime: Long = Platform.currentTime
|
||||
challenge <- if(currentAttemptCounterValue <3){
|
||||
if(expiredDateTime > currentTime) {
|
||||
val currentHashedAnswer = BCrypt.hashpw(challengeAnswer, challenge.salt).substring(0, 44)
|
||||
val expectedHashedAnswer = challenge.expectedAnswer
|
||||
userId match {
|
||||
case None =>
|
||||
if(currentHashedAnswer==expectedHashedAnswer) {
|
||||
tryo{challenge.mSuccessful(true).mScaStatus(StrongCustomerAuthenticationStatus.finalised.toString).saveMe()}
|
||||
} else {
|
||||
Failure(s"${ErrorMessages.InvalidChallengeAnswer}")
|
||||
}
|
||||
case Some(id) =>
|
||||
if(currentHashedAnswer==expectedHashedAnswer && id==challenge.expectedUserId) {
|
||||
tryo{challenge.mSuccessful(true).mScaStatus(StrongCustomerAuthenticationStatus.finalised.toString).saveMe()}
|
||||
} else {
|
||||
Failure(s"${ErrorMessages.InvalidChallengeAnswer}")
|
||||
}
|
||||
}
|
||||
}else{
|
||||
Failure(s"${ErrorMessages.OneTimePasswordExpired} Current expiration time is $transactionRequestChallengeTtl seconds")
|
||||
}
|
||||
}else{
|
||||
Failure(s"${ErrorMessages.OneTimePasswordExpired} Current expiration time is $transactionRequestChallengeTtl seconds")
|
||||
Failure(s"${ErrorMessages.AllowedAttemptsUsedUp}")
|
||||
}
|
||||
}else{
|
||||
Failure(s"${ErrorMessages.AllowedAttemptsUsedUp}")
|
||||
} yield{
|
||||
challenge
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user