Skip to content

Commit

Permalink
Merge pull request #866 from /issues/777-fake-otp-marker
Browse files Browse the repository at this point in the history
Fix #777: Add column for fake OTP delivery
  • Loading branch information
banterCZ authored Sep 26, 2023
2 parents 3cca169 + 3e3c4f4 commit 61e2607
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd">

<changeSet id="1" logicalFilePath="enrollment-server-onboarding/1.5.x/20230919-add-otp-fake.xml" author="Lubos Racansky">
<preConditions onFail="MARK_RAN">
<not>
<columnExists tableName="es_onboarding_otp" columnName="fake"/>
</not>
</preConditions>
<comment>Add fake column</comment>
<addColumn tableName="es_onboarding_otp">
<column name="fake" type="boolean" defaultValueBoolean="false">
<constraints nullable="false" />
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd">

<changeSet id="1" logicalFilePath="enrollment-server-onboarding/1.5.x/20230824-add-tag-1.5.0.xml" author="Lubos Racansky">
<changeSet id="1" logicalFilePath="enrollment-server-onboarding/1.5.x/20230919-add-tag-1.5.0.xml" author="Lubos Racansky">
<tagDatabase tag="enrollment-server-onboarding/1.5.0"/>
</changeSet>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<include file="20230315-add-column-fds-data.xml" relativeToChangelogFile="true" />
<include file="20230530-add-column-total-attempts.xml" relativeToChangelogFile="true" />
<include file="20230614-add-sca-result.xml" relativeToChangelogFile="true" />
<include file="20230824-add-tag-1.5.0.xml" relativeToChangelogFile="true" />
<include file="20230919-add-otp-fake.xml" relativeToChangelogFile="true" />
<include file="20230919-add-tag-1.5.0.xml" relativeToChangelogFile="true" />

</databaseChangeLog>
33 changes: 17 additions & 16 deletions docs/onboarding/Database-Structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,23 @@ Stores onboarding OTP codes used during activation and user verification.

#### Schema

| Name | Type | Info | Note |
|---|---|---|---|
| `id` | `VARCHAR(36)` | `NOT NULL PRIMARY KEY` | Autogenerated record identifier (UUID). |
| `process_id` | `VARCHAR(36)` | `NOT NULL` | Process identifier (UUID). |
| `otp_code` | `VARCHAR(32)` | `NOT NULL` | Generated OTP code. |
| `status` | `VARCHAR(36)` | | Generated OTP code. |
| `type` | `VARCHAR(32)` | `NOT NULL` | OTP code type (`ACTIVATION`, `USER_VERIFICATION`). |
| `error_detail` | `VARCHAR(256)` | | Detail of error (e.g. information about timeout or exceeded number of failed attempts). |
| `error_origin` | `VARCHAR(256)` | | Origin of the error (`DOCUMENT_VERIFICATION`, `PRESENCE_CHECK`, `CLIENT_EVALUATION`, `OTP_VERIFICATION`, `PROCESS_LIMIT_CHECK`, `USER_REQUEST`). |
| `failed_attempts` | `INTEGER` | | Number of failed attempts for verification. |
| `total_attempts` | `INTEGER` | | Number of total attempts for verification. |
| `timestamp_created` | `TIMESTAMP` | `NOT NULL DEFAULT CURRENT_TIMESTAMP` | Timestamp when process was started. |
| `timestamp_expiration` | `TIMESTAMP` | `NOT NULL` | Timestamp when the OTP expires. |
| `timestamp_last_updated` | `TIMESTAMP` | | Timestamp when record was last updated. |
| `timestamp_verified` | `TIMESTAMP` | | Timestamp when OTP was verified. |
| `timestamp_failed` | `TIMESTAMP` | | Timestamp when OTP failed. |
| Name | Type | Info | Note |
|--------------------------|----------------|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | `VARCHAR(36)` | `NOT NULL PRIMARY KEY` | Autogenerated record identifier (UUID). |
| `process_id` | `VARCHAR(36)` | `NOT NULL` | Process identifier (UUID). |
| `otp_code` | `VARCHAR(32)` | `NOT NULL` | Generated OTP code. |
| `status` | `VARCHAR(36)` | | Generated OTP code. |
| `type` | `VARCHAR(32)` | `NOT NULL` | OTP code type (`ACTIVATION`, `USER_VERIFICATION`). |
| `error_detail` | `VARCHAR(256)` | | Detail of error (e.g. information about timeout or exceeded number of failed attempts). |
| `error_origin` | `VARCHAR(256)` | | Origin of the error (`DOCUMENT_VERIFICATION`, `PRESENCE_CHECK`, `CLIENT_EVALUATION`, `OTP_VERIFICATION`, `PROCESS_LIMIT_CHECK`, `USER_REQUEST`). |
| `failed_attempts` | `INTEGER` | | Number of failed attempts for verification. |
| `total_attempts` | `INTEGER` | | Number of total attempts for verification. |
| `fake` | `BOOLEAN` | `NOT NULL DEFAULT FALSE` | Whether is a fake entry not supposed to be sent. |
| `timestamp_created` | `TIMESTAMP` | `NOT NULL DEFAULT CURRENT_TIMESTAMP` | Timestamp when process was started. |
| `timestamp_expiration` | `TIMESTAMP` | `NOT NULL` | Timestamp when the OTP expires. |
| `timestamp_last_updated` | `TIMESTAMP` | | Timestamp when record was last updated. |
| `timestamp_verified` | `TIMESTAMP` | | Timestamp when OTP was verified. |
| `timestamp_failed` | `TIMESTAMP` | | Timestamp when OTP failed. |

<!-- end -->

Expand Down
21 changes: 21 additions & 0 deletions docs/onboarding/PowerAuth-Enrollment-Onboarding-Server-1.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ CREATE INDEX PROCESS_ID ON ES_SCA_RESULT (PROCESS_ID);
```


### OTP Fake Marker

A new column `fake` has been added to the table `es_onboarding_otp`.


#### PostgreSQL

```sql
ALTER TABLE es_onboarding_otp
ADD COLUMN fake BOOLEAN NOT NULL DEFAULT FALSE;
```


#### Oracle

```sql
ALTER TABLE es_onboarding_OTP
ADD fake NUMBER(1) NOT NULL DEFAULT 0;
```


## Dependencies

PostgreSQL JDBC driver is already included in the WAR file.
Expand Down
1 change: 1 addition & 0 deletions docs/sql/oracle/onboarding/create-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ CREATE TABLE ES_ONBOARDING_OTP (
ERROR_ORIGIN VARCHAR2(256 CHAR),
FAILED_ATTEMPTS INTEGER,
TOTAL_ATTEMPTS INTEGER DEFAULT 0,
FAKE NUMBER(1) NOT NULL DEFAULT 0,
TIMESTAMP_CREATED TIMESTAMP(6) NOT NULL,
TIMESTAMP_EXPIRATION TIMESTAMP(6) NOT NULL,
TIMESTAMP_LAST_UPDATED TIMESTAMP(6),
Expand Down
1 change: 1 addition & 0 deletions docs/sql/postgresql/onboarding/create-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ CREATE TABLE es_onboarding_otp (
error_origin VARCHAR(256),
failed_attempts INTEGER,
total_attempts INTEGER DEFAULT 0,
fake BOOLEAN NOT NULL DEFAULT false,
timestamp_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
timestamp_expiration TIMESTAMP NOT NULL,
timestamp_last_updated TIMESTAMP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.UuidGenerator;

import java.io.Serial;
Expand Down Expand Up @@ -96,6 +95,12 @@ public class OnboardingOtpEntity implements Serializable {
@Column(name = "total_attempts")
private int totalAttempts;

/**
* Whether is a fake entry not supposed to be sent.
*/
@Column(name = "fake")
private boolean fake;

@Column(name = "timestamp_created", nullable = false)
private Date timestampCreated;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,12 @@ public OnboardingStartResponse startOnboarding(
throw new TooManyProcessesException("Maximum number of processes per day reached for user: " + userId);
}

final String otpCode = otpService.createOtpCode(process, OtpType.ACTIVATION);
if (userId == null) {
logger.debug("User ID is null, OTP is not sent");
otpService.createFakeOtpCode(process, OtpType.ACTIVATION);
} else {
logger.debug("Sending OTP for user ID: {}", userId);
final String otpCode = otpService.createOtpCode(process, OtpType.ACTIVATION);
sendOtp(process, otpCode);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ public String createOtpCode(OnboardingProcessEntity process, OtpType otpType) th
return generateOtpCode(process, otpType);
}

/**
* Create a fake OTP code for onboarding process.
*
* @param process Onboarding process.
* @param otpType OTP type.
* @throws OnboardingProcessException Thrown in case OTP code could not be generated.
* @see #createOtpCode(OnboardingProcessEntity, OtpType)
*/
public void createFakeOtpCode(OnboardingProcessEntity process, OtpType otpType) throws OnboardingProcessException {
generateFakeOtpCode(process, otpType);
}

/**
* Create an OTP code for onboarding process for resend.
* @param process Onboarding process.
Expand Down Expand Up @@ -155,6 +167,31 @@ public void cancelOtp(OnboardingProcessEntity process, OtpType otpType) {
* @throws OnboardingProcessException Thrown in case OTP code could not be generated.
*/
private String generateOtpCode(OnboardingProcessEntity process, OtpType otpType) throws OnboardingProcessException {
return generateOtpCode(process, otpType, false);
}

/**
* Generate a fake OTP code for an onboarding process.
*
* @param process Onboarding process.
* @param otpType OTP type.
* @return OTP code.
* @throws OnboardingProcessException Thrown in case OTP code could not be generated.
*/
private void generateFakeOtpCode(OnboardingProcessEntity process, OtpType otpType) throws OnboardingProcessException {
generateOtpCode(process, otpType, true);
}

/**
* Generate an OTP code for an onboarding process.
*
* @param process Onboarding process.
* @param otpType OTP type.
* @param fake Whether OTP should be marked as a fake.
* @return OTP code.
* @throws OnboardingProcessException Thrown in case OTP code could not be generated.
*/
private String generateOtpCode(OnboardingProcessEntity process, OtpType otpType, boolean fake) throws OnboardingProcessException {
int otpLength = onboardingConfig.getOtpLength();
String otpCode = otpGeneratorService.generateOtpCode(otpLength);

Expand All @@ -173,6 +210,7 @@ private String generateOtpCode(OnboardingProcessEntity process, OtpType otpType)
otp.setTimestampExpiration(timestampExpiration);
otp.setFailedAttempts(0);
otp.setTotalAttempts(0);
otp.setFake(fake);

if (otpType == OtpType.USER_VERIFICATION) {
final String activationId = process.getActivationId();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
INSERT INTO es_onboarding_process(id, identification_data, status, error_score, custom_data, timestamp_created) VALUES
('b4662611-df91-4053-bb3d-3970979baf5d', '{}', 'VERIFICATION_IN_PROGRESS', 0, '{}', now());

INSERT INTO es_onboarding_otp(id, process_id, otp_code, failed_attempts, total_attempts, status, type, timestamp_created, timestamp_expiration) VALUES
('f50b8c04-649d-43a7-8079-4dbf9b0bbc72', 'b4662611-df91-4053-bb3d-3970979baf5d', '123', 0, 0, 'ACTIVE', 'USER_VERIFICATION', now(), now()),
('6560a85d-7d97-44c0-bd29-04c57051aa57', 'b4662611-df91-4053-bb3d-3970979baf5d', '123', 0, 0, 'ACTIVE', 'USER_VERIFICATION', now() - interval '301' second, now()), -- to be failed
('e4974ef6-135a-4ae1-be91-a2c0f674c8fd', 'b4662611-df91-4053-bb3d-3970979baf5d', '123', 0, 0, 'VERIFIED', 'USER_VERIFICATION', now() - interval '301' second, now());
INSERT INTO es_onboarding_otp(id, process_id, otp_code, failed_attempts, total_attempts, status, type, fake, timestamp_created, timestamp_expiration) VALUES
('f50b8c04-649d-43a7-8079-4dbf9b0bbc72', 'b4662611-df91-4053-bb3d-3970979baf5d', '123', 0, 0, 'ACTIVE', 'USER_VERIFICATION', false, now(), now()),
('6560a85d-7d97-44c0-bd29-04c57051aa57', 'b4662611-df91-4053-bb3d-3970979baf5d', '123', 0, 0, 'ACTIVE', 'USER_VERIFICATION', false, now() - interval '301' second, now()), -- to be failed
('e4974ef6-135a-4ae1-be91-a2c0f674c8fd', 'b4662611-df91-4053-bb3d-3970979baf5d', '123', 0, 0, 'VERIFIED', 'USER_VERIFICATION', false, now() - interval '301' second, now());

0 comments on commit 61e2607

Please sign in to comment.