Support for profile auto-fill with LDAP

This commit is contained in:
Maxime Dor
2017-10-08 04:22:38 +02:00
parent 2bf68538c3
commit 9af0cd3615

View File

@@ -20,7 +20,11 @@
package io.kamax.mxisd.backend.ldap; package io.kamax.mxisd.backend.ldap;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import io.kamax.matrix.ThreePidMedium;
import io.kamax.matrix._MatrixID; import io.kamax.matrix._MatrixID;
import io.kamax.mxisd.ThreePid;
import io.kamax.mxisd.UserIdType; import io.kamax.mxisd.UserIdType;
import io.kamax.mxisd.auth.provider.AuthenticatorProvider; import io.kamax.mxisd.auth.provider.AuthenticatorProvider;
import io.kamax.mxisd.auth.provider.BackendAuthResult; import io.kamax.mxisd.auth.provider.BackendAuthResult;
@@ -41,12 +45,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
@Component @Component
public class LdapAuthProvider extends LdapGenericBackend implements AuthenticatorProvider { public class LdapAuthProvider extends LdapGenericBackend implements AuthenticatorProvider {
private Logger log = LoggerFactory.getLogger(LdapAuthProvider.class); private Logger log = LoggerFactory.getLogger(LdapAuthProvider.class);
private PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
@Autowired @Autowired
public LdapAuthProvider(LdapConfig cfg, MatrixConfig mxCfg) { public LdapAuthProvider(LdapConfig cfg, MatrixConfig mxCfg) {
super(cfg, mxCfg); super(cfg, mxCfg);
@@ -57,6 +66,21 @@ public class LdapAuthProvider extends LdapGenericBackend implements Authenticato
return getCfg().isEnabled(); return getCfg().isEnabled();
} }
private Optional<String> getMsisdn(String phoneNumber) {
try { // FIXME export into dedicated ThreePid class within SDK (copy from Firebase Auth)
return Optional.of(phoneUtil.format(
phoneUtil.parse(
phoneNumber,
null // No default region
),
PhoneNumberUtil.PhoneNumberFormat.E164
).substring(1)); // We want without the leading +
} catch (NumberParseException e) {
log.warn("Invalid phone number: {}", phoneNumber);
return Optional.empty();
}
}
@Override @Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) { public BackendAuthResult authenticate(_MatrixID mxid, String password) {
log.info("Performing auth for {}", mxid); log.info("Performing auth for {}", mxid);
@@ -74,7 +98,15 @@ public class LdapAuthProvider extends LdapGenericBackend implements Authenticato
String userFilter = "(" + getUidAtt() + "=" + userFilterValue + ")"; String userFilter = "(" + getUidAtt() + "=" + userFilterValue + ")";
userFilter = buildWithFilter(userFilter, getCfg().getAuth().getFilter()); userFilter = buildWithFilter(userFilter, getCfg().getAuth().getFilter());
try (EntryCursor cursor = conn.search(getBaseDn(), userFilter, SearchScope.SUBTREE, getUidAtt(), getAt().getName())) {
Set<String> attributes = new HashSet<>();
attributes.add(getUidAtt());
attributes.add(getAt().getName());
getAt().getThreepid().forEach((k, v) -> attributes.addAll(v));
String[] attArray = new String[attributes.size()];
attributes.toArray(attArray);
try (EntryCursor cursor = conn.search(getBaseDn(), userFilter, SearchScope.SUBTREE, attArray)) {
while (cursor.next()) { while (cursor.next()) {
Entry entry = cursor.get(); Entry entry = cursor.get();
String dn = entry.getDn().getName(); String dn = entry.getDn().getName();
@@ -99,7 +131,18 @@ public class LdapAuthProvider extends LdapGenericBackend implements Authenticato
log.info("DN {} is a valid match", dn); log.info("DN {} is a valid match", dn);
// TODO should we canonicalize the MXID? // TODO should we canonicalize the MXID?
return BackendAuthResult.success(mxid.getId(), UserIdType.MatrixID, name); BackendAuthResult result = BackendAuthResult.success(mxid.getId(), UserIdType.MatrixID, name);
log.info("Processing 3PIDs for profile");
getAt().getThreepid().forEach((k, v) -> v.forEach(attId -> {
getAttribute(entry, attId).ifPresent(tpidValue -> {
if (ThreePidMedium.PhoneNumber.is(k)) {
tpidValue = getMsisdn(tpidValue).orElse(tpidValue);
}
result.withThreePid(new ThreePid(k, tpidValue));
});
}));
log.info("Found {} 3PIDs", result.getProfile().getThreePids().size());
return result;
} }
} catch (CursorLdapReferralException e) { } catch (CursorLdapReferralException e) {
log.warn("Entity for {} is only available via referral, skipping", mxid); log.warn("Entity for {} is only available via referral, skipping", mxid);