This is an automated email from the ASF dual-hosted git repository.

ptuomola pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 907f932  Simplify build for different auth strategies
907f932 is described below

commit 907f932abe5bd13a87052e7179ca3394560b57ee
Author: Aleksandar Vidakovic <[email protected]>
AuthorDate: Sun Jan 2 05:07:20 2022 +0100

    Simplify build for different auth strategies
---
 .github/workflows/build-oauth2.yml                 | 60 ----------------------
 .github/workflows/build-twofactor.yml              | 52 -------------------
 .github/workflows/build.yml                        | 22 ++++++--
 .gitignore                                         |  1 -
 README.md                                          | 44 ++++++++++++++++
 fineract-provider/build.gradle                     | 32 ------------
 .../properties/basicauth/application.properties    | 33 ------------
 .../properties/oauth/application.properties        | 37 -------------
 .../core/config/OAuth2SecurityConfig.java          |  4 +-
 .../infrastructure/core/config/SecurityConfig.java |  4 +-
 .../core/config/SecurityValidationConfig.java      | 50 ++++++++++++++++++
 .../security/api/AuthenticationApiResource.java    | 15 +++---
 .../security/api/TwoFactorApiResource.java         |  4 +-
 .../api/TwoFactorConfigurationApiResource.java     |  4 +-
 .../security/api/UserDetailsApiResource.java       | 21 ++++----
 .../InvalidateTFAccessTokenCommandHandler.java     |  4 +-
 .../UpdateTwoFactorConfigCommandHandler.java       |  4 +-
 .../data/TwoFactorConfigurationValidator.java      |  4 +-
 .../security/domain/OTPRequestRepository.java      |  4 +-
 .../security/domain/TFAccessTokenRepository.java   |  4 +-
 .../domain/TwoFactorConfigurationRepository.java   |  4 +-
 .../InsecureTwoFactorAuthenticationFilter.java     |  4 +-
 .../TenantAwareBasicAuthenticationFilter.java      |  4 +-
 .../filter/TenantAwareTenantIdentifierFilter.java  |  4 +-
 .../filter/TwoFactorAuthenticationFilter.java      |  4 +-
 .../service/TwoFactorConfigurationServiceImpl.java |  4 +-
 .../security/service/TwoFactorServiceImpl.java     |  4 +-
 .../security/service/TwoFactorUtils.java           | 45 ----------------
 .../api/SelfAuthenticationApiResource.java         |  4 +-
 .../security/api/SelfUserDetailsApiResource.java   |  4 +-
 .../main/resources}/application.properties         |  8 +--
 .../provider/CommandHandlerProviderTest.java       |  4 +-
 .../spring/SpringConfigurationTest.java            |  4 +-
 ...TestsWithoutDatabaseAndNoJobsConfiguration.java |  9 ++++
 ...ractSpringBootWithMariaDB4jIntegrationTest.java |  4 +-
 .../test/resources/application-test.properties}    |  6 ++-
 oauth2-tests/build.gradle                          |  2 +-
 twofactor-tests/build.gradle                       |  2 +-
 .../TwoFactorAuthenticationTest.java               |  2 +-
 39 files changed, 194 insertions(+), 331 deletions(-)

diff --git a/.github/workflows/build-oauth2.yml 
b/.github/workflows/build-oauth2.yml
deleted file mode 100644
index 7b715fe..0000000
--- a/.github/workflows/build-oauth2.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-name: Fineract Gradle build - oauth2
-on: [push, pull_request]
-
-jobs:
-  build:
-    runs-on: ubuntu-20.04
-
-    services:
-        mariad:
-            image: mariadb:10.6
-            ports:
-                - 3306:3306
-            env:
-                MARIADB_ROOT_PASSWORD: mysql
-            options: --health-cmd="mysqladmin ping" --health-interval=5s 
--health-timeout=2s --health-retries=3
-
-        mock-oauth2-server:
-            image: ghcr.io/navikt/mock-oauth2-server:0.4.0
-            ports:
-                - 9000:9000
-            env:
-                SERVER_PORT: 9000
-                JSON_CONFIG: '{ "interactiveLogin": true, "httpServer": 
"NettyWrapper", "tokenCallbacks": [ { "issuerId": "auth/realms/fineract", 
"tokenExpiry": 120, "requestMappings": [{ "requestParam": "scope", "match": 
"fineract", "claims": { "sub": "mifos", "scope": [ "test" ] } } ] } ] }'
-
-    env:
-        TZ: Asia/Kolkata
-    steps:
-      - name: Set up cache
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-oauth2-${{ hashFiles('**/*.gradle*', 
'**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-oauth2-
-      - name: Checkout
-        uses: actions/checkout@v2
-      - name: Set up JDK 11
-        uses: actions/setup-java@v2
-        with:
-          java-version: '11'
-          distribution: 'zulu'
-      - name: Validate Gradle wrapper
-        uses: 
gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
-      - name: Verify MariaDB connection
-        run: |
-            while ! mysqladmin ping -h"127.0.0.1" -P3306 ; do
-                sleep 1
-            done
-      - name: Initialise databases
-        run: |
-            ./gradlew --no-daemon -q createDB -PdbName=fineract_tenants
-            ./gradlew --no-daemon -q createDB -PdbName=fineract_default
-      - name: Install additional software
-        run: |
-            sudo apt-get update
-            sudo apt-get install ghostscript -y
-      - name: Build & Test
-        run: ./gradlew --no-daemon -q --console=plain build test --fail-fast 
-x :integration-tests:test -x :twofactor-tests:test -Psecurity=oauth
diff --git a/.github/workflows/build-twofactor.yml 
b/.github/workflows/build-twofactor.yml
deleted file mode 100644
index aac7141..0000000
--- a/.github/workflows/build-twofactor.yml
+++ /dev/null
@@ -1,52 +0,0 @@
-name: Fineract Gradle build - twofactor
-on: [push, pull_request]
-
-jobs:
-  build:
-    runs-on: ubuntu-20.04
-
-    services:
-        mariad:
-            image: mariadb:10.6
-            ports:
-                - 3306:3306
-            env:
-                MARIADB_ROOT_PASSWORD: mysql
-            options: --health-cmd="mysqladmin ping" --health-interval=5s 
--health-timeout=2s --health-retries=3
-
-    env:
-        TZ: Asia/Kolkata
-    steps:
-      - name: Set up cache
-        uses: actions/cache@v2
-        with:
-          path: |
-            ~/.gradle/caches
-            ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-twofactor-${{ hashFiles('**/*.gradle*', 
'**/gradle-wrapper.properties') }}
-          restore-keys: |
-            ${{ runner.os }}-gradle-twofactor-
-      - name: Checkout
-        uses: actions/checkout@v2
-      - name: Set up JDK 11
-        uses: actions/setup-java@v2
-        with:
-          java-version: '11'
-          distribution: 'zulu'
-      - name: Validate Gradle wrapper
-        uses: 
gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
-      - name: Verify MariaDB connection
-        run: |
-            while ! mysqladmin ping -h"127.0.0.1" -P3306 ; do
-                sleep 1
-            done
-      - name: Initialise databases
-        run: |
-            ./gradlew --no-daemon -q createDB -PdbName=fineract_tenants
-            ./gradlew --no-daemon -q createDB -PdbName=fineract_default
-      - name: Install additional software
-        run: |
-            sudo apt-get update
-            sudo apt-get install ghostscript -y
-      - name: Build & Test
-        run: ./gradlew --no-daemon -q --console=plain build test --fail-fast 
-x :integration-tests:test -x :oauth2-tests:test -Ptwofactor=enabled
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9e89ac6..6ce6f08 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,6 +13,15 @@ jobs:
             env:
                 MARIADB_ROOT_PASSWORD: mysql
             options: --health-cmd="mysqladmin ping" --health-interval=5s 
--health-timeout=2s --health-retries=3
+
+        mock-oauth2-server:
+          image: ghcr.io/navikt/mock-oauth2-server:0.4.0
+          ports:
+            - 9000:9000
+          env:
+            SERVER_PORT: 9000
+            JSON_CONFIG: '{ "interactiveLogin": true, "httpServer": 
"NettyWrapper", "tokenCallbacks": [ { "issuerId": "auth/realms/fineract", 
"tokenExpiry": 120, "requestMappings": [{ "requestParam": "scope", "match": 
"fineract", "claims": { "sub": "mifos", "scope": [ "test" ] } } ] } ] }'
+
     env:
         TZ: Asia/Kolkata
     steps:
@@ -22,9 +31,9 @@ jobs:
           path: |
             ~/.gradle/caches
             ~/.gradle/wrapper
-          key: ${{ runner.os }}-gradle-basicauth-${{ hashFiles('**/*.gradle*', 
'**/gradle-wrapper.properties') }}
+          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', 
'**/gradle-wrapper.properties') }}
           restore-keys: |
-            ${{ runner.os }}-gradle-basicauth-
+            ${{ runner.os }}-gradle-
       - name: Checkout
         uses: actions/checkout@v2
       - name: Set up JDK 11
@@ -47,5 +56,12 @@ jobs:
         run: |
             sudo apt-get update
             sudo apt-get install ghostscript -y
-      - name: Build & Test
+
+      - name: Basic Auth Build & Test
         run: ./gradlew --no-daemon -q --console=plain licenseMain licenseTest 
check build test --fail-fast doc -x :twofactor-tests:test -x :oauth2-test:test
+
+      - name: 2FA Build & Test
+        run: ./gradlew --no-daemon -q --console=plain :twofactor-tests:test 
--fail-fast
+
+      - name: OAuth2 Build & Test
+        run: ./gradlew --no-daemon -q --console=plain :oauth2-tests:test 
--fail-fast
diff --git a/.gitignore b/.gitignore
index e56ba7e..0ae3f43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,7 +17,6 @@ build
 catalina.base_IS_UNDEFINED/
 keystore.jks
 bin/
-fineract-provider/src/main/resources/application.properties
 .lock
 fineract-provider/out/
 fineract-provider/config/swagger/config.json
diff --git a/README.md b/README.md
index d276d3e..9c26e58 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,50 @@ The tenants database connection details are configured [via 
environment variable
     java -jar fineract-provider.jar
 
 
+Security
+============
+NOTE: The HTTP Basic and OAuth2 authentication schemes are mutually exclusive. 
You can't enable them both at the same time. Fineract checks these settings on 
startup and will fail if more than one authentication scheme is enabled.
+
+HTTP Basic Authentication
+------------
+By default Fineract is configured with a HTTP Basic Authentication scheme, so 
you actually don't have to do anything if you want to use it. But if you would 
like to explicitly choose this authentication scheme then there are two ways to 
enable it:
+1. Use environment variables (best choice if you run with Docker Compose):
+```
+FINERACT_SECURITY_BASICAUTH_ENABLED=true
+FINERACT_SECURITY_OAUTH_ENABLED=false
+```
+2. Use JVM parameters (best choice if you run the Spring Boot JAR):
+```
+java -Dfineract.security.basicauth.enabled=true 
-Dfineract.security.oauth.enabled=false -jar fineract-provider.jar
+```
+
+OAuth2 Authentication
+------------
+There is also an OAuth2 authentication scheme available. Again, two ways to 
enable it:
+1. Use environment variables (best choice if you run with Docker Compose):
+```
+FINERACT_SECURITY_BASICAUTH_ENABLED=false
+FINERACT_SECURITY_OAUTH_ENABLED=true
+```
+2. Use JVM parameters (best choice if you run the Spring Boot JAR):
+```
+java -Dfineract.security.basicauth.enabled=false 
-Dfineract.security.oauth.enabled=true -jar fineract-provider.jar
+```
+
+Two Factor Authentication
+------------
+You can also enable 2FA authentication. Depending on how you start Fineract 
add the following:
+
+1. Use environment variable (best choice if you run with Docker Compose):
+```
+FINERACT_SECURITY_2FA_ENABLED=true
+```
+2. Use JVM parameter (best choice if you run the Spring Boot JAR):
+```
+-Dfineract.security.2fa.enabled=true
+```
+
+
 Instructions to build a WAR file
 ============
 1. Clone the repository or download and extract the archive file to your local 
directory.
diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle
index f034777..0d8d44a 100644
--- a/fineract-provider/build.gradle
+++ b/fineract-provider/build.gradle
@@ -155,37 +155,6 @@ configurations {
 
 apply from: 'dependencies.gradle'
 
-/* Enable Oauth2 authentication based on environment, default to HTTP basic 
auth */
-if (project.hasProperty('security') && project.getProperty('security') == 
'oauth') {
-    if(project.hasProperty('twofactor') && project.getProperty('twofactor') == 
'enabled') {
-        copy {
-            from './properties/oauth/twofactor/'
-            into 'src/main/resources/'
-            include '*.properties'
-        }
-    } else {
-        copy {
-            from './properties/oauth/'
-            into 'src/main/resources/'
-            include '*.properties'
-        }
-    }
-}  else {
-    if(project.hasProperty('twofactor') && project.getProperty('twofactor') == 
'enabled') {
-        copy {
-            from './properties/basicauth/twofactor/'
-            into 'src/main/resources/'
-            include '*.properties'
-        }
-    } else {
-        copy {
-            from './properties/basicauth/'
-            into 'src/main/resources/'
-            include '*.properties'
-        }
-    }
-}
-
 // Configuration for the modernizer plugin
 // https://github.com/andygoossens/gradle-modernizer-plugin
 modernizer {
@@ -324,7 +293,6 @@ jib {
         ]
         args = [
             '-Duser.home=/tmp',
-            '-Dspring.profiles.active=basicauth',
             '-Dfile.encoding=UTF-8',
             '-Duser.timezone=UTC',
             '-Djava.security.egd=file:/dev/./urandom'
diff --git a/fineract-provider/properties/basicauth/application.properties 
b/fineract-provider/properties/basicauth/application.properties
deleted file mode 100644
index be392eb..0000000
--- a/fineract-provider/properties/basicauth/application.properties
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-spring.profiles.default=basicauth
-management.health.jms.enabled=false
-
-# FINERACT 1296
-management.endpoint.health.probes.enabled=true
-management.health.livenessState.enabled=true
-management.health.readinessState.enabled=true
-
-# FINERACT-883
-management.info.git.mode=FULL
-management.endpoints.web.exposure.include=health,info
-
-# FINERACT-914
-server.forward-headers-strategy=framework
diff --git a/fineract-provider/properties/oauth/application.properties 
b/fineract-provider/properties/oauth/application.properties
deleted file mode 100644
index 6936db5..0000000
--- a/fineract-provider/properties/oauth/application.properties
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-spring.profiles.default=basicauth
-spring.profiles.active=oauth
-management.health.jms.enabled=false
-
-# FINERACT 1296
-management.endpoint.health.probes.enabled=true
-management.health.livenessState.enabled=true
-management.health.readinessState.enabled=true
-
-# FINERACT-883
-management.info.git.mode=FULL
-management.endpoints.web.exposure.include=health,info
-
-# FINERACT-914
-server.forward-headers-strategy=framework
-
-# OAuth authorisation server endpoint
-spring.security.oauth2.resourceserver.jwt.issuer-uri: 
http://localhost:9000/auth/realms/fineract
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
index a2226c9..32202a6 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
@@ -29,10 +29,10 @@ import 
org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticatio
 import 
org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
 import 
org.apache.fineract.infrastructure.security.vote.SelfServiceUserAccessVote;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Profile;
 import org.springframework.core.convert.converter.Converter;
 import org.springframework.http.HttpMethod;
 import org.springframework.security.access.AccessDecisionManager;
@@ -59,7 +59,7 @@ import 
org.springframework.security.web.authentication.www.BasicAuthenticationFi
 import 
org.springframework.security.web.context.SecurityContextPersistenceFilter;
 
 @Configuration
-@Profile("oauth")
+@ConditionalOnProperty("fineract.security.oauth.enabled")
 @EnableGlobalMethodSecurity(prePostEnabled = true)
 public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
index 4269790..8fac767 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
@@ -23,10 +23,10 @@ import 
org.apache.fineract.infrastructure.security.filter.TenantAwareBasicAuthen
 import 
org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticationFilter;
 import 
org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Profile;
 import org.springframework.http.HttpMethod;
 import org.springframework.security.authentication.AuthenticationManager;
 import 
org.springframework.security.authentication.dao.DaoAuthenticationProvider;
@@ -42,7 +42,7 @@ import 
org.springframework.security.web.authentication.www.BasicAuthenticationFi
 import 
org.springframework.security.web.context.SecurityContextPersistenceFilter;
 
 @Configuration
-@Profile("basicauth")
+@ConditionalOnProperty("fineract.security.basicauth.enabled")
 @EnableGlobalMethodSecurity(prePostEnabled = true)
 public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityValidationConfig.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityValidationConfig.java
new file mode 100644
index 0000000..6954d46
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityValidationConfig.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.infrastructure.core.config;
+
+import javax.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SecurityValidationConfig {
+
+    @Value("${fineract.security.basicauth.enabled}")
+    private Boolean basicAuthEnabled;
+
+    @Value("${fineract.security.oauth.enabled}")
+    private Boolean oauthEnabled;
+
+    @PostConstruct
+    public void validate() {
+        // NOTE: avoid NPE if these values are not set
+        if (!Boolean.TRUE.equals(basicAuthEnabled) && 
!Boolean.TRUE.equals(oauthEnabled)) {
+            // NOTE: while we are already doing consistency checks we might as 
well cover this case; should not happen
+            // as defaults are set in application.properties
+            throw new IllegalArgumentException(
+                    "No authentication scheme selected. Please decide if you 
want to use basic OR OAuth2 authentication.");
+        }
+
+        if (Boolean.TRUE.equals(basicAuthEnabled) && 
Boolean.TRUE.equals(oauthEnabled)) {
+            throw new IllegalArgumentException(
+                    "Too many authentication schemes selected. Please decide 
if you want to use basic OR OAuth2 authentication.");
+        }
+    }
+}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/AuthenticationApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/AuthenticationApiResource.java
index fc3ed60..91efd8e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/AuthenticationApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/AuthenticationApiResource.java
@@ -44,14 +44,14 @@ import 
org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer
 import 
org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
 import org.apache.fineract.infrastructure.security.data.AuthenticatedUserData;
 import 
org.apache.fineract.infrastructure.security.service.SpringSecurityPlatformSecurityContext;
-import org.apache.fineract.infrastructure.security.service.TwoFactorUtils;
 import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
 import org.apache.fineract.useradministration.data.RoleData;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.apache.fineract.useradministration.domain.Role;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Profile;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Scope;
 import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import 
org.springframework.security.authentication.dao.DaoAuthenticationProvider;
@@ -61,11 +61,14 @@ import org.springframework.stereotype.Component;
 
 @Component
 @Scope("singleton")
-@Profile("basicauth")
+@ConditionalOnProperty("fineract.security.basicauth.enabled")
 @Path("/authentication")
 @Tag(name = "Authentication HTTP Basic", description = "An API capability that 
allows client applications to verify authentication details using HTTP Basic 
Authentication.")
 public class AuthenticationApiResource {
 
+    @Value("${fineract.security.2fa.enabled}")
+    private boolean twoFactorEnabled;
+
     public static class AuthenticateRequest {
 
         public String username;
@@ -75,19 +78,17 @@ public class AuthenticationApiResource {
     private final DaoAuthenticationProvider customAuthenticationProvider;
     private final ToApiJsonSerializer<AuthenticatedUserData> 
apiJsonSerializerService;
     private final SpringSecurityPlatformSecurityContext 
springSecurityPlatformSecurityContext;
-    private final TwoFactorUtils twoFactorUtils;
     private final ClientReadPlatformService clientReadPlatformService;
 
     @Autowired
     public AuthenticationApiResource(
             @Qualifier("customAuthenticationProvider") final 
DaoAuthenticationProvider customAuthenticationProvider,
             final ToApiJsonSerializer<AuthenticatedUserData> 
apiJsonSerializerService,
-            final SpringSecurityPlatformSecurityContext 
springSecurityPlatformSecurityContext, TwoFactorUtils twoFactorUtils,
+            final SpringSecurityPlatformSecurityContext 
springSecurityPlatformSecurityContext,
             ClientReadPlatformService aClientReadPlatformService) {
         this.customAuthenticationProvider = customAuthenticationProvider;
         this.apiJsonSerializerService = apiJsonSerializerService;
         this.springSecurityPlatformSecurityContext = 
springSecurityPlatformSecurityContext;
-        this.twoFactorUtils = twoFactorUtils;
         clientReadPlatformService = aClientReadPlatformService;
     }
 
@@ -143,7 +144,7 @@ public class AuthenticationApiResource {
 
             final EnumOptionData organisationalRole = 
principal.organisationalRoleData();
 
-            boolean isTwoFactorRequired = 
twoFactorUtils.isTwoFactorAuthEnabled()
+            boolean isTwoFactorRequired = this.twoFactorEnabled
                     && 
!principal.hasSpecificPermissionTo(TwoFactorConstants.BYPASS_TWO_FACTOR_PERMISSION);
             Long userId = principal.getId();
             if 
(this.springSecurityPlatformSecurityContext.doesPasswordHasToBeRenewed(principal))
 {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorApiResource.java
index 839c050..91617dd 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorApiResource.java
@@ -45,13 +45,13 @@ import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
 import org.apache.fineract.infrastructure.security.service.TwoFactorService;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
 @Path("/twofactor")
 @Component
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 @Scope("singleton")
 @Tag(name = "Two Factor", description = "")
 public class TwoFactorApiResource {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorConfigurationApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorConfigurationApiResource.java
index c6980eb..e76af9a 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorConfigurationApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/TwoFactorConfigurationApiResource.java
@@ -33,7 +33,7 @@ import 
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import 
org.apache.fineract.infrastructure.security.service.TwoFactorConfigurationService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
@@ -42,7 +42,7 @@ import org.springframework.stereotype.Component;
 @Produces({ MediaType.APPLICATION_JSON })
 @Component
 @Scope("singleton")
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class TwoFactorConfigurationApiResource {
 
     private final String resourceNameForPermissions = "TWOFACTOR_CONFIG";
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/UserDetailsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/UserDetailsApiResource.java
index 64e96bf..2ee5fcc 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/UserDetailsApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/api/UserDetailsApiResource.java
@@ -37,12 +37,12 @@ import 
org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
 import 
org.apache.fineract.infrastructure.security.data.AuthenticatedOauthUserData;
 import 
org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
 import 
org.apache.fineract.infrastructure.security.service.SpringSecurityPlatformSecurityContext;
-import org.apache.fineract.infrastructure.security.service.TwoFactorUtils;
 import org.apache.fineract.useradministration.data.RoleData;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.apache.fineract.useradministration.domain.Role;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Scope;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.context.SecurityContext;
@@ -54,22 +54,22 @@ import org.springframework.stereotype.Component;
  */
 @Path("/userdetails")
 @Component
-@Profile("oauth")
+@ConditionalOnProperty("fineract.security.oauth.enabled")
 @Scope("singleton")
-
 @Tag(name = "Fetch authenticated user details", description = "")
 public class UserDetailsApiResource {
 
     private final ToApiJsonSerializer<AuthenticatedOauthUserData> 
apiJsonSerializerService;
     private final SpringSecurityPlatformSecurityContext 
springSecurityPlatformSecurityContext;
-    private final TwoFactorUtils twoFactorUtils;
+
+    @Value("${fineract.security.2fa.enabled}")
+    private boolean twoFactorEnabled;
 
     @Autowired
     public UserDetailsApiResource(final 
ToApiJsonSerializer<AuthenticatedOauthUserData> apiJsonSerializerService,
-            final SpringSecurityPlatformSecurityContext 
springSecurityPlatformSecurityContext, final TwoFactorUtils twoFactorUtils) {
+            final SpringSecurityPlatformSecurityContext 
springSecurityPlatformSecurityContext) {
         this.apiJsonSerializerService = apiJsonSerializerService;
         this.springSecurityPlatformSecurityContext = 
springSecurityPlatformSecurityContext;
-        this.twoFactorUtils = twoFactorUtils;
     }
 
     @GET
@@ -116,16 +116,15 @@ public class UserDetailsApiResource {
 
         final EnumOptionData organisationalRole = 
principal.organisationalRoleData();
 
-        final boolean requireTwoFactorAuth = 
twoFactorUtils.isTwoFactorAuthEnabled()
+        boolean isTwoFactorRequired = this.twoFactorEnabled
                 && 
!principal.hasSpecificPermissionTo(TwoFactorConstants.BYPASS_TWO_FACTOR_PERMISSION);
-
         if 
(this.springSecurityPlatformSecurityContext.doesPasswordHasToBeRenewed(principal))
 {
             authenticatedUserData = new 
AuthenticatedOauthUserData(principal.getUsername(), principal.getId(),
-                    authentication.getToken().getTokenValue(), 
requireTwoFactorAuth);
+                    authentication.getToken().getTokenValue(), 
isTwoFactorRequired);
         } else {
             authenticatedUserData = new 
AuthenticatedOauthUserData(principal.getUsername(), officeId, officeName, 
staffId, staffDisplayName,
                     organisationalRole, roles, permissions, principal.getId(), 
authentication.getToken().getTokenValue(),
-                    requireTwoFactorAuth);
+                    isTwoFactorRequired);
         }
 
         return this.apiJsonSerializerService.serialize(authenticatedUserData);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/InvalidateTFAccessTokenCommandHandler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/InvalidateTFAccessTokenCommandHandler.java
index 903b5cf..46c8062 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/InvalidateTFAccessTokenCommandHandler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/InvalidateTFAccessTokenCommandHandler.java
@@ -43,13 +43,13 @@ import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
 import org.apache.fineract.infrastructure.security.service.TwoFactorService;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 @Service
 @CommandType(entity = "TWOFACTOR_ACCESSTOKEN", action = "INVALIDATE")
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class InvalidateTFAccessTokenCommandHandler implements 
NewCommandSourceHandler {
 
     private final TwoFactorService twoFactorService;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/UpdateTwoFactorConfigCommandHandler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/UpdateTwoFactorConfigCommandHandler.java
index 58b027b..d103315 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/UpdateTwoFactorConfigCommandHandler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/command/UpdateTwoFactorConfigCommandHandler.java
@@ -27,13 +27,13 @@ import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuild
 import 
org.apache.fineract.infrastructure.security.data.TwoFactorConfigurationValidator;
 import 
org.apache.fineract.infrastructure.security.service.TwoFactorConfigurationService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 @Service
 @CommandType(entity = "TWOFACTOR_CONFIGURATION", action = "UPDATE")
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class UpdateTwoFactorConfigCommandHandler implements 
NewCommandSourceHandler {
 
     private final TwoFactorConfigurationService configurationService;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/data/TwoFactorConfigurationValidator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/data/TwoFactorConfigurationValidator.java
index bea4599..6888a7e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/data/TwoFactorConfigurationValidator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/data/TwoFactorConfigurationValidator.java
@@ -32,11 +32,11 @@ import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
 import 
org.apache.fineract.infrastructure.security.constants.TwoFactorConfigurationConstants;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 
 @Component
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class TwoFactorConfigurationValidator {
 
     private final FromJsonHelper fromJsonHelper;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/OTPRequestRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/OTPRequestRepository.java
index 031ac0f..eaf3f43 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/OTPRequestRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/OTPRequestRepository.java
@@ -21,12 +21,12 @@ package org.apache.fineract.infrastructure.security.domain;
 import java.util.concurrent.ConcurrentHashMap;
 import org.apache.fineract.infrastructure.security.data.OTPRequest;
 import org.apache.fineract.useradministration.domain.AppUser;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Repository;
 import org.springframework.util.Assert;
 
 @Repository
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 @SuppressWarnings({ "MemberName" })
 public class OTPRequestRepository {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessTokenRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessTokenRepository.java
index b840eae..aaed99f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessTokenRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TFAccessTokenRepository.java
@@ -19,11 +19,11 @@
 package org.apache.fineract.infrastructure.security.domain;
 
 import org.apache.fineract.useradministration.domain.AppUser;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public interface TFAccessTokenRepository extends JpaRepository<TFAccessToken, 
Long>, JpaSpecificationExecutor<TFAccessToken> {
 
     TFAccessToken findByUserAndToken(AppUser user, String token);
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TwoFactorConfigurationRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TwoFactorConfigurationRepository.java
index 508e9a8..9692d39 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TwoFactorConfigurationRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/domain/TwoFactorConfigurationRepository.java
@@ -19,11 +19,11 @@
 package org.apache.fineract.infrastructure.security.domain;
 
 import java.util.List;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public interface TwoFactorConfigurationRepository
         extends JpaRepository<TwoFactorConfiguration, Long>, 
JpaSpecificationExecutor<TwoFactorConfiguration> {
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/InsecureTwoFactorAuthenticationFilter.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/InsecureTwoFactorAuthenticationFilter.java
index 64e40b8..0de5651 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/InsecureTwoFactorAuthenticationFilter.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/InsecureTwoFactorAuthenticationFilter.java
@@ -27,7 +27,7 @@ import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import 
org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
@@ -43,7 +43,7 @@ import org.springframework.stereotype.Service;
  * This filter adds 'TWOFACTOR_AUTHENTICATED' authority to every authenticated 
platform user.
  */
 @Service
-@Profile("!twofactor")
+@ConditionalOnProperty(name = "fineract.security.2fa.enabled", havingValue = 
"false")
 public class InsecureTwoFactorAuthenticationFilter extends 
TwoFactorAuthenticationFilter {
 
     public InsecureTwoFactorAuthenticationFilter() {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
index b97c3b0..c29fbdb 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
@@ -38,7 +38,7 @@ import org.apache.fineract.useradministration.domain.AppUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.authentication.BadCredentialsException;
 import org.springframework.security.core.Authentication;
@@ -59,7 +59,7 @@ import 
org.springframework.security.web.authentication.www.BasicAuthenticationFi
  * If multi-tenant and basic auth credentials are invalid, a http error 
response is returned.
  */
 
-@Profile("basicauth")
+@ConditionalOnProperty("fineract.security.basicauth.enabled")
 public class TenantAwareBasicAuthenticationFilter extends 
BasicAuthenticationFilter {
 
     private static boolean firstRequestProcessed = false;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareTenantIdentifierFilter.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareTenantIdentifierFilter.java
index bbc23de..0638c73 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareTenantIdentifierFilter.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareTenantIdentifierFilter.java
@@ -38,7 +38,7 @@ import 
org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetail
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Service;
 import org.springframework.web.filter.GenericFilterBean;
@@ -55,7 +55,7 @@ import org.springframework.web.filter.GenericFilterBean;
  * Used to support Oauth2 authentication and the service is loaded only when 
"oauth" profile is active.
  */
 @Service
-@Profile("oauth")
+@ConditionalOnProperty("fineract.security.oauth.enabled")
 public class TenantAwareTenantIdentifierFilter extends GenericFilterBean {
 
     private static boolean firstRequestProcessed = false;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TwoFactorAuthenticationFilter.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TwoFactorAuthenticationFilter.java
index 14dff4b..a5ae91e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TwoFactorAuthenticationFilter.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TwoFactorAuthenticationFilter.java
@@ -34,7 +34,7 @@ import 
org.apache.fineract.infrastructure.security.domain.TFAccessToken;
 import org.apache.fineract.infrastructure.security.service.TwoFactorService;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import 
org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.GrantedAuthority;
@@ -57,7 +57,7 @@ import org.springframework.web.filter.GenericFilterBean;
  * authority regardless of the value of the 'Fineract-Platform-TFA-Token' 
header.
  */
 @Service
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class TwoFactorAuthenticationFilter extends GenericFilterBean {
 
     private final TwoFactorService twoFactorService;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorConfigurationServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorConfigurationServiceImpl.java
index 31babfc..a01eaf8 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorConfigurationServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorConfigurationServiceImpl.java
@@ -36,13 +36,13 @@ import 
org.apache.fineract.infrastructure.security.domain.TwoFactorConfiguration
 import 
org.apache.fineract.infrastructure.security.domain.TwoFactorConfigurationRepository;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.Cacheable;
-import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
 @Service
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class TwoFactorConfigurationServiceImpl implements 
TwoFactorConfigurationService {
 
     private static final String DEFAULT_EMAIL_SUBJECT = "Fineract Two-Factor 
Authentication Token";
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorServiceImpl.java
index 8132d68..0134950 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorServiceImpl.java
@@ -39,14 +39,14 @@ import 
org.apache.fineract.infrastructure.sms.domain.SmsMessageRepository;
 import 
org.apache.fineract.infrastructure.sms.scheduler.SmsMessageScheduledJobService;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.cache.annotation.CachePut;
 import org.springframework.cache.annotation.Cacheable;
-import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
 
 @Service
-@Profile("twofactor")
+@ConditionalOnProperty("fineract.security.2fa.enabled")
 public class TwoFactorServiceImpl implements TwoFactorService {
 
     private final AccessTokenGenerationService accessTokenGenerationService;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorUtils.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorUtils.java
deleted file mode 100644
index ee435db..0000000
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/service/TwoFactorUtils.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.fineract.infrastructure.security.service;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
-import org.springframework.stereotype.Component;
-
-@Component
-public class TwoFactorUtils {
-
-    private static final String TWO_FACTOR_PROFILE_NAME = "twofactor";
-
-    private final Environment environment;
-
-    @Autowired
-    public TwoFactorUtils(Environment environment) {
-        this.environment = environment;
-    }
-
-    public boolean isTwoFactorAuthEnabled() {
-        for (final String profile : this.environment.getActiveProfiles()) {
-            if (TWO_FACTOR_PROFILE_NAME.equals(profile)) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
index 371d72c..cbdd50c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
@@ -31,13 +31,13 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import 
org.apache.fineract.infrastructure.security.api.AuthenticationApiResource;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
 @Component
 @Scope("singleton")
-@Profile("basicauth")
+@ConditionalOnProperty("fineract.security.basicauth.enabled")
 @Path("/self/authentication")
 @Tag(name = "Self Authentication", description = "Authenticates the 
credentials provided and returns the set roles and permissions allowed")
 public class SelfAuthenticationApiResource {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
index 2104cdb..bbacd50 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
@@ -30,13 +30,13 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import org.apache.fineract.infrastructure.security.api.UserDetailsApiResource;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Profile;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
 @Path("/self/userdetails")
 @Component
-@Profile("oauth")
+@ConditionalOnProperty("fineract.security.oauth.enabled")
 @Scope("singleton")
 
 @Tag(name = "Self User Details", description = "")
diff --git 
a/fineract-provider/properties/oauth/twofactor/application.properties 
b/fineract-provider/src/main/resources/application.properties
similarity index 78%
rename from fineract-provider/properties/oauth/twofactor/application.properties
rename to fineract-provider/src/main/resources/application.properties
index 3a2e01d..b4e3949 100644
--- a/fineract-provider/properties/oauth/twofactor/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -17,8 +17,10 @@
 # under the License.
 #
 
-spring.profiles.default=basicauth
-spring.profiles.active=oauth,twofactor
+fineract.security.basicauth.enabled=${FINERACT_SECURITY_BASICAUTH_ENABLED:true}
+fineract.security.oauth.enabled=${FINERACT_SECURITY_OAUTH_ENABLED:false}
+fineract.security.2fa.enabled=${FINERACT_SECURITY_2FA_ENABLED:false}
+
 management.health.jms.enabled=false
 
 # FINERACT 1296
@@ -34,4 +36,4 @@ management.endpoints.web.exposure.include=health,info
 server.forward-headers-strategy=framework
 
 # OAuth authorisation server endpoint
-spring.security.oauth2.resourceserver.jwt.issuer-uri: 
http://localhost:9000/auth/realms/fineract
+spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:9000/auth/realms/fineract
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/commands/provider/CommandHandlerProviderTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/commands/provider/CommandHandlerProviderTest.java
index 30baef9..2f776bc 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/commands/provider/CommandHandlerProviderTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/commands/provider/CommandHandlerProviderTest.java
@@ -29,14 +29,14 @@ import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.springframework.test.context.web.WebAppConfiguration;
 
 @ExtendWith(SpringExtension.class)
+@TestPropertySource("classpath:application-test.properties")
 @WebAppConfiguration
-@ActiveProfiles("basicauth")
 @ContextConfiguration(classes = 
TestsWithoutDatabaseAndNoJobsConfiguration.class)
 public class CommandHandlerProviderTest {
 
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/SpringConfigurationTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/SpringConfigurationTest.java
index a6d23e4..7a2627f 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/SpringConfigurationTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/SpringConfigurationTest.java
@@ -20,8 +20,8 @@ package 
org.apache.fineract.infrastructure.configuration.spring;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.test.context.ActiveProfiles;
 import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.springframework.test.context.web.WebAppConfiguration;
 
@@ -34,8 +34,8 @@ import 
org.springframework.test.context.web.WebAppConfiguration;
  * sufficient (as long as the TestsWithoutDatabaseAndNoJobsConfiguration used 
extends AbstractApplicationConfiguration).
  */
 @ExtendWith(SpringExtension.class)
+@TestPropertySource("classpath:application-test.properties")
 @WebAppConfiguration
-@ActiveProfiles("basicauth")
 @ContextConfiguration(classes = 
TestsWithoutDatabaseAndNoJobsConfiguration.class)
 public class SpringConfigurationTest {
 
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/TestsWithoutDatabaseAndNoJobsConfiguration.java
 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/TestsWithoutDatabaseAndNoJobsConfiguration.java
index 4ce3cb8..1f51900 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/TestsWithoutDatabaseAndNoJobsConfiguration.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/configuration/spring/TestsWithoutDatabaseAndNoJobsConfiguration.java
@@ -24,6 +24,9 @@ import 
org.apache.fineract.infrastructure.core.service.TenantDatabaseUpgradeServ
 import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
 import org.mockito.Mockito;
 import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
 
 /**
  * Spring @Configuration which does not require a running database. It also 
does not load any job configuration (as they
@@ -65,4 +68,10 @@ public class TestsWithoutDatabaseAndNoJobsConfiguration 
extends AbstractApplicat
         DataSource mockDataSource = Mockito.mock(DataSource.class, 
Mockito.RETURNS_MOCKS);
         return mockDataSource;
     }
+
+    @Bean
+    @Primary
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
 }
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/AbstractSpringBootWithMariaDB4jIntegrationTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/AbstractSpringBootWithMariaDB4jIntegrationTest.java
index 39288cf..4ee62bc 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/AbstractSpringBootWithMariaDB4jIntegrationTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/core/boot/tests/AbstractSpringBootWithMariaDB4jIntegrationTest.java
@@ -21,14 +21,14 @@ package org.apache.fineract.infrastructure.core.boot.tests;
 import org.apache.fineract.ServerWithMariaDB4jApplication;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.springframework.test.context.web.WebAppConfiguration;
 
 @ExtendWith(SpringExtension.class)
 @SpringBootTest(classes = ServerWithMariaDB4jApplication.Configuration.class)
+@TestPropertySource("classpath:application-test.properties")
 @WebAppConfiguration
-@ActiveProfiles("basicauth")
 public abstract class AbstractSpringBootWithMariaDB4jIntegrationTest {
 
     // do NOT put any helper methods here!
diff --git 
a/fineract-provider/properties/basicauth/twofactor/application.properties 
b/fineract-provider/src/test/resources/application-test.properties
similarity index 90%
rename from 
fineract-provider/properties/basicauth/twofactor/application.properties
rename to fineract-provider/src/test/resources/application-test.properties
index 03788ec..30b680b 100644
--- a/fineract-provider/properties/basicauth/twofactor/application.properties
+++ b/fineract-provider/src/test/resources/application-test.properties
@@ -17,8 +17,10 @@
 # under the License.
 #
 
-spring.profiles.default=basicauth
-spring.profiles.active=basicauth,twofactor
+fineract.security.basicauth.enabled=true
+fineract.security.oauth.enabled=false
+fineract.security.2fa.enabled=false
+
 management.health.jms.enabled=false
 
 # FINERACT 1296
diff --git a/oauth2-tests/build.gradle b/oauth2-tests/build.gradle
index f704877..fd20ac4 100644
--- a/oauth2-tests/build.gradle
+++ b/oauth2-tests/build.gradle
@@ -45,7 +45,7 @@ cargo {
         }
         startStopTimeout = 240000
         containerProperties {
-            property 'cargo.start.jvmargs', '-Dspring.profiles.active=oauth'
+            property 'cargo.start.jvmargs', 
'-Dfineract.security.basicauth.enabled=false 
-Dfineract.security.oauth.enabled=true -Dfineract.security.2fa.enabled=false'
             property 'cargo.tomcat.connector.keystoreFile', 
file("$rootDir/fineract-provider/src/main/resources/keystore.jks")
             property 'cargo.tomcat.connector.keystorePass', 'openmf'
             property 'cargo.tomcat.httpSecure', true
diff --git a/twofactor-tests/build.gradle b/twofactor-tests/build.gradle
index aa91bb0..e5c45c2 100644
--- a/twofactor-tests/build.gradle
+++ b/twofactor-tests/build.gradle
@@ -45,7 +45,7 @@ cargo {
         }
         startStopTimeout = 240000
         containerProperties {
-            property 'cargo.start.jvmargs', 
'-Dspring.profiles.active=twofactor,basicauth'
+            property 'cargo.start.jvmargs', 
'-Dfineract.security.basicauth.enabled=true 
-Dfineract.security.oauth.enabled=false -Dfineract.security.2fa.enabled=true'
             property 'cargo.tomcat.connector.keystoreFile', 
file("$rootDir/fineract-provider/src/main/resources/keystore.jks")
             property 'cargo.tomcat.connector.keystorePass', 'openmf'
             property 'cargo.tomcat.httpSecure', true
diff --git 
a/twofactor-tests/src/test/java/org/apache/fineract/twofactortests/TwoFactorAuthenticationTest.java
 
b/twofactor-tests/src/test/java/org/apache/fineract/twofactortests/TwoFactorAuthenticationTest.java
index e3703b4..8269298 100644
--- 
a/twofactor-tests/src/test/java/org/apache/fineract/twofactortests/TwoFactorAuthenticationTest.java
+++ 
b/twofactor-tests/src/test/java/org/apache/fineract/twofactortests/TwoFactorAuthenticationTest.java
@@ -111,7 +111,7 @@ public class TwoFactorAuthenticationTest {
                 
.log().ifError().when().post("/fineract-provider/api/v1/authentication?" + 
TENANT_IDENTIFIER).asString();
         assertFalse(StringUtils.isBlank(json));
         Boolean key = 
JsonPath.with(json).get("isTwoFactorAuthenticationRequired");
-        assertEquals(key, true);
+        assertEquals(true, key);
     }
 
     @Test

Reply via email to