Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #311: Improve detection of failed presence check #315

Merged
merged 9 commits into from
Aug 19, 2022
8 changes: 8 additions & 0 deletions docs/sql/mysql/create-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ CREATE TABLE es_onboarding_process (
activation_id VARCHAR(36),
status VARCHAR(32) NOT NULL,
error_detail VARCHAR(256),
error_origin VARCHAR(256),
error_score INTEGER NOT NULL DEFAULT 0,
timestamp_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_last_updated DATETIME,
Expand All @@ -52,6 +53,7 @@ CREATE TABLE es_onboarding_otp (
status VARCHAR(32) NOT NULL,
type VARCHAR(32) NOT NULL,
error_detail VARCHAR(256),
error_origin VARCHAR(256),
failed_attempts INTEGER,
timestamp_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_expiration DATETIME NOT NULL,
Expand All @@ -73,7 +75,9 @@ CREATE TABLE es_identity_verification (
status VARCHAR(32) NOT NULL,
phase VARCHAR(32) NOT NULL,
reject_reason TEXT,
reject_origin VARCHAR(256),
error_detail VARCHAR(256),
error_origin VARCHAR(256),
session_info TEXT,
timestamp_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_last_updated DATETIME,
Expand Down Expand Up @@ -101,7 +105,9 @@ CREATE TABLE es_document_verification (
photo_id VARCHAR(256),
verification_score INTEGER,
reject_reason TEXT,
reject_origin VARCHAR(256),
error_detail VARCHAR(256),
error_origin VARCHAR(256),
original_document_id VARCHAR(36),
used_for_verification TINYINT DEFAULT 0,
timestamp_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
Expand Down Expand Up @@ -136,8 +142,10 @@ CREATE TABLE es_document_result (
document_verification_id VARCHAR(36) NOT NULL,
phase VARCHAR(32) NOT NULL,
reject_reason TEXT,
reject_origin VARCHAR(256),
verification_result TEXT,
error_detail TEXT,
error_origin VARCHAR(256),
extracted_data TEXT,
timestamp_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (document_verification_id) REFERENCES es_document_verification (id)
Expand Down
8 changes: 8 additions & 0 deletions docs/sql/oracle/create-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ CREATE TABLE ES_ONBOARDING_PROCESS (
ACTIVATION_ID VARCHAR2(36 CHAR),
STATUS VARCHAR2(32 CHAR) NOT NULL,
ERROR_DETAIL VARCHAR2(256 CHAR),
ERROR_ORIGIN VARCHAR2(256 CHAR),
ERROR_SCORE INTEGER DEFAULT 0 NOT NULL,
TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL,
TIMESTAMP_LAST_UPDATED TIMESTAMP(6),
Expand All @@ -55,6 +56,7 @@ CREATE TABLE ES_ONBOARDING_OTP (
STATUS VARCHAR2(32 CHAR) NOT NULL,
TYPE VARCHAR2(32 CHAR) NOT NULL,
ERROR_DETAIL VARCHAR2(256 CHAR),
ERROR_ORIGIN VARCHAR2(256 CHAR),
FAILED_ATTEMPTS INTEGER,
TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL,
TIMESTAMP_EXPIRATION TIMESTAMP(6) NOT NULL,
Expand All @@ -77,7 +79,9 @@ CREATE TABLE ES_IDENTITY_VERIFICATION (
STATUS VARCHAR2(32 CHAR) NOT NULL,
PHASE VARCHAR2(32 CHAR) NOT NULL,
REJECT_REASON CLOB,
REJECT_ORIGIN VARCHAR2(256 CHAR),
ERROR_DETAIL VARCHAR2(256 CHAR),
ERROR_ORIGIN VARCHAR2(256 CHAR),
SESSION_INFO CLOB,
TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL,
TIMESTAMP_LAST_UPDATED TIMESTAMP(6),
Expand Down Expand Up @@ -105,7 +109,9 @@ CREATE TABLE ES_DOCUMENT_VERIFICATION (
PHOTO_ID VARCHAR2(256 CHAR),
VERIFICATION_SCORE INTEGER,
REJECT_REASON CLOB,
REJECT_ORIGIN VARCHAR2(256 CHAR),
ERROR_DETAIL VARCHAR2(256 CHAR),
ERROR_ORIGIN VARCHAR2(256 CHAR),
ORIGINAL_DOCUMENT_ID VARCHAR2(36 CHAR),
USED_FOR_VERIFICATION NUMBER(1) DEFAULT 0,
TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL,
Expand Down Expand Up @@ -141,8 +147,10 @@ CREATE TABLE ES_DOCUMENT_RESULT (
DOCUMENT_VERIFICATION_ID VARCHAR2(36 CHAR) NOT NULL,
PHASE VARCHAR2(32 CHAR) NOT NULL,
REJECT_REASON CLOB,
REJECT_ORIGIN VARCHAR2(256 CHAR),
VERIFICATION_RESULT CLOB,
ERROR_DETAIL CLOB,
ERROR_ORIGIN VARCHAR2(256 CHAR),
EXTRACTED_DATA CLOB,
TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL,
FOREIGN KEY (DOCUMENT_VERIFICATION_ID) REFERENCES ES_DOCUMENT_VERIFICATION (ID)
Expand Down
8 changes: 8 additions & 0 deletions docs/sql/postgresql/create-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ CREATE TABLE es_onboarding_process (
activation_id VARCHAR(36),
status VARCHAR(32) NOT NULL,
error_detail VARCHAR(256),
error_origin VARCHAR(256),
error_score INTEGER NOT NULL DEFAULT 0,
timestamp_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_last_updated TIMESTAMP,
Expand All @@ -59,6 +60,7 @@ CREATE TABLE es_onboarding_otp (
status VARCHAR(32) NOT NULL,
type VARCHAR(32) NOT NULL,
error_detail VARCHAR(256),
error_origin VARCHAR(256),
failed_attempts INTEGER,
timestamp_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_expiration TIMESTAMP NOT NULL,
Expand All @@ -81,7 +83,9 @@ CREATE TABLE es_identity_verification (
status VARCHAR(32) NOT NULL,
phase VARCHAR(32) NOT NULL,
reject_reason TEXT,
reject_origin VARCHAR(256),
error_detail VARCHAR(256),
error_origin VARCHAR(256),
session_info TEXT,
timestamp_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_last_updated TIMESTAMP,
Expand Down Expand Up @@ -109,7 +113,9 @@ CREATE TABLE es_document_verification (
photo_id VARCHAR(256),
verification_score INTEGER,
reject_reason TEXT,
reject_origin VARCHAR(256),
error_detail VARCHAR(256),
error_origin VARCHAR(256),
original_document_id VARCHAR(36),
used_for_verification BOOLEAN DEFAULT FALSE,
timestamp_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
Expand Down Expand Up @@ -145,8 +151,10 @@ CREATE TABLE es_document_result (
document_verification_id VARCHAR(36) NOT NULL,
phase VARCHAR(32) NOT NULL,
reject_reason TEXT,
reject_origin VARCHAR(256),
verification_result TEXT,
error_detail TEXT,
error_origin VARCHAR(256),
extracted_data TEXT,
timestamp_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (document_verification_id) REFERENCES es_document_verification (id)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* PowerAuth Enrollment Server
* Copyright (C) 2022 Wultra s.r.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wultra.app.enrollmentserver.model.enumeration;

/**
* Origin of an error enumeration.
*
* @author Roman Strobl, roman.strobl@wultra.com
*/
public enum ErrorOrigin {

DOCUMENT_VERIFICATION,

PRESENCE_CHECK,

OTP_VERIFICATION,

PROCESS_LIMIT_CHECK,

USER_REQUEST

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* PowerAuth Enrollment Server
* Copyright (C) 2022 Wultra s.r.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wultra.app.enrollmentserver.model.enumeration;

/**
* Origin of a rejection enumeration.
*
* @author Roman Strobl, roman.strobl@wultra.com
*/
public enum RejectOrigin {

DOCUMENT_VERIFICATION,

PRESENCE_CHECK

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.wultra.app.onboardingserver.common.database.entity;

import com.wultra.app.enrollmentserver.model.enumeration.ErrorOrigin;
import com.wultra.app.enrollmentserver.model.enumeration.OtpStatus;
import com.wultra.app.enrollmentserver.model.enumeration.OtpType;
import lombok.Getter;
Expand Down Expand Up @@ -74,6 +75,10 @@ public class OnboardingOtpEntity implements Serializable {
@Column(name = "error_detail")
private String errorDetail;

@Column(name = "error_origin")
@Enumerated(EnumType.STRING)
private ErrorOrigin errorOrigin;

@Column(name = "failed_attempts")
private int failedAttempts;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package com.wultra.app.onboardingserver.common.database.entity;

import com.wultra.app.enrollmentserver.model.enumeration.ErrorOrigin;
import com.wultra.app.enrollmentserver.model.enumeration.OnboardingStatus;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down Expand Up @@ -77,6 +78,10 @@ public class OnboardingProcessEntity implements Serializable {
@Column(name = "error_detail")
private String errorDetail;

@Column(name = "error_origin")
@Enumerated(EnumType.STRING)
private ErrorOrigin errorOrigin;

@Column(name = "error_score")
private int errorScore;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.wultra.app.onboardingserver.common.service;

import com.wultra.app.enrollmentserver.api.model.onboarding.response.OtpVerifyResponse;
import com.wultra.app.enrollmentserver.model.enumeration.ErrorOrigin;
import com.wultra.app.enrollmentserver.model.enumeration.OnboardingStatus;
import com.wultra.app.enrollmentserver.model.enumeration.OtpStatus;
import com.wultra.app.enrollmentserver.model.enumeration.OtpType;
Expand Down Expand Up @@ -94,12 +95,13 @@ public OtpVerifyResponse verifyOtpCode(String processId, String otpCode, OtpType
logger.warn("Unexpected not active {}, process ID: {}", otp, processId);
} else if (failedAttempts >= maxFailedAttempts) {
logger.warn("Unexpected OTP code verification when already exhausted max failed attempts, process ID: {}", processId);
process = processLimitService.failProcess(process, OnboardingOtpEntity.ERROR_MAX_FAILED_ATTEMPTS);
process = processLimitService.failProcess(process, OnboardingOtpEntity.ERROR_MAX_FAILED_ATTEMPTS, ErrorOrigin.PROCESS_LIMIT_CHECK);
} else if (otp.hasExpired()) {
logger.info("Expired OTP code received, process ID: {}", processId);
expired = true;
otp.setStatus(OtpStatus.FAILED);
otp.setErrorDetail(OnboardingOtpEntity.ERROR_EXPIRED);
otp.setErrorOrigin(ErrorOrigin.OTP_VERIFICATION);
otp.setTimestampLastUpdated(now);
onboardingOtpRepository.save(otp);
} else if (otp.getOtpCode().equals(otpCode)) {
Expand Down Expand Up @@ -138,10 +140,11 @@ private void handleFailedOtpVerification(OnboardingProcessEntity process, Onboar
if (failedAttempts >= maxFailedAttempts) {
otp.setStatus(OtpStatus.FAILED);
otp.setErrorDetail(OnboardingOtpEntity.ERROR_MAX_FAILED_ATTEMPTS);
otp.setErrorOrigin(ErrorOrigin.OTP_VERIFICATION);
onboardingOtpRepository.save(otp);

// Onboarding process is failed, update it
process = processLimitService.failProcess(process, OnboardingOtpEntity.ERROR_MAX_FAILED_ATTEMPTS);
process = processLimitService.failProcess(process, OnboardingOtpEntity.ERROR_MAX_FAILED_ATTEMPTS, ErrorOrigin.PROCESS_LIMIT_CHECK);
} else {
// Increase error score for process based on OTP type
if (otpType == OtpType.ACTIVATION) {
Expand All @@ -156,6 +159,7 @@ private void handleFailedOtpVerification(OnboardingProcessEntity process, Onboar
if (process.getStatus() == OnboardingStatus.FAILED) {
otp.setStatus(OtpStatus.FAILED);
otp.setErrorDetail(process.getErrorDetail());
otp.setErrorOrigin(ErrorOrigin.OTP_VERIFICATION);
onboardingOtpRepository.save(otp);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.wultra.app.onboardingserver.common.service;

import com.wultra.app.enrollmentserver.model.enumeration.ErrorOrigin;
import com.wultra.app.enrollmentserver.model.enumeration.OnboardingStatus;
import com.wultra.app.onboardingserver.common.configuration.CommonOnboardingConfig;
import com.wultra.app.onboardingserver.common.database.OnboardingProcessRepository;
Expand Down Expand Up @@ -71,7 +72,7 @@ public OnboardingProcessEntity checkOnboardingProcessErrorLimits(OnboardingProce
int maxProcessErrorScore = config.getMaxProcessErrorScore();
if (process.getErrorScore() > maxProcessErrorScore) {
// Onboarding process is failed, update it and persist the change
process = failProcess(process, OnboardingProcessEntity.ERROR_MAX_PROCESS_ERROR_SCORE_EXCEEDED);
process = failProcess(process, OnboardingProcessEntity.ERROR_MAX_PROCESS_ERROR_SCORE_EXCEEDED, ErrorOrigin.PROCESS_LIMIT_CHECK);
}
return process;
}
Expand All @@ -84,14 +85,15 @@ public OnboardingProcessEntity checkOnboardingProcessErrorLimits(OnboardingProce
* @param errorDetail Error detail.
* @return Updated onboarding process entity.
*/
public OnboardingProcessEntity failProcess(OnboardingProcessEntity entity, String errorDetail) {
public OnboardingProcessEntity failProcess(OnboardingProcessEntity entity, String errorDetail, ErrorOrigin errorOrigin) {
if (OnboardingStatus.FAILED == entity.getStatus()) {
logger.debug("Not failing already failed onboarding entity ID: {}", entity.getId());
return entity;
}
entity.setStatus(OnboardingStatus.FAILED);
entity.setTimestampLastUpdated(new Date());
entity.setErrorDetail(errorDetail);
entity.setErrorOrigin(errorOrigin);
return onboardingProcessRepository.save(entity);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
package com.wultra.app.onboardingserver.database.entity;

import com.wultra.app.enrollmentserver.model.enumeration.DocumentProcessingPhase;
import com.wultra.app.enrollmentserver.model.enumeration.ErrorOrigin;
import com.wultra.app.enrollmentserver.model.enumeration.RejectOrigin;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand Down Expand Up @@ -74,6 +76,13 @@ public class DocumentResultEntity implements Serializable {
@Lob
private String rejectReason;

/**
* Origin of rejection
*/
@Column(name = "reject_origin")
@Enumerated(EnumType.STRING)
private RejectOrigin rejectOrigin;

/**
* JSON serialized document with the verification result
*/
Expand All @@ -88,6 +97,10 @@ public class DocumentResultEntity implements Serializable {
@Lob
private String errorDetail;

@Column(name = "error_origin")
@Enumerated(EnumType.STRING)
private ErrorOrigin errorOrigin;

/**
* JSON serialized data extracted from the uploaded document
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@

package com.wultra.app.onboardingserver.database.entity;

import com.wultra.app.enrollmentserver.model.enumeration.CardSide;
import com.wultra.app.enrollmentserver.model.enumeration.DocumentStatus;
import com.wultra.app.enrollmentserver.model.enumeration.DocumentType;
import com.wultra.app.enrollmentserver.model.enumeration.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand Down Expand Up @@ -141,12 +139,26 @@ public class DocumentVerificationEntity implements Serializable {
@Lob
private String rejectReason;

/**
* Origin of rejection
*/
@Column(name = "reject_origin")
@Enumerated(EnumType.STRING)
private RejectOrigin rejectOrigin;

/**
* Overall error detail in case a generic error occurred
*/
@Column(name = "error_detail")
private String errorDetail;

/**
* Origin of an error
*/
@Column(name = "error_origin")
@Enumerated(EnumType.STRING)
private ErrorOrigin errorOrigin;

/**
* Identifier of an entity which was replaced by this entity
*/
Expand Down
Loading