feature/added attemptCounter field to MappedChallengeProvider table

This commit is contained in:
hongwei 2022-05-04 12:06:26 +02:00
parent f27497785f
commit 4cc824d059
7 changed files with 35 additions and 29 deletions

View File

@ -525,6 +525,7 @@ object ErrorMessages {
val InvalidChallengeType = "OBP-40015: Invalid Challenge Type. Please specify a valid value for CHALLENGE_TYPE, when you create the transaction request."
val InvalidChallengeAnswer = "OBP-40016: Invalid Challenge Answer. Please specify a valid value for answer in Json body. " +
"The challenge answer may be expired." +
"Or you've used up your allowed attempts (3 times)." +
"Or if connector = mapped and transactionRequestType_OTP_INSTRUCTION_TRANSPORT = DUMMY and suggested_default_sca_method=DUMMY, the answer must be `123`. " +
"Or if connector = others, the challenge answer can be got by phone message or other security ways."
val InvalidPhoneNumber = "OBP-40017: Invalid Phone Number. Please specify a valid value for PHONE_NUMBER. Eg:+9722398746 "

View File

@ -637,11 +637,6 @@ trait APIMethods210 {
existingTransactionRequest.challenge.id.equals(challengeAnswerJson.id)
}
//Check the allowed attempts, Note: not support yet, the default value is 3
_ <- Helper.booleanToFuture(s"${AllowedAttemptsUsedUp}", cc=callContext) {
existingTransactionRequest.challenge.allowed_attempts > 0
}
//Check the challenge type, Note: not support yet, the default value is SANDBOX_TAN
_ <- Helper.booleanToFuture(s"${InvalidChallengeType} ", cc=callContext) {
existingTransactionRequest.challenge.challenge_type == TransactionChallengeTypes.OTP_VIA_API.toString

View File

@ -1363,11 +1363,6 @@ trait APIMethods400 {
existingTransactionRequestType.equals(transactionRequestType.value)
}
//Check the allowed attempts, Note: not supported yet, the default value is 3
_ <- Helper.booleanToFuture(s"${AllowedAttemptsUsedUp}", cc=callContext) {
existingTransactionRequest.challenge.allowed_attempts > 0
}
//Check the challenge type, Note: not supported yet, the default value is SANDBOX_TAN
_ <- Helper.booleanToFuture(s"${InvalidChallengeType} ", cc=callContext) {
List(

View File

@ -58,32 +58,40 @@ object MappedChallengeProvider extends ChallengeProvider {
): 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 createDate = challenge.createdAt.get
val tokenDuration : Long = Helpers.seconds(APIUtil.otpExpirationSeconds)
val expiredDateTime: Long = createDate.getTime+tokenDuration
val currentTime: Long = Platform.currentTime
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}")
}
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 $otpExpirationSeconds seconds")
}
}else{
Failure(s"${ErrorMessages.OneTimePasswordExpired} Current expiration time is $otpExpirationSeconds seconds")
}else{
Failure(s"${ErrorMessages.AllowedAttemptsUsedUp}")
}
}
}

View File

@ -24,6 +24,9 @@ class MappedExpectedChallengeAnswer extends ChallengeTrait with LongKeyedMapper[
object mScaStatus extends MappedString(this,100)
object mConsentId extends MappedString(this,100)
object mAuthenticationMethodId extends MappedString(this,100)
object mAttemptCounter extends MappedInt(this){
override def defaultValue = 0
}
override def challengeId: String = mChallengeId.get
override def challengeType: String = mChallengeType.get
@ -36,6 +39,7 @@ class MappedExpectedChallengeAnswer extends ChallengeTrait with LongKeyedMapper[
override def scaMethod: Option[SCA] = Option(StrongCustomerAuthentication.withName(mScaMethod.get))
override def scaStatus: Option[SCAStatus] = Option(StrongCustomerAuthenticationStatus.withName(mScaStatus.get))
override def authenticationMethodId: Option[String] = Option(mAuthenticationMethodId.get)
override def attemptCounter: Int = mAttemptCounter.get
}
object MappedExpectedChallengeAnswer extends MappedExpectedChallengeAnswer with LongKeyedMetaMapper[MappedExpectedChallengeAnswer] {

View File

@ -532,6 +532,7 @@ case class ChallengeCommons(
override val scaMethod: Option[SCA],
override val scaStatus: Option[SCAStatus],
override val authenticationMethodId: Option[String] ,
override val attemptCounter: Int = 0
) extends ChallengeTrait
object ChallengeCommons extends Converter[ChallengeTrait, ChallengeCommons]

View File

@ -561,6 +561,8 @@ trait ChallengeTrait {
def scaMethod: Option[SCA]
def scaStatus: Option[SCAStatus]
def authenticationMethodId: Option[String]
def attemptCounter: Int
}