FINERACT-1724: EclipseLink upgrade fixes + Spring Security chain fixes
This commit is contained in:
committed by
Arnold Gálovics
parent
abb5d4abb5
commit
a7d5f834d5
+1
-1
@@ -55,7 +55,7 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath 'com.bmuschko:gradle-cargo-plugin:2.9.0'
|
||||
classpath 'org.eclipse.persistence:eclipselink:4.0.1'
|
||||
classpath 'org.eclipse.persistence:eclipselink:4.0.0'
|
||||
classpath 'jakarta.ws.rs:jakarta.ws.rs-api:3.1.0'
|
||||
classpath 'com.google.cloud.tools:jib-layer-filter-extension-gradle:0.3.0'
|
||||
classpath 'org.apache.commons:commons-lang3:3.12.0'
|
||||
|
||||
@@ -50,7 +50,7 @@ dependencyManagement {
|
||||
dependency 'org.codehaus.janino:janino:3.1.9'
|
||||
|
||||
|
||||
dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:4.0.1'
|
||||
dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:4.0.0'
|
||||
dependency 'com.google.guava:guava:31.1-jre'
|
||||
dependency 'com.google.code.gson:gson:2.10.1'
|
||||
dependency 'com.google.truth:truth:1.1.3'
|
||||
@@ -64,6 +64,7 @@ dependencyManagement {
|
||||
dependency 'com.github.librepdf:openpdf:1.3.30'
|
||||
dependency ('org.mnode.ical4j:ical4j:3.2.11') {
|
||||
exclude 'com.sun.mail:javax.mail'
|
||||
exclude 'org.codehaus.groovy:groovy'
|
||||
}
|
||||
dependency 'org.apache.commons:commons-csv:1.10.0'
|
||||
dependency 'org.quartz-scheduler:quartz:2.3.2'
|
||||
@@ -233,6 +234,8 @@ dependencyManagement {
|
||||
entry 'json-path'
|
||||
entry 'xml-path'
|
||||
}
|
||||
dependency 'org.apache.groovy:groovy-xml:4.0.6'
|
||||
dependency 'org.apache.groovy:groovy-json:4.0.6'
|
||||
|
||||
dependency 'org.mapstruct:mapstruct:1.5.4.Final'
|
||||
dependency 'org.mapstruct:mapstruct-processor:1.5.4.Final'
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.acme.fineract.event.starter.AcmeEventAutoConfiguration
|
||||
+1
@@ -0,0 +1 @@
|
||||
com.acme.fineract.event.starter.AcmeEventAutoConfiguration
|
||||
@@ -1,2 +0,0 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.acme.fineract.loan.starter.AcmeLoanAutoConfiguration
|
||||
+1
@@ -0,0 +1 @@
|
||||
com.acme.fineract.loan.starter.AcmeLoanAutoConfiguration
|
||||
-1
@@ -1,2 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.acme.fineract.portfolio.note.starter.AcmeNoteAutoConfiguration
|
||||
+1
@@ -21,6 +21,7 @@ package org.apache.fineract.infrastructure.core.boot;
|
||||
public final class FineractProfiles {
|
||||
|
||||
public static final String LIQUIBASE_ONLY = "liquibase-only";
|
||||
public static final String DIAGNOSTICS = "diagnostics";
|
||||
|
||||
private FineractProfiles() {}
|
||||
}
|
||||
|
||||
+36
@@ -57,6 +57,7 @@ public class FineractProperties {
|
||||
|
||||
private FineractQueryProperties query;
|
||||
private FineractApiProperties api;
|
||||
private FineractSecurityProperties security;
|
||||
|
||||
private FineractNotificationProperties notification;
|
||||
|
||||
@@ -352,6 +353,41 @@ public class FineractProperties {
|
||||
private boolean errorNotFoundFail;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class FineractSecurityProperties {
|
||||
|
||||
private FineractSecurityBasicAuth basicauth;
|
||||
private FineractSecurityTwoFactorAuth twoFactor;
|
||||
private FineractSecurityOAuth oauth;
|
||||
|
||||
public void set2fa(FineractSecurityTwoFactorAuth twoFactor) {
|
||||
this.twoFactor = twoFactor;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class FineractSecurityBasicAuth {
|
||||
|
||||
private boolean enabled;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class FineractSecurityTwoFactorAuth {
|
||||
|
||||
private boolean enabled;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class FineractSecurityOAuth {
|
||||
|
||||
private boolean enabled;
|
||||
}
|
||||
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class FineractTransactionProcessorItemProperties {
|
||||
|
||||
+43
-28
@@ -25,15 +25,21 @@ import static org.springframework.security.authorization.AuthorityAuthorizationM
|
||||
import static org.springframework.security.authorization.AuthorizationManagers.allOf;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
|
||||
import org.apache.fineract.infrastructure.cache.service.CacheWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.exceptionmapper.OAuth2ExceptionEntryPoint;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
|
||||
import org.apache.fineract.infrastructure.security.data.PlatformRequestLog;
|
||||
import org.apache.fineract.infrastructure.security.filter.TenantAwareTenantIdentifierFilter;
|
||||
import org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticationFilter;
|
||||
import org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
|
||||
import org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
|
||||
import org.apache.fineract.infrastructure.security.service.TwoFactorService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
@@ -55,25 +61,36 @@ import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty("fineract.security.oauth.enabled")
|
||||
@EnableMethodSecurity
|
||||
public class OAuth2SecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private TwoFactorAuthenticationFilter twoFactorAuthenticationFilter;
|
||||
|
||||
@Autowired
|
||||
private TenantAwareTenantIdentifierFilter tenantAwareTenantIdentifierFilter;
|
||||
|
||||
@Autowired
|
||||
private TenantAwareJpaPlatformUserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private ServerProperties serverProperties;
|
||||
|
||||
private static final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
@Autowired
|
||||
private TwoFactorService twoFactorService;
|
||||
|
||||
@Autowired
|
||||
private BasicAuthTenantDetailsService basicAuthTenantDetailsService;
|
||||
|
||||
@Autowired
|
||||
private ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
private CacheWritePlatformService cacheWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
private BusinessDateReadPlatformService businessDateReadPlatformService;
|
||||
|
||||
private static final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain authorizationFilterChain(HttpSecurity http) throws Exception {
|
||||
@@ -90,26 +107,40 @@ public class OAuth2SecurityConfig {
|
||||
.requestMatchers("/api/*/twofactor").fullyAuthenticated() //
|
||||
.requestMatchers("/api/**").access(allOf(fullyAuthenticated(), hasAuthority("TWOFACTOR_AUTHENTICATED"), selfServiceUserAuthManager())); //
|
||||
});
|
||||
|
||||
if (serverProperties.getSsl().isEnabled()) {
|
||||
http.requiresChannel(channel -> channel.requestMatchers("/api/**").requiresSecure());
|
||||
}
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain FilterChain(HttpSecurity http) throws Exception {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http //
|
||||
.csrf((csrf) -> csrf.disable()) // NOSONAR only creating a service that is used by non-browser clients
|
||||
.exceptionHandling((ehc) -> ehc.authenticationEntryPoint(new OAuth2ExceptionEntryPoint()))
|
||||
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(authenticationConverter()))
|
||||
.authenticationEntryPoint(new OAuth2ExceptionEntryPoint())) //
|
||||
.sessionManagement((smc) -> smc.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //
|
||||
.addFilterAfter(tenantAwareTenantIdentifierFilter, SecurityContextHolderFilter.class) //
|
||||
.addFilterAfter(twoFactorAuthenticationFilter, BasicAuthenticationFilter.class); //
|
||||
.addFilterAfter(tenantAwareTenantIdentifierFilter(), SecurityContextHolderFilter.class) //
|
||||
.addFilterAfter(twoFactorAuthenticationFilter(), BasicAuthenticationFilter.class); //
|
||||
|
||||
if (serverProperties.getSsl().isEnabled()) {
|
||||
http.requiresChannel(channel -> channel.requestMatchers("/api/**").requiresSecure());
|
||||
}
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
public TenantAwareTenantIdentifierFilter tenantAwareTenantIdentifierFilter() {
|
||||
return new TenantAwareTenantIdentifierFilter(basicAuthTenantDetailsService, toApiJsonSerializer, configurationDomainService, cacheWritePlatformService, businessDateReadPlatformService);
|
||||
}
|
||||
|
||||
public TwoFactorAuthenticationFilter twoFactorAuthenticationFilter() {
|
||||
return new TwoFactorAuthenticationFilter(twoFactorService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
|
||||
@@ -127,20 +158,4 @@ public class OAuth2SecurityConfig {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TenantAwareTenantIdentifierFilter> tenantAwareTenantIdentifierFilterRegistration() throws Exception {
|
||||
FilterRegistrationBean<TenantAwareTenantIdentifierFilter> registration = new FilterRegistrationBean<TenantAwareTenantIdentifierFilter>(
|
||||
tenantAwareTenantIdentifierFilter);
|
||||
registration.setEnabled(false);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TwoFactorAuthenticationFilter> twoFactorAuthenticationFilterRegistration() {
|
||||
FilterRegistrationBean<TwoFactorAuthenticationFilter> registration = new FilterRegistrationBean<TwoFactorAuthenticationFilter>(
|
||||
twoFactorAuthenticationFilter);
|
||||
registration.setEnabled(false);
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
|
||||
+122
-45
@@ -23,17 +23,38 @@ import static org.springframework.security.authorization.AuthenticatedAuthorizat
|
||||
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasAuthority;
|
||||
import static org.springframework.security.authorization.AuthorizationManagers.allOf;
|
||||
|
||||
import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl;
|
||||
import org.apache.fineract.cob.service.LoanAccountLockService;
|
||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||
import org.apache.fineract.commands.service.CommandSourceService;
|
||||
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
|
||||
import org.apache.fineract.infrastructure.cache.service.CacheWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
||||
import org.apache.fineract.infrastructure.core.filters.CorrelationHeaderFilter;
|
||||
import org.apache.fineract.infrastructure.core.filters.IdempotencyStoreFilter;
|
||||
import org.apache.fineract.infrastructure.core.filters.RequestResponseFilter;
|
||||
import org.apache.fineract.infrastructure.core.filters.ResponseCorsFilter;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.MDCWrapper;
|
||||
import org.apache.fineract.infrastructure.instancemode.filter.FineractInstanceModeApiFilter;
|
||||
import org.apache.fineract.infrastructure.jobs.filter.LoanCOBApiFilter;
|
||||
import org.apache.fineract.infrastructure.security.data.PlatformRequestLog;
|
||||
import org.apache.fineract.infrastructure.security.filter.InsecureTwoFactorAuthenticationFilter;
|
||||
import org.apache.fineract.infrastructure.security.filter.TenantAwareBasicAuthenticationFilter;
|
||||
import org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticationFilter;
|
||||
import org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
|
||||
import org.apache.fineract.infrastructure.security.service.TwoFactorService;
|
||||
import org.apache.fineract.notification.service.UserNotificationService;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.GLIMAccountInfoRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
@@ -48,25 +69,19 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty("fineract.security.basicauth.enabled")
|
||||
@EnableMethodSecurity
|
||||
public class SecurityConfig {
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private TenantAwareJpaPlatformUserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private TwoFactorAuthenticationFilter twoFactorAuthenticationFilter;
|
||||
|
||||
@Autowired
|
||||
private FineractInstanceModeApiFilter fineractInstanceModeApiFilter;
|
||||
@Autowired
|
||||
private LoanCOBApiFilter loanCOBApiFilter;
|
||||
|
||||
@Autowired
|
||||
private FineractProperties fineractProperties;
|
||||
|
||||
@@ -74,8 +89,40 @@ public class SecurityConfig {
|
||||
private ServerProperties serverProperties;
|
||||
|
||||
@Autowired
|
||||
private IdempotencyStoreFilter idempotencyStoreFilter;
|
||||
private ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer;
|
||||
@Autowired
|
||||
private ConfigurationDomainService configurationDomainService;
|
||||
@Autowired
|
||||
private CacheWritePlatformService cacheWritePlatformService;
|
||||
@Autowired
|
||||
private UserNotificationService userNotificationService;
|
||||
@Autowired
|
||||
private BasicAuthTenantDetailsService basicAuthTenantDetailsService;
|
||||
@Autowired
|
||||
private BusinessDateReadPlatformService businessDateReadPlatformService;
|
||||
@Autowired
|
||||
private MDCWrapper mdcWrapper;
|
||||
@Autowired
|
||||
private CommandSourceRepository commandSourceRepository;
|
||||
@Autowired
|
||||
private CommandSourceService commandSourceService;
|
||||
@Autowired
|
||||
private FineractRequestContextHolder fineractRequestContextHolder;
|
||||
|
||||
@Autowired
|
||||
private GLIMAccountInfoRepository glimAccountInfoRepository;
|
||||
@Autowired
|
||||
private LoanAccountLockService loanAccountLockService;
|
||||
@Autowired
|
||||
private PlatformSecurityContext context;
|
||||
@Autowired
|
||||
private InlineLoanCOBExecutorServiceImpl inlineLoanCOBExecutorService;
|
||||
@Autowired
|
||||
private LoanRepository loanRepository;
|
||||
@Autowired
|
||||
private LoanRescheduleRequestRepository loanRescheduleRequestRepository;
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain authorizationFilterChain(HttpSecurity http) throws Exception {
|
||||
@@ -93,20 +140,7 @@ public class SecurityConfig {
|
||||
.requestMatchers("/api/*/twofactor").fullyAuthenticated() //
|
||||
.requestMatchers("/api/**").access(allOf(fullyAuthenticated(), hasAuthority("TWOFACTOR_AUTHENTICATED"))); //
|
||||
}) //
|
||||
.httpBasic((httpBasic) -> httpBasic.authenticationEntryPoint(basicAuthenticationEntryPoint())); //
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http //
|
||||
.csrf((csrf) -> csrf.disable()) // NOSONAR only creating a service that is used by non-browser clients
|
||||
.sessionManagement((smc) -> smc.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //
|
||||
.addFilterAfter(fineractInstanceModeApiFilter, SecurityContextHolderFilter.class) //
|
||||
.addFilterAfter(tenantAwareBasicAuthenticationFilter(), FineractInstanceModeApiFilter.class) //
|
||||
.addFilterAfter(twoFactorAuthenticationFilter, BasicAuthenticationFilter.class) //
|
||||
.addFilterAfter(loanCOBApiFilter, InsecureTwoFactorAuthenticationFilter.class) //
|
||||
.addFilterBefore(idempotencyStoreFilter, ExceptionTranslationFilter.class); //
|
||||
.httpBasic((httpBasic) -> httpBasic.authenticationEntryPoint(basicAuthenticationEntryPoint()));
|
||||
|
||||
if (serverProperties.getSsl().isEnabled()) {
|
||||
http.requiresChannel(channel -> channel.requestMatchers("/api/**").requiresSecure());
|
||||
@@ -115,8 +149,68 @@ public class SecurityConfig {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http //
|
||||
.csrf((csrf) -> csrf.disable()) // NOSONAR only creating a service that is used by non-browser clients
|
||||
.securityContext((securityContext) -> securityContext.requireExplicitSave(false))
|
||||
.sessionManagement((smc) -> smc.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //
|
||||
.addFilterAfter(requestResponseFilter(), ExceptionTranslationFilter.class)
|
||||
.addFilterAfter(correlationHeaderFilter(), RequestResponseFilter.class)
|
||||
.addFilterAfter(responseCorsFilter(), CorrelationHeaderFilter.class) //
|
||||
.addFilterAfter(fineractInstanceModeApiFilter(), ResponseCorsFilter.class) //
|
||||
.addFilterAfter(tenantAwareBasicAuthenticationFilter(), FineractInstanceModeApiFilter.class) //
|
||||
.addFilterAfter(loanCOBApiFilter(), TenantAwareBasicAuthenticationFilter.class) //
|
||||
.addFilterAfter(idempotencyStoreFilter(), LoanCOBApiFilter.class); //
|
||||
|
||||
if (fineractProperties.getSecurity().getTwoFactor().isEnabled()) {
|
||||
http.addFilterAfter(twoFactorAuthenticationFilter(), FineractInstanceModeApiFilter.class);
|
||||
} else {
|
||||
http.addFilterAfter(insecureTwoFactorAuthenticationFilter(), FineractInstanceModeApiFilter.class);
|
||||
}
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
public RequestResponseFilter requestResponseFilter() {
|
||||
return new RequestResponseFilter();
|
||||
}
|
||||
|
||||
public LoanCOBApiFilter loanCOBApiFilter() {
|
||||
return new LoanCOBApiFilter(glimAccountInfoRepository, loanAccountLockService, context, inlineLoanCOBExecutorService, loanRepository, fineractProperties, loanRescheduleRequestRepository, transactionManager);
|
||||
}
|
||||
|
||||
public TwoFactorAuthenticationFilter twoFactorAuthenticationFilter() {
|
||||
TwoFactorService twoFactorService = applicationContext.getBean(TwoFactorService.class);
|
||||
return new TwoFactorAuthenticationFilter(twoFactorService);
|
||||
}
|
||||
|
||||
public InsecureTwoFactorAuthenticationFilter insecureTwoFactorAuthenticationFilter() {
|
||||
return new InsecureTwoFactorAuthenticationFilter();
|
||||
}
|
||||
|
||||
public FineractInstanceModeApiFilter fineractInstanceModeApiFilter() {
|
||||
return new FineractInstanceModeApiFilter(fineractProperties);
|
||||
}
|
||||
|
||||
public IdempotencyStoreFilter idempotencyStoreFilter() {
|
||||
return new IdempotencyStoreFilter(commandSourceRepository, commandSourceService, fineractProperties, fineractRequestContextHolder);
|
||||
}
|
||||
|
||||
public CorrelationHeaderFilter correlationHeaderFilter() {
|
||||
return new CorrelationHeaderFilter(fineractProperties, mdcWrapper);
|
||||
}
|
||||
|
||||
public ResponseCorsFilter responseCorsFilter() {
|
||||
return new ResponseCorsFilter();
|
||||
}
|
||||
|
||||
public TenantAwareBasicAuthenticationFilter tenantAwareBasicAuthenticationFilter() throws Exception {
|
||||
return new TenantAwareBasicAuthenticationFilter(authenticationManagerBean(), basicAuthenticationEntryPoint());
|
||||
TenantAwareBasicAuthenticationFilter filter = new TenantAwareBasicAuthenticationFilter(authenticationManagerBean(), basicAuthenticationEntryPoint(),
|
||||
toApiJsonSerializer, configurationDomainService, cacheWritePlatformService,
|
||||
userNotificationService, basicAuthTenantDetailsService,
|
||||
businessDateReadPlatformService);
|
||||
filter.setRequestMatcher(AntPathRequestMatcher.antMatcher("/api/**"));
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -145,21 +239,4 @@ public class SecurityConfig {
|
||||
providerManager.setEraseCredentialsAfterAuthentication(false);
|
||||
return providerManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TenantAwareBasicAuthenticationFilter> tenantAwareBasicAuthenticationFilterRegistration()
|
||||
throws Exception {
|
||||
FilterRegistrationBean<TenantAwareBasicAuthenticationFilter> registration = new FilterRegistrationBean<TenantAwareBasicAuthenticationFilter>(
|
||||
tenantAwareBasicAuthenticationFilter());
|
||||
registration.setEnabled(false);
|
||||
return registration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TwoFactorAuthenticationFilter> twoFactorAuthenticationFilterRegistration() {
|
||||
FilterRegistrationBean<TwoFactorAuthenticationFilter> registration = new FilterRegistrationBean<TwoFactorAuthenticationFilter>(
|
||||
twoFactorAuthenticationFilter);
|
||||
registration.setEnabled(false);
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
|
||||
-36
@@ -1,36 +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.core.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConditionalOnClass(name = "org.apache.coyote.http11.Http11Nio2Protocol")
|
||||
public class TomcatConnectorCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableServletWebServerFactory factory) {
|
||||
((TomcatServletWebServerFactory) factory).setProtocol("org.apache.coyote.http11.Http11Nio2Protocol");
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -20,6 +20,7 @@ package org.apache.fineract.infrastructure.core.diagnostics.jpa;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
|
||||
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
|
||||
import org.eclipse.persistence.sessions.changesets.UnitOfWorkChangeSet;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -38,7 +39,7 @@ import org.springframework.stereotype.Component;
|
||||
* <br>
|
||||
* To enable this, run Fineract with the <b>diagnostics</b> profile.
|
||||
*/
|
||||
@Profile("diagnostics")
|
||||
@Profile(FineractProfiles.DIAGNOSTICS)
|
||||
@Component
|
||||
public class DiagnosticsEntityManager implements ApplicationContextAware {
|
||||
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.diagnostics.security;
|
||||
|
||||
import static java.lang.System.lineSeparator;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Profile(FineractProfiles.DIAGNOSTICS)
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityFilterChainDiagnostics implements InitializingBean {
|
||||
private final List<SecurityFilterChain> filterChains;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
filterChains.forEach(this::printFilterChain);
|
||||
}
|
||||
|
||||
private void printFilterChain(SecurityFilterChain filterChain) {
|
||||
if (filterChain instanceof DefaultSecurityFilterChain) {
|
||||
printDefaultFilterChain((DefaultSecurityFilterChain) filterChain);
|
||||
} else {
|
||||
printUnknownFilterChain(filterChain);
|
||||
}
|
||||
}
|
||||
|
||||
private void printDefaultFilterChain(DefaultSecurityFilterChain filterChain) {
|
||||
|
||||
log.info(
|
||||
"""
|
||||
|
||||
Filter chain matcher: %s
|
||||
Filters in order:
|
||||
%s
|
||||
""".formatted(filterChain.getRequestMatcher(), getFormattedFilters(filterChain)));
|
||||
}
|
||||
|
||||
private String getFormattedFilters(DefaultSecurityFilterChain filterChain) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
filterChain.getFilters().forEach(f -> {
|
||||
result.append("- ");
|
||||
result.append(f.getClass().getName());
|
||||
result.append(lineSeparator());
|
||||
});
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void printUnknownFilterChain(SecurityFilterChain filterChain) {
|
||||
log.info(
|
||||
"""
|
||||
Filter chain:
|
||||
%s
|
||||
""".formatted(filterChain));
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -19,23 +19,21 @@
|
||||
|
||||
package org.apache.fineract.infrastructure.core.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.service.MDCWrapper;
|
||||
import org.apache.fineract.infrastructure.security.utils.LogParameterEscapeUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CorrelationHeaderFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String CORRELATION_ID_KEY = "correlationId";
|
||||
|
||||
+3
-5
@@ -18,14 +18,14 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.mutable.Mutable;
|
||||
@@ -39,13 +39,11 @@ import org.apache.fineract.commands.service.SynchronousCommandProcessingService;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Component
|
||||
public class IdempotencyStoreFilter extends OncePerRequestFilter implements BatchFilter {
|
||||
|
||||
private final CommandSourceRepository commandSourceRepository;
|
||||
|
||||
+1
-3
@@ -19,19 +19,17 @@
|
||||
|
||||
package org.apache.fineract.infrastructure.core.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RequestResponseFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
|
||||
+14
-19
@@ -18,36 +18,31 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.filters;
|
||||
|
||||
import jakarta.ws.rs.container.ContainerRequestContext;
|
||||
import jakarta.ws.rs.container.ContainerResponseContext;
|
||||
import jakarta.ws.rs.container.ContainerResponseFilter;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Filter that returns a response with headers that allows for Cross-Origin Requests (CORs) to be performed against the
|
||||
* platform API.
|
||||
*/
|
||||
|
||||
@Provider
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class ResponseCorsFilter implements ContainerResponseFilter {
|
||||
public class ResponseCorsFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
public void filter(final ContainerRequestContext request, final ContainerResponseContext response) {
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
||||
|
||||
response.getHeaders().add("Access-Control-Allow-Origin", "*");
|
||||
// .header("Access-Control-Expose-Headers",
|
||||
// "Fineract-Platform-TenantId")
|
||||
response.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
||||
final String reqHead = request.getHeader("Access-Control-Request-Headers");
|
||||
|
||||
final String reqHead = request.getHeaders().getFirst("Access-Control-Request-Headers");
|
||||
|
||||
if (null != reqHead && StringUtils.hasText(reqHead)) {
|
||||
response.getHeaders().add("Access-Control-Allow-Headers", reqHead);
|
||||
if (StringUtils.hasText(reqHead)) {
|
||||
response.addHeader("Access-Control-Allow-Headers", reqHead);
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ApplicationPath("/api")
|
||||
public class JerseyConfig extends ResourceConfig {
|
||||
|
||||
|
||||
+3
-5
@@ -21,23 +21,21 @@ package org.apache.fineract.infrastructure.instancemode.filter;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.fineract.infrastructure.instancemode.filter.FineractInstanceModeApiFilter.ExceptionListItem.item;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.ws.rs.HttpMethod;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class FineractInstanceModeApiFilter extends OncePerRequestFilter {
|
||||
|
||||
|
||||
+4
-6
@@ -22,6 +22,10 @@ import static org.apache.fineract.batch.command.CommandStrategyUtils.isRelativeU
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.github.resilience4j.core.functions.Either;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -29,10 +33,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -57,13 +57,11 @@ import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanResch
|
||||
import org.apache.fineract.useradministration.exception.UnAuthenticatedUserException;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchRequestPreprocessor {
|
||||
|
||||
|
||||
+4
-8
@@ -18,16 +18,15 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.security.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
|
||||
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;
|
||||
@@ -35,15 +34,12 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* A dummy {@link TwoFactorAuthenticationFilter} filter used when 'twofactor' environment profile is not active.
|
||||
*
|
||||
* This filter adds 'TWOFACTOR_AUTHENTICATED' authority to every authenticated platform user.
|
||||
*/
|
||||
@Service
|
||||
@ConditionalOnProperty(name = "fineract.security.2fa.enabled", havingValue = "false")
|
||||
public class InsecureTwoFactorAuthenticationFilter extends TwoFactorAuthenticationFilter {
|
||||
|
||||
public InsecureTwoFactorAuthenticationFilter() {
|
||||
|
||||
+65
-68
@@ -18,13 +18,15 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.security.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.time.StopWatch;
|
||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||
import org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
|
||||
@@ -39,16 +41,14 @@ import org.apache.fineract.infrastructure.security.exception.InvalidTenantIdenti
|
||||
import org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
|
||||
import org.apache.fineract.notification.service.UserNotificationService;
|
||||
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.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* A customised version of spring security's {@link BasicAuthenticationFilter}.
|
||||
@@ -63,36 +63,32 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
|
||||
* If multi-tenant and basic auth credentials are invalid, a http error response is returned.
|
||||
*/
|
||||
|
||||
@ConditionalOnProperty("fineract.security.basicauth.enabled")
|
||||
@Slf4j
|
||||
public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFilter {
|
||||
|
||||
private static boolean firstRequestProcessed = false;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TenantAwareBasicAuthenticationFilter.class);
|
||||
|
||||
@Autowired
|
||||
private ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
private CacheWritePlatformService cacheWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
private UserNotificationService userNotificationService;
|
||||
|
||||
@Autowired
|
||||
private BasicAuthTenantDetailsService basicAuthTenantDetailsService;
|
||||
|
||||
@Autowired
|
||||
private BusinessDateReadPlatformService businessDateReadPlatformService;
|
||||
private final ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final CacheWritePlatformService cacheWritePlatformService;
|
||||
private final UserNotificationService userNotificationService;
|
||||
private final BasicAuthTenantDetailsService basicAuthTenantDetailsService;
|
||||
private final BusinessDateReadPlatformService businessDateReadPlatformService;
|
||||
|
||||
private final String tenantRequestHeader = "Fineract-Platform-TenantId";
|
||||
private final boolean exceptionIfHeaderMissing = true;
|
||||
|
||||
@Setter
|
||||
private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
|
||||
|
||||
public TenantAwareBasicAuthenticationFilter(final AuthenticationManager authenticationManager,
|
||||
final AuthenticationEntryPoint authenticationEntryPoint) {
|
||||
final AuthenticationEntryPoint authenticationEntryPoint, ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer, ConfigurationDomainService configurationDomainService, CacheWritePlatformService cacheWritePlatformService, UserNotificationService userNotificationService, BasicAuthTenantDetailsService basicAuthTenantDetailsService, BusinessDateReadPlatformService businessDateReadPlatformService) {
|
||||
super(authenticationManager, authenticationEntryPoint);
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.cacheWritePlatformService = cacheWritePlatformService;
|
||||
this.userNotificationService = userNotificationService;
|
||||
this.basicAuthTenantDetailsService = basicAuthTenantDetailsService;
|
||||
this.businessDateReadPlatformService = businessDateReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -108,48 +104,49 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
|
||||
// ignore to allow 'preflight' requests from AJAX applications
|
||||
// in different origin (domain name)
|
||||
} else {
|
||||
if (requestMatcher.matches(request)) {
|
||||
String tenantIdentifier = request.getHeader(this.tenantRequestHeader);
|
||||
|
||||
String tenantIdentifier = request.getHeader(this.tenantRequestHeader);
|
||||
|
||||
if (org.apache.commons.lang3.StringUtils.isBlank(tenantIdentifier)) {
|
||||
tenantIdentifier = request.getParameter("tenantIdentifier");
|
||||
}
|
||||
|
||||
if (tenantIdentifier == null && this.exceptionIfHeaderMissing) {
|
||||
throw new InvalidTenantIdentifierException("No tenant identifier found: Add request header of '"
|
||||
+ this.tenantRequestHeader + "' or add the parameter 'tenantIdentifier' to query string of request URL.");
|
||||
}
|
||||
|
||||
String pathInfo = request.getRequestURI();
|
||||
boolean isReportRequest = false;
|
||||
if (pathInfo != null && pathInfo.contains("report")) {
|
||||
isReportRequest = true;
|
||||
}
|
||||
final FineractPlatformTenant tenant = this.basicAuthTenantDetailsService.loadTenantById(tenantIdentifier, isReportRequest);
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
HashMap<BusinessDateType, LocalDate> businessDates = this.businessDateReadPlatformService.getBusinessDates();
|
||||
ThreadLocalContextUtil.setBusinessDates(businessDates);
|
||||
String authToken = request.getHeader("Authorization");
|
||||
|
||||
if (authToken != null && authToken.startsWith("Basic ")) {
|
||||
ThreadLocalContextUtil.setAuthToken(authToken.replaceFirst("Basic ", ""));
|
||||
}
|
||||
|
||||
if (!firstRequestProcessed) {
|
||||
final String baseUrl = request.getRequestURL().toString().replace(request.getPathInfo(), "/");
|
||||
System.setProperty("baseUrl", baseUrl);
|
||||
|
||||
final boolean ehcacheEnabled = this.configurationDomainService.isEhcacheEnabled();
|
||||
if (ehcacheEnabled) {
|
||||
this.cacheWritePlatformService.switchToCache(CacheType.SINGLE_NODE);
|
||||
} else {
|
||||
this.cacheWritePlatformService.switchToCache(CacheType.NO_CACHE);
|
||||
if (org.apache.commons.lang3.StringUtils.isBlank(tenantIdentifier)) {
|
||||
tenantIdentifier = request.getParameter("tenantIdentifier");
|
||||
}
|
||||
TenantAwareBasicAuthenticationFilter.firstRequestProcessed = true;
|
||||
}
|
||||
}
|
||||
|
||||
super.doFilterInternal(request, response, filterChain);
|
||||
if (tenantIdentifier == null && this.exceptionIfHeaderMissing) {
|
||||
throw new InvalidTenantIdentifierException("No tenant identifier found: Add request header of '"
|
||||
+ this.tenantRequestHeader + "' or add the parameter 'tenantIdentifier' to query string of request URL.");
|
||||
}
|
||||
|
||||
String pathInfo = request.getRequestURI();
|
||||
boolean isReportRequest = false;
|
||||
if (pathInfo != null && pathInfo.contains("report")) {
|
||||
isReportRequest = true;
|
||||
}
|
||||
final FineractPlatformTenant tenant = this.basicAuthTenantDetailsService.loadTenantById(tenantIdentifier, isReportRequest);
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
HashMap<BusinessDateType, LocalDate> businessDates = this.businessDateReadPlatformService.getBusinessDates();
|
||||
ThreadLocalContextUtil.setBusinessDates(businessDates);
|
||||
String authToken = request.getHeader("Authorization");
|
||||
|
||||
if (authToken != null && authToken.startsWith("Basic ")) {
|
||||
ThreadLocalContextUtil.setAuthToken(authToken.replaceFirst("Basic ", ""));
|
||||
}
|
||||
|
||||
if (!firstRequestProcessed) {
|
||||
final String baseUrl = request.getRequestURL().toString().replace(request.getPathInfo(), "/");
|
||||
System.setProperty("baseUrl", baseUrl);
|
||||
|
||||
final boolean ehcacheEnabled = this.configurationDomainService.isEhcacheEnabled();
|
||||
if (ehcacheEnabled) {
|
||||
this.cacheWritePlatformService.switchToCache(CacheType.SINGLE_NODE);
|
||||
} else {
|
||||
this.cacheWritePlatformService.switchToCache(CacheType.NO_CACHE);
|
||||
}
|
||||
TenantAwareBasicAuthenticationFilter.firstRequestProcessed = true;
|
||||
}
|
||||
}
|
||||
|
||||
super.doFilterInternal(request, response, filterChain);
|
||||
}
|
||||
} catch (final InvalidTenantIdentifierException e) {
|
||||
// deal with exception at low level
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
@@ -160,7 +157,7 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
|
||||
ThreadLocalContextUtil.reset();
|
||||
task.stop();
|
||||
final PlatformRequestLog log = PlatformRequestLog.from(task, request);
|
||||
LOG.debug("{}", this.toApiJsonSerializer.serialize(log));
|
||||
TenantAwareBasicAuthenticationFilter.log.debug("{}", this.toApiJsonSerializer.serialize(log));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-14
@@ -18,23 +18,22 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.security.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.security.constants.TwoFactorConstants;
|
||||
import org.apache.fineract.infrastructure.security.data.FineractJwtAuthenticationToken;
|
||||
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.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
@@ -42,7 +41,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
/**
|
||||
@@ -56,17 +54,11 @@ import org.springframework.web.filter.GenericFilterBean;
|
||||
* An authenticated platform user with permission 'BYPASS_TWOFACTOR' will always be granted 'TWOFACTOR_AUTHENTICATED'
|
||||
* authority regardless of the value of the 'Fineract-Platform-TFA-Token' header.
|
||||
*/
|
||||
@Service
|
||||
@ConditionalOnProperty("fineract.security.2fa.enabled")
|
||||
@RequiredArgsConstructor
|
||||
public class TwoFactorAuthenticationFilter extends GenericFilterBean {
|
||||
|
||||
private final TwoFactorService twoFactorService;
|
||||
|
||||
@Autowired
|
||||
public TwoFactorAuthenticationFilter(TwoFactorService twoFactorService) {
|
||||
this.twoFactorService = twoFactorService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
|
||||
@@ -21,18 +21,18 @@
|
||||
-->
|
||||
|
||||
|
||||
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
|
||||
version="2.0">
|
||||
<entity-mappings xmlns="https://jakarta.ee/xml/ns/persistence/orm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence/orm
|
||||
https://jakarta.ee/xml/ns/persistence/orm/orm_3_0.xsd" version="3.0">
|
||||
|
||||
<persistence-unit-metadata>
|
||||
<persistence-unit-defaults>
|
||||
<delimited-identifiers/>
|
||||
<!-- <entity-listeners>-->
|
||||
<!-- <entity-listener-->
|
||||
<!-- class="org.springframework.data.jpa.domain.support.AuditingEntityListener" />-->
|
||||
<!-- </entity-listeners>-->
|
||||
<entity-listeners>
|
||||
<entity-listener
|
||||
class="org.springframework.data.jpa.domain.support.AuditingEntityListener"/>
|
||||
</entity-listeners>
|
||||
</persistence-unit-defaults>
|
||||
</persistence-unit-metadata>
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ dependencies {
|
||||
exclude group: 'org.apache.sling'
|
||||
exclude group: 'com.sun.xml.bind'
|
||||
}
|
||||
testImplementation 'org.apache.groovy:groovy-xml'
|
||||
testImplementation 'org.apache.groovy:groovy-json'
|
||||
testImplementation 'org.awaitility:awaitility'
|
||||
|
||||
testCompileOnly 'org.projectlombok:lombok'
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user