mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-30 20:06:19 +00:00
Fix Login Configuration Issue (#19109)
* Fix Login Configuration Issue * Fix Tests
This commit is contained in:
parent
c96c7785df
commit
4b9948dbfb
@ -35,7 +35,7 @@ public final class CatalogExceptionMessage {
|
|||||||
public static final String PASSWORD_INVALID_FORMAT =
|
public static final String PASSWORD_INVALID_FORMAT =
|
||||||
"Password must be of minimum 8 characters, with one special, one Upper, one lower case character, and one Digit.";
|
"Password must be of minimum 8 characters, with one special, one Upper, one lower case character, and one Digit.";
|
||||||
public static final String MAX_FAILED_LOGIN_ATTEMPT =
|
public static final String MAX_FAILED_LOGIN_ATTEMPT =
|
||||||
"Failed Login Attempts Exceeded. Please try after some time.";
|
"Failed Login Attempts Exceeded. Use Forgot Password or retry after some time.";
|
||||||
|
|
||||||
public static final String INCORRECT_OLD_PASSWORD = "INCORRECT_OLD_PASSWORD";
|
public static final String INCORRECT_OLD_PASSWORD = "INCORRECT_OLD_PASSWORD";
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ import org.openmetadata.service.search.SearchRepository;
|
|||||||
import org.openmetadata.service.secrets.SecretsManager;
|
import org.openmetadata.service.secrets.SecretsManager;
|
||||||
import org.openmetadata.service.secrets.SecretsManagerFactory;
|
import org.openmetadata.service.secrets.SecretsManagerFactory;
|
||||||
import org.openmetadata.service.security.JwtFilter;
|
import org.openmetadata.service.security.JwtFilter;
|
||||||
|
import org.openmetadata.service.security.auth.LoginAttemptCache;
|
||||||
import org.openmetadata.service.util.JsonUtils;
|
import org.openmetadata.service.util.JsonUtils;
|
||||||
import org.openmetadata.service.util.OpenMetadataConnectionBuilder;
|
import org.openmetadata.service.util.OpenMetadataConnectionBuilder;
|
||||||
import org.openmetadata.service.util.RestUtil;
|
import org.openmetadata.service.util.RestUtil;
|
||||||
@ -249,6 +250,10 @@ public class SystemRepository {
|
|||||||
WorkflowHandler workflowHandler = WorkflowHandler.getInstance();
|
WorkflowHandler workflowHandler = WorkflowHandler.getInstance();
|
||||||
workflowHandler.initializeNewProcessEngine(workflowHandler.getProcessEngineConfiguration());
|
workflowHandler.initializeNewProcessEngine(workflowHandler.getProcessEngineConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settingsType == SettingsType.LOGIN_CONFIGURATION) {
|
||||||
|
LoginAttemptCache.updateLoginConfiguration();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSetting(Settings setting) {
|
public void updateSetting(Settings setting) {
|
||||||
|
@ -118,7 +118,7 @@ public class SettingsCache {
|
|||||||
.withConfigValue(
|
.withConfigValue(
|
||||||
new LoginConfiguration()
|
new LoginConfiguration()
|
||||||
.withMaxLoginFailAttempts(3)
|
.withMaxLoginFailAttempts(3)
|
||||||
.withAccessBlockTime(600)
|
.withAccessBlockTime(30)
|
||||||
.withJwtTokenExpiryTime(3600));
|
.withJwtTokenExpiryTime(3600));
|
||||||
systemRepository.createNewSetting(setting);
|
systemRepository.createNewSetting(setting);
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,6 @@ public class BasicAuthenticator implements AuthenticatorHandler {
|
|||||||
private static final int HASHING_COST = 12;
|
private static final int HASHING_COST = 12;
|
||||||
private UserRepository userRepository;
|
private UserRepository userRepository;
|
||||||
private TokenRepository tokenRepository;
|
private TokenRepository tokenRepository;
|
||||||
private LoginAttemptCache loginAttemptCache;
|
|
||||||
private AuthorizerConfiguration authorizerConfiguration;
|
private AuthorizerConfiguration authorizerConfiguration;
|
||||||
private boolean isSelfSignUpAvailable;
|
private boolean isSelfSignUpAvailable;
|
||||||
|
|
||||||
@ -111,7 +110,6 @@ public class BasicAuthenticator implements AuthenticatorHandler {
|
|||||||
this.userRepository = (UserRepository) Entity.getEntityRepository(Entity.USER);
|
this.userRepository = (UserRepository) Entity.getEntityRepository(Entity.USER);
|
||||||
this.tokenRepository = Entity.getTokenRepository();
|
this.tokenRepository = Entity.getTokenRepository();
|
||||||
this.authorizerConfiguration = config.getAuthorizerConfiguration();
|
this.authorizerConfiguration = config.getAuthorizerConfiguration();
|
||||||
this.loginAttemptCache = new LoginAttemptCache();
|
|
||||||
this.isSelfSignUpAvailable = config.getAuthenticationConfiguration().getEnableSelfSignup();
|
this.isSelfSignUpAvailable = config.getAuthenticationConfiguration().getEnableSelfSignup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +265,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
|
|||||||
LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex);
|
LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex);
|
||||||
throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
|
throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
|
||||||
}
|
}
|
||||||
loginAttemptCache.recordSuccessfulLogin(request.getUsername());
|
LoginAttemptCache.getInstance().recordSuccessfulLogin(request.getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -312,7 +310,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
|
|||||||
storedUser.getAuthenticationMechanism().setConfig(storedBasicAuthMechanism);
|
storedUser.getAuthenticationMechanism().setConfig(storedBasicAuthMechanism);
|
||||||
PutResponse<User> response = userRepository.createOrUpdate(uriInfo, storedUser);
|
PutResponse<User> response = userRepository.createOrUpdate(uriInfo, storedUser);
|
||||||
// remove login/details from cache
|
// remove login/details from cache
|
||||||
loginAttemptCache.recordSuccessfulLogin(userName);
|
LoginAttemptCache.getInstance().recordSuccessfulLogin(userName);
|
||||||
|
|
||||||
// in case admin updates , send email to user
|
// in case admin updates , send email to user
|
||||||
if (request.getRequestType() == USER && getSmtpSettings().getEnableSmtpServer()) {
|
if (request.getRequestType() == USER && getSmtpSettings().getEnableSmtpServer()) {
|
||||||
@ -476,7 +474,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkIfLoginBlocked(String email) {
|
public void checkIfLoginBlocked(String email) {
|
||||||
if (loginAttemptCache.isLoginBlocked(email)) {
|
if (LoginAttemptCache.getInstance().isLoginBlocked(email)) {
|
||||||
throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT);
|
throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,15 +482,15 @@ public class BasicAuthenticator implements AuthenticatorHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void recordFailedLoginAttempt(String email, String userName)
|
public void recordFailedLoginAttempt(String email, String userName)
|
||||||
throws TemplateException, IOException {
|
throws TemplateException, IOException {
|
||||||
loginAttemptCache.recordFailedLogin(email);
|
LoginAttemptCache.getInstance().recordFailedLogin(email);
|
||||||
int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(email);
|
int failedLoginAttempt = LoginAttemptCache.getInstance().getUserFailedLoginCount(email);
|
||||||
if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
|
if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
|
||||||
sendAccountStatus(
|
sendAccountStatus(
|
||||||
userName,
|
userName,
|
||||||
email,
|
email,
|
||||||
"Multiple Failed Login Attempts.",
|
"Multiple Failed Login Attempts.",
|
||||||
String.format(
|
String.format(
|
||||||
"Someone is trying to access your account. Login is Blocked for %s minutes. Please change your password.",
|
"Someone is trying to access your account. Login is Blocked for %s seconds. Please change your password.",
|
||||||
SecurityUtil.getLoginConfiguration().getAccessBlockTime()));
|
SecurityUtil.getLoginConfiguration().getAccessBlockTime()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,6 @@ public class LdapAuthenticator implements AuthenticatorHandler {
|
|||||||
private RoleRepository roleRepository;
|
private RoleRepository roleRepository;
|
||||||
private UserRepository userRepository;
|
private UserRepository userRepository;
|
||||||
private TokenRepository tokenRepository;
|
private TokenRepository tokenRepository;
|
||||||
private LoginAttemptCache loginAttemptCache;
|
|
||||||
private LdapConfiguration ldapConfiguration;
|
private LdapConfiguration ldapConfiguration;
|
||||||
private LDAPConnectionPool ldapLookupConnectionPool;
|
private LDAPConnectionPool ldapLookupConnectionPool;
|
||||||
private boolean isSelfSignUpEnabled;
|
private boolean isSelfSignUpEnabled;
|
||||||
@ -102,7 +101,6 @@ public class LdapAuthenticator implements AuthenticatorHandler {
|
|||||||
this.roleRepository = (RoleRepository) Entity.getEntityRepository(Entity.ROLE);
|
this.roleRepository = (RoleRepository) Entity.getEntityRepository(Entity.ROLE);
|
||||||
this.tokenRepository = Entity.getTokenRepository();
|
this.tokenRepository = Entity.getTokenRepository();
|
||||||
this.ldapConfiguration = config.getAuthenticationConfiguration().getLdapConfiguration();
|
this.ldapConfiguration = config.getAuthenticationConfiguration().getLdapConfiguration();
|
||||||
this.loginAttemptCache = new LoginAttemptCache();
|
|
||||||
this.isSelfSignUpEnabled = config.getAuthenticationConfiguration().getEnableSelfSignup();
|
this.isSelfSignUpEnabled = config.getAuthenticationConfiguration().getEnableSelfSignup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +174,7 @@ public class LdapAuthenticator implements AuthenticatorHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void checkIfLoginBlocked(String email) {
|
public void checkIfLoginBlocked(String email) {
|
||||||
if (loginAttemptCache.isLoginBlocked(email)) {
|
if (LoginAttemptCache.getInstance().isLoginBlocked(email)) {
|
||||||
throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT);
|
throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,8 +182,8 @@ public class LdapAuthenticator implements AuthenticatorHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void recordFailedLoginAttempt(String email, String userName)
|
public void recordFailedLoginAttempt(String email, String userName)
|
||||||
throws TemplateException, IOException {
|
throws TemplateException, IOException {
|
||||||
loginAttemptCache.recordFailedLogin(email);
|
LoginAttemptCache.getInstance().recordFailedLogin(email);
|
||||||
int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(email);
|
int failedLoginAttempt = LoginAttemptCache.getInstance().getUserFailedLoginCount(email);
|
||||||
if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
|
if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
|
||||||
EmailUtil.sendAccountStatus(
|
EmailUtil.sendAccountStatus(
|
||||||
userName,
|
userName,
|
||||||
|
@ -3,6 +3,7 @@ package org.openmetadata.service.security.auth;
|
|||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import io.dropwizard.logback.shaded.guava.annotations.VisibleForTesting;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
@ -12,10 +13,11 @@ import org.openmetadata.schema.settings.SettingsType;
|
|||||||
import org.openmetadata.service.resources.settings.SettingsCache;
|
import org.openmetadata.service.resources.settings.SettingsCache;
|
||||||
|
|
||||||
public class LoginAttemptCache {
|
public class LoginAttemptCache {
|
||||||
|
private static LoginAttemptCache INSTANCE;
|
||||||
private int maxAttempt = 3;
|
private int maxAttempt = 3;
|
||||||
private final LoadingCache<String, Integer> attemptsCache;
|
private final LoadingCache<String, Integer> attemptsCache;
|
||||||
|
|
||||||
public LoginAttemptCache() {
|
private LoginAttemptCache() {
|
||||||
LoginConfiguration loginConfiguration =
|
LoginConfiguration loginConfiguration =
|
||||||
SettingsCache.getSetting(SettingsType.LOGIN_CONFIGURATION, LoginConfiguration.class);
|
SettingsCache.getSetting(SettingsType.LOGIN_CONFIGURATION, LoginConfiguration.class);
|
||||||
long accessBlockTime = 600;
|
long accessBlockTime = 600;
|
||||||
@ -35,6 +37,18 @@ public class LoginAttemptCache {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LoginAttemptCache getInstance() {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
INSTANCE = new LoginAttemptCache();
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateLoginConfiguration() {
|
||||||
|
INSTANCE = new LoginAttemptCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
public LoginAttemptCache(int maxAttempt, int blockTimeInSec) {
|
public LoginAttemptCache(int maxAttempt, int blockTimeInSec) {
|
||||||
this.maxAttempt = maxAttempt;
|
this.maxAttempt = maxAttempt;
|
||||||
attemptsCache =
|
attemptsCache =
|
||||||
|
@ -124,7 +124,7 @@ class ConfigResourceTest extends OpenMetadataApplicationTest {
|
|||||||
LoginConfiguration loginConfiguration =
|
LoginConfiguration loginConfiguration =
|
||||||
TestUtils.get(target, LoginConfiguration.class, TEST_AUTH_HEADERS);
|
TestUtils.get(target, LoginConfiguration.class, TEST_AUTH_HEADERS);
|
||||||
assertEquals(3, loginConfiguration.getMaxLoginFailAttempts());
|
assertEquals(3, loginConfiguration.getMaxLoginFailAttempts());
|
||||||
assertEquals(600, loginConfiguration.getAccessBlockTime());
|
assertEquals(30, loginConfiguration.getAccessBlockTime());
|
||||||
assertEquals(3600, loginConfiguration.getJwtTokenExpiryTime());
|
assertEquals(3600, loginConfiguration.getJwtTokenExpiryTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +436,7 @@ public class SystemResourceTest extends OpenMetadataApplicationTest {
|
|||||||
|
|
||||||
// Assert default values
|
// Assert default values
|
||||||
assertEquals(3, loginConfig.getMaxLoginFailAttempts());
|
assertEquals(3, loginConfig.getMaxLoginFailAttempts());
|
||||||
assertEquals(600, loginConfig.getAccessBlockTime());
|
assertEquals(30, loginConfig.getAccessBlockTime());
|
||||||
assertEquals(3600, loginConfig.getJwtTokenExpiryTime());
|
assertEquals(3600, loginConfig.getJwtTokenExpiryTime());
|
||||||
|
|
||||||
// Update login configuration
|
// Update login configuration
|
||||||
|
Loading…
x
Reference in New Issue
Block a user