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:
parent
ac81f3529b
commit
23735316f9
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue