Skip to content

Commit 893727d

Browse files
author
Chen, Taiyue
committed
<feature>[ldap]: refactor LDAP login logic and add two-factor authentication support
1. Extract common method findAccountThirdPartyAccountSourceRefByName - Extract the logic of finding third-party account source reference from login method into a standalone method - Unify account lookup logic in both login and collectUserInfoIntoContext methods 2. Add two-factor authentication support - getRequiredAdditionalAuthFeature method now returns a list containing both basicLoginControl and twoFactor - Support two-factor authentication for LDAP login Resolves: ZSV-11833 Change-Id: I7578626465676e6569686a786271786b64667179
1 parent 1340bd2 commit 893727d

5 files changed

Lines changed: 56 additions & 45 deletions

File tree

plugin/ldap/src/main/java/org/zstack/ldap/LdapManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import org.zstack.core.Platform;
44
import org.zstack.header.errorcode.ErrorableValue;
5+
import org.zstack.identity.imports.entity.AccountThirdPartyAccountSourceRefVO;
56
import org.zstack.ldap.driver.LdapUtil;
67
import org.zstack.ldap.entity.LdapServerVO;
78

@@ -10,7 +11,7 @@
1011
*/
1112
public interface LdapManager {
1213
boolean isValid(String uid, String password);
13-
14+
ErrorableValue<AccountThirdPartyAccountSourceRefVO> findAccountThirdPartyAccountSourceRefByName(String ldapLoginName, String ldapLoginPassword);
1415
ErrorableValue<String> findCurrentLdapServerUuid();
1516
ErrorableValue<LdapServerVO> findCurrentLdapServer();
1617

plugin/ldap/src/main/java/org/zstack/ldap/LdapManagerImpl.java

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.zstack.header.core.ReturnValueCompletion;
1616
import org.zstack.header.errorcode.ErrorCode;
1717
import org.zstack.header.errorcode.ErrorableValue;
18+
import org.zstack.header.errorcode.OperationFailureException;
1819
import org.zstack.header.identity.*;
1920
import org.zstack.header.identity.login.*;
2021
import org.zstack.header.message.APIMessage;
@@ -407,44 +408,49 @@ public LoginType getLoginType() {
407408
return loginType;
408409
}
409410

410-
@Override
411-
public void login(LoginContext loginContext, ReturnValueCompletion<LoginSessionInfo> completion) {
411+
public ErrorableValue<AccountThirdPartyAccountSourceRefVO> findAccountThirdPartyAccountSourceRefByName(String ldapLoginName, String ldapLoginPassword) {
412412
final ErrorableValue<LdapServerVO> currentLdapServer = findCurrentLdapServer();
413413
if (!currentLdapServer.isSuccess()) {
414-
logger.debug("failed to login by LDAP: failed to find current LdapServer: " + currentLdapServer.error.getDetails());
415-
completion.fail(err(IdentityErrors.AUTHENTICATION_ERROR,
416-
"Login validation failed in LDAP"));
417-
return;
414+
return ErrorableValue.ofErrorCode(currentLdapServer.error);
418415
}
419416
final LdapServerVO ldap = currentLdapServer.result;
420417

421-
String ldapLoginName = loginContext.getUsername();
422-
if (!isValid(ldapLoginName, loginContext.getPassword())) {
423-
completion.fail(err(IdentityErrors.AUTHENTICATION_ERROR,
424-
"Login validation failed in LDAP"));
425-
return;
426-
}
427-
428418
String dn = createDriver().getFullUserDn(ldap, ldap.getUsernameProperty(), ldapLoginName);
429419
AccountThirdPartyAccountSourceRefVO vo = Q.New(AccountThirdPartyAccountSourceRefVO.class)
430420
.eq(AccountThirdPartyAccountSourceRefVO_.credentials, dn)
431421
.eq(AccountThirdPartyAccountSourceRefVO_.accountSourceUuid, ldap.getUuid())
432422
.find();
433423

434424
if (vo == null) {
435-
completion.fail(err(IdentityErrors.AUTHENTICATION_ERROR,
425+
return ErrorableValue.ofErrorCode(err(IdentityErrors.AUTHENTICATION_ERROR,
436426
"The ldapUid does not have a binding account."));
427+
}
428+
return ErrorableValue.of(vo);
429+
}
430+
431+
@Override
432+
public void login(LoginContext loginContext, ReturnValueCompletion<LoginSessionInfo> completion) {
433+
if (!isValid(loginContext.getUsername(), loginContext.getPassword())) {
434+
completion.fail(err(IdentityErrors.AUTHENTICATION_ERROR,
435+
"Login validation failed in LDAP"));
437436
return;
438437
}
439438

439+
final ErrorableValue<AccountThirdPartyAccountSourceRefVO> accountThirdPartyAccountSourceRef = findAccountThirdPartyAccountSourceRefByName(loginContext.getUsername(), loginContext.getPassword());
440+
441+
if (!accountThirdPartyAccountSourceRef.isSuccess()) {
442+
completion.fail(accountThirdPartyAccountSourceRef.error);
443+
return;
444+
}
445+
String accountUuid = accountThirdPartyAccountSourceRef.result.getAccountUuid();
440446
final AccountState state = Q.New(AccountVO.class)
441-
.eq(AccountVO_.uuid, vo.getAccountUuid())
447+
.eq(AccountVO_.uuid, accountUuid)
442448
.select(AccountVO_.state)
443449
.findValue();
444450

445451
if (state == null || state == AccountState.Staled) {
446452
completion.fail(operr(
447-
"Account[uuid:%s] Not Found!!!", vo.getAccountUuid()));
453+
"Account[uuid:%s] Not Found!!!", accountUuid));
448454
return;
449455
}
450456
if (state == AccountState.Disabled) {
@@ -453,7 +459,7 @@ public void login(LoginContext loginContext, ReturnValueCompletion<LoginSessionI
453459
}
454460

455461
LoginSessionInfo info = new LoginSessionInfo();
456-
info.setAccountUuid(vo.getAccountUuid());
462+
info.setAccountUuid(accountUuid);
457463
completion.success(info);
458464
}
459465

@@ -468,21 +474,39 @@ public boolean authenticate(String username, String password) {
468474

469475
@Override
470476
public String getAccountIdByName(String username) {
471-
final ErrorableValue<LdapServerVO> property = findCurrentLdapServer();
472-
if (property.isSuccess()) {
473-
final String fullUserDn = createDriver().getFullUserDn(property.result, username);
474-
return "".equals(fullUserDn) ? null : fullUserDn;
477+
final ErrorableValue<LdapServerVO> currentLdapServer = findCurrentLdapServer();
478+
if (!currentLdapServer.isSuccess()) {
479+
return null;
480+
}
481+
final LdapServerVO ldap = currentLdapServer.result;
482+
483+
String dn = createDriver().getFullUserDn(ldap, ldap.getUsernameProperty(), username);
484+
if (dn == null || dn.isEmpty()) {
485+
return null;
475486
}
476-
return null;
487+
488+
String accountUuid = Q.New(AccountThirdPartyAccountSourceRefVO.class)
489+
.select(AccountThirdPartyAccountSourceRefVO_.accountUuid)
490+
.eq(AccountThirdPartyAccountSourceRefVO_.credentials, dn)
491+
.eq(AccountThirdPartyAccountSourceRefVO_.accountSourceUuid, ldap.getUuid())
492+
.findValue();
493+
return accountUuid;
477494
}
478495

479496
@Override
480497
public void collectUserInfoIntoContext(LoginContext loginContext) {
481-
loginContext.setAccountUuid(getAccountIdByName(loginContext.getUsername()));
498+
ErrorableValue<AccountThirdPartyAccountSourceRefVO> accountThirdPartyAccountSourceRef = findAccountThirdPartyAccountSourceRefByName(loginContext.getUsername(), loginContext.getPassword());
499+
if (!accountThirdPartyAccountSourceRef.isSuccess()) {
500+
throw new OperationFailureException(accountThirdPartyAccountSourceRef.error);
501+
}
502+
if (accountThirdPartyAccountSourceRef.result == null) {
503+
return;
504+
}
505+
loginContext.setAccountUuid(accountThirdPartyAccountSourceRef.result.getAccountUuid());
482506
}
483507

484508
@Override
485509
public List<AdditionalAuthFeature> getRequiredAdditionalAuthFeature() {
486-
return Collections.singletonList(LoginAuthConstant.basicLoginControl);
510+
return Arrays.asList(LoginAuthConstant.basicLoginControl, LoginAuthConstant.twoFactor);
487511
}
488512
}

sdk/src/main/java/org/zstack/sdk/GetTwoFactorAuthenticationSecretAction.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public Result throwExceptionIfError() {
3737
@Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
3838
public java.lang.String verifyCode;
3939

40+
@Param(required = true, validValues = {"account","ldap"}, nonempty = true, nullElements = false, emptyString = true, noTrim = false)
41+
public java.lang.String type;
42+
4043
@Param(required = false)
4144
public java.util.List systemTags;
4245

sdk/src/main/java/org/zstack/sdk/ResetTwoFactorAuthenticationSecretAction.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ public Result throwExceptionIfError() {
3737
@Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
3838
public java.lang.String verifyCode;
3939

40+
@Param(required = true, validValues = {"account","ldap"}, nonempty = true, nullElements = false, emptyString = true, noTrim = false)
41+
public java.lang.String type;
42+
4043
@Param(required = false)
4144
public java.util.List systemTags;
4245

test/src/test/resources/springConfigXml/license.xml

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)