IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823) (#1596)

* IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823)

Show MFA for support users in System, even if they have roles in several tenants, they can just have MFA defined in System tenant

* IDEMPIERE-5408 Allow or enforce login with specific tenant (FHCA-3823)

- Change of approach, the MFA can be shown first when the client is defined, or when the user is defined to belong to a single tenant
  - on the contrary, when we have same user/password in two tenants, the MFA must be delayed until the tenant is identified

- Reviewing this noticed that the Login locking/inactivity logic is working on the full users array, even if the user has a different password (so is a different user)
  Fixed this to work just on the authenticated users - this is, those that have the same password in different tenants
This commit is contained in:
Carlos Ruiz 2022-12-02 08:31:56 +01:00 committed by GitHub
parent ac81f3529b
commit 23735316f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 43 deletions

View File

@ -1361,46 +1361,8 @@ public class Login
int MAX_INACTIVE_PERIOD_DAY = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_MAX_INACTIVE_PERIOD_DAY, 0); int MAX_INACTIVE_PERIOD_DAY = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_MAX_INACTIVE_PERIOD_DAY, 0);
int MAX_PASSWORD_AGE = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_MAX_PASSWORD_AGE_DAY, 0); int MAX_PASSWORD_AGE = MSysConfig.getIntValue(MSysConfig.USER_LOCKING_MAX_PASSWORD_AGE_DAY, 0);
long now = new Date().getTime(); long now = new Date().getTime();
for (MUser user : users) { List<MUser> usersAuthenticated = new ArrayList<MUser>();
if (MAX_ACCOUNT_LOCK_MINUTES > 0 && user.isLocked() && user.getDateAccountLocked() != null) // Perform first validation of user/password to define the authenticated users
{
long minutes = (now - user.getDateAccountLocked().getTime()) / (1000 * 60);
if (minutes > MAX_ACCOUNT_LOCK_MINUTES)
{
boolean inactive = false;
if (MAX_INACTIVE_PERIOD_DAY > 0 && user.getDateLastLogin() != null && !user.isNoExpire())
{
long days = (now - user.getDateLastLogin().getTime()) / (1000 * 60 * 60 * 24);
if (days > MAX_INACTIVE_PERIOD_DAY)
inactive = true;
}
if (!inactive)
{
user.setIsLocked(false);
user.setDateAccountLocked(null);
user.setFailedLoginCount(0);
Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, user.getAD_Client_ID());
if (!user.save())
log.severe("Failed to unlock user account");
}
}
}
if (MAX_INACTIVE_PERIOD_DAY > 0 && !user.isLocked() && user.getDateLastLogin() != null && !user.isNoExpire())
{
long days = (now - user.getDateLastLogin().getTime()) / (1000 * 60 * 60 * 24);
if (days > MAX_INACTIVE_PERIOD_DAY)
{
user.setIsLocked(true);
user.setDateAccountLocked(new Timestamp(now));
Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, user.getAD_Client_ID());
if (!user.save())
log.severe("Failed to lock user account");
}
}
}
boolean validButLocked = false; boolean validButLocked = false;
for (MUser user : users) { for (MUser user : users) {
if (clientsValidated.contains(user.getAD_Client_ID())) { if (clientsValidated.contains(user.getAD_Client_ID())) {
@ -1424,6 +1386,7 @@ public class Login
} }
if (valid ) { if (valid ) {
usersAuthenticated.add(user);
if (user.isLocked()) if (user.isLocked())
{ {
validButLocked = true; validButLocked = true;
@ -1490,7 +1453,53 @@ public class Login
if (clientList.size() > 0) if (clientList.size() > 0)
authenticated=true; authenticated=true;
// Validate locking/inactivity just on authenticated users
for (MUser user : usersAuthenticated) {
if (MAX_ACCOUNT_LOCK_MINUTES > 0 && user.isLocked() && user.getDateAccountLocked() != null)
{
long minutes = (now - user.getDateAccountLocked().getTime()) / (1000 * 60);
if (minutes > MAX_ACCOUNT_LOCK_MINUTES)
{
boolean inactive = false;
if (MAX_INACTIVE_PERIOD_DAY > 0 && user.getDateLastLogin() != null && !user.isNoExpire())
{
long days = (now - user.getDateLastLogin().getTime()) / (1000 * 60 * 60 * 24);
if (days > MAX_INACTIVE_PERIOD_DAY)
inactive = true;
}
if (!inactive)
{
user.setIsLocked(false);
user.setDateAccountLocked(null);
user.setFailedLoginCount(0);
Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, user.getAD_Client_ID());
if (!user.save())
log.severe("Failed to unlock user account");
}
}
}
if (MAX_INACTIVE_PERIOD_DAY > 0 && !user.isLocked() && user.getDateLastLogin() != null && !user.isNoExpire())
{
long days = (now - user.getDateLastLogin().getTime()) / (1000 * 60 * 60 * 24);
if (days > MAX_INACTIVE_PERIOD_DAY)
{
user.setIsLocked(true);
user.setDateAccountLocked(new Timestamp(now));
Env.setContext(Env.getCtx(), Env.AD_CLIENT_ID, user.getAD_Client_ID());
if (!user.save())
log.severe("Failed to lock user account");
}
}
}
if (authenticated) { if (authenticated) {
if (usersAuthenticated.size() == 1) {
// The user/password combination just belongs to a single user, it's clearly identified here
Env.setContext(Env.getCtx(), Env.AD_USER_ID, usersAuthenticated.get(0).getAD_User_ID());
}
if (Ini.isClient()) if (Ini.isClient())
{ {
if (MSystem.isSwingRememberUserAllowed()) if (MSystem.isSwingRememberUserAllowed())
@ -1505,7 +1514,7 @@ public class Login
clientList.toArray(retValue); clientList.toArray(retValue);
if (log.isLoggable(Level.FINE)) log.fine("User=" + app_user + " - roles #" + retValue.length); if (log.isLoggable(Level.FINE)) log.fine("User=" + app_user + " - roles #" + retValue.length);
for (MUser user : users) for (MUser user : usersAuthenticated)
{ {
user.setFailedLoginCount(0); user.setFailedLoginCount(0);
user.setDateLastLogin(new Timestamp(now)); user.setDateLastLogin(new Timestamp(now));
@ -1522,7 +1531,7 @@ public class Login
else else
{ {
boolean foundLockedAccount = false; boolean foundLockedAccount = false;
for (MUser user : users) for (MUser user : usersAuthenticated)
{ {
if (user.isLocked()) if (user.isLocked())
{ {

View File

@ -110,7 +110,7 @@ public class LoginWindow extends FWindow implements EventListener<Event>
public void loginOk(String userName, boolean show, KeyNamePair[] clientsKNPairs) public void loginOk(String userName, boolean show, KeyNamePair[] clientsKNPairs)
{ {
boolean isClientDefined = (clientsKNPairs.length == 1); boolean isClientDefined = (clientsKNPairs.length == 1 || ! Util.isEmpty(Env.getContext(ctx, Env.AD_USER_ID)));
if (pnlRole == null) if (pnlRole == null)
pnlRole = new RolePanel(ctx, this, userName, show, clientsKNPairs, isClientDefined); pnlRole = new RolePanel(ctx, this, userName, show, clientsKNPairs, isClientDefined);
if (isClientDefined) { if (isClientDefined) {