Search in sources :

Example 1 with BackendAuthResult

use of io.kamax.mxisd.auth.provider.BackendAuthResult in project mxisd by kamax-io.

the class GoogleFirebaseAuthenticator method authenticate.

@Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
    if (!isEnabled()) {
        throw new IllegalStateException();
    }
    log.info("Trying to authenticate {}", mxid);
    final BackendAuthResult result = BackendAuthResult.failure();
    String localpart = mxid.getLocalPart();
    CountDownLatch l = new CountDownLatch(1);
    getFirebase().verifyIdToken(password).addOnSuccessListener(token -> {
        try {
            if (!StringUtils.equals(localpart, token.getUid())) {
                log.info("Failure to authenticate {}: Matrix ID localpart '{}' does not match Firebase UID '{}'", mxid, localpart, token.getUid());
                result.fail();
                return;
            }
            result.succeed(mxid.getId(), UserIdType.MatrixID.getId(), token.getName());
            log.info("{} was successfully authenticated", mxid);
            log.info("Fetching profile for {}", mxid);
            CountDownLatch userRecordLatch = new CountDownLatch(1);
            getFirebase().getUser(token.getUid()).addOnSuccessListener(user -> {
                try {
                    toEmail(result, user.getEmail());
                    toMsisdn(result, user.getPhoneNumber());
                    for (UserInfo info : user.getProviderData()) {
                        toEmail(result, info.getEmail());
                        toMsisdn(result, info.getPhoneNumber());
                    }
                    log.info("Got {} 3PIDs in profile", result.getProfile().getThreePids().size());
                } finally {
                    userRecordLatch.countDown();
                }
            }).addOnFailureListener(e -> {
                try {
                    log.warn("Unable to fetch Firebase user profile for {}", mxid);
                    result.fail();
                } finally {
                    userRecordLatch.countDown();
                }
            });
            waitOnLatch(result, userRecordLatch, "Firebase user profile");
        } finally {
            l.countDown();
        }
    }).addOnFailureListener(e -> {
        try {
            if (e instanceof IllegalArgumentException) {
                log.info("Failure to authenticate {}: invalid firebase token", mxid);
            } else {
                log.info("Failure to authenticate {}: {}", mxid, e.getMessage(), e);
                log.info("Exception", e);
            }
            result.fail();
        } finally {
            l.countDown();
        }
    });
    waitOnLatch(result, l, "Firebase auth check");
    return result;
}
Also used : BackendAuthResult(io.kamax.mxisd.auth.provider.BackendAuthResult) ThreePidMedium(io.kamax.matrix.ThreePidMedium) StringUtils(org.apache.commons.lang.StringUtils) Logger(org.slf4j.Logger) UserInfo(com.google.firebase.auth.UserInfo) AuthenticatorProvider(io.kamax.mxisd.auth.provider.AuthenticatorProvider) LoggerFactory(org.slf4j.LoggerFactory) io.kamax.matrix._MatrixID(io.kamax.matrix._MatrixID) BackendAuthResult(io.kamax.mxisd.auth.provider.BackendAuthResult) ThreePid(io.kamax.matrix.ThreePid) TimeUnit(java.util.concurrent.TimeUnit) PhoneNumberUtil(com.google.i18n.phonenumbers.PhoneNumberUtil) CountDownLatch(java.util.concurrent.CountDownLatch) NumberParseException(com.google.i18n.phonenumbers.NumberParseException) UserIdType(io.kamax.mxisd.UserIdType) UserInfo(com.google.firebase.auth.UserInfo) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 2 with BackendAuthResult

use of io.kamax.mxisd.auth.provider.BackendAuthResult in project mxisd by kamax-io.

the class LdapAuthProvider method authenticate.

@Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
    log.info("Performing auth for {}", mxid);
    try (LdapConnection conn = getConn()) {
        bind(conn);
        String uidType = getAt().getUid().getType();
        String userFilterValue = StringUtils.equals(LdapBackend.UID, uidType) ? mxid.getLocalPart() : mxid.getId();
        if (StringUtils.isBlank(userFilterValue)) {
            log.warn("Username is empty, failing auth");
            return BackendAuthResult.failure();
        }
        String userFilter = "(" + getUidAtt() + "=" + userFilterValue + ")";
        userFilter = buildWithFilter(userFilter, getCfg().getAuth().getFilter());
        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);
        log.debug("Base DN: {}", getBaseDn());
        log.debug("Query: {}", userFilter);
        log.debug("Attributes: {}", GsonUtil.build().toJson(attArray));
        try (EntryCursor cursor = conn.search(getBaseDn(), userFilter, SearchScope.SUBTREE, attArray)) {
            while (cursor.next()) {
                Entry entry = cursor.get();
                String dn = entry.getDn().getName();
                log.info("Checking possible match, DN: {}", dn);
                if (!getAttribute(entry, getUidAtt()).isPresent()) {
                    continue;
                }
                log.info("Attempting authentication on LDAP for {}", dn);
                try {
                    conn.bind(entry.getDn(), password);
                } catch (LdapException e) {
                    log.info("Unable to bind using {} because {}", entry.getDn().getName(), e.getMessage());
                    return BackendAuthResult.failure();
                }
                Attribute nameAttribute = entry.get(getAt().getName());
                String name = nameAttribute != null ? nameAttribute.get().toString() : null;
                log.info("Authentication successful for {}", entry.getDn().getName());
                log.info("DN {} is a valid match", dn);
                // TODO should we canonicalize the MXID?
                BackendAuthResult result = BackendAuthResult.success(mxid.getId(), UserIdType.MatrixID, name);
                log.info("Processing 3PIDs for profile");
                getAt().getThreepid().forEach((k, v) -> {
                    log.info("Processing 3PID type {}", k);
                    v.forEach(attId -> {
                        List<String> values = getAttributes(entry, attId);
                        log.info("\tAttribute {} has {} value(s)", attId, values.size());
                        getAttributes(entry, attId).forEach(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) {
            log.warn("Entity for {} is only available via referral, skipping", mxid);
        }
        log.info("No match were found for {}", mxid);
        return BackendAuthResult.failure();
    } catch (LdapException | IOException | CursorException e) {
        throw new RuntimeException(e);
    }
}
Also used : EntryCursor(org.apache.directory.api.ldap.model.cursor.EntryCursor) Attribute(org.apache.directory.api.ldap.model.entry.Attribute) IOException(java.io.IOException) BackendAuthResult(io.kamax.mxisd.auth.provider.BackendAuthResult) Entry(org.apache.directory.api.ldap.model.entry.Entry) CursorException(org.apache.directory.api.ldap.model.cursor.CursorException) CursorLdapReferralException(org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException) ThreePid(io.kamax.matrix.ThreePid) LdapException(org.apache.directory.api.ldap.model.exception.LdapException) LdapConnection(org.apache.directory.ldap.client.api.LdapConnection) HashSet(java.util.HashSet)

Example 3 with BackendAuthResult

use of io.kamax.mxisd.auth.provider.BackendAuthResult in project mxisd by kamax-io.

the class AuthManager method authenticate.

public UserAuthResult authenticate(String id, String password) {
    _MatrixID mxid = MatrixID.asAcceptable(id);
    for (AuthenticatorProvider provider : providers) {
        if (!provider.isEnabled()) {
            continue;
        }
        BackendAuthResult result = provider.authenticate(mxid, password);
        if (result.isSuccess()) {
            String mxId;
            if (UserIdType.Localpart.is(result.getId().getType())) {
                mxId = MatrixID.from(result.getId().getValue(), mxCfg.getDomain()).acceptable().getId();
            } else if (UserIdType.MatrixID.is(result.getId().getType())) {
                mxId = MatrixID.asAcceptable(result.getId().getValue()).getId();
            } else {
                log.warn("Unsupported User ID type {} for backend {}", result.getId().getType(), provider.getClass().getSimpleName());
                continue;
            }
            UserAuthResult authResult = new UserAuthResult().success(result.getProfile().getDisplayName());
            for (_ThreePid pid : result.getProfile().getThreePids()) {
                authResult.withThreePid(pid.getMedium(), pid.getAddress());
            }
            log.info("{} was authenticated by {}, publishing 3PID mappings, if any", id, provider.getClass().getSimpleName());
            for (ThreePid pid : authResult.getThreePids()) {
                log.info("Processing {} for {}", pid, id);
                invMgr.publishMappingIfInvited(new ThreePidMapping(pid, mxId));
            }
            invMgr.lookupMappingsForInvites();
            return authResult;
        }
    }
    return new UserAuthResult().failure();
}
Also used : BackendAuthResult(io.kamax.mxisd.auth.provider.BackendAuthResult) ThreePidMapping(io.kamax.mxisd.lookup.ThreePidMapping) AuthenticatorProvider(io.kamax.mxisd.auth.provider.AuthenticatorProvider) io.kamax.matrix._ThreePid(io.kamax.matrix._ThreePid) ThreePid(io.kamax.matrix.ThreePid) io.kamax.matrix._ThreePid(io.kamax.matrix._ThreePid) io.kamax.matrix._MatrixID(io.kamax.matrix._MatrixID)

Example 4 with BackendAuthResult

use of io.kamax.mxisd.auth.provider.BackendAuthResult in project mxisd by kamax-io.

the class WordpressAuthProvider method authenticate.

@Override
public BackendAuthResult authenticate(_MatrixID mxid, String password) {
    try {
        WordpressAuthData data = wordpress.authenticate(mxid.getLocalPart(), password);
        BackendAuthResult result = new BackendAuthResult();
        if (StringUtils.isNotBlank(data.getUserEmail())) {
            result.withThreePid(new ThreePid("email", data.getUserEmail()));
        }
        result.succeed(mxid.getId(), UserIdType.MatrixID.getId(), data.getUserDisplayName());
        return result;
    } catch (IllegalArgumentException e) {
        log.error("Authentication failed for {}: {}", mxid.getId(), e.getMessage());
        return BackendAuthResult.failure();
    }
}
Also used : BackendAuthResult(io.kamax.mxisd.auth.provider.BackendAuthResult) ThreePid(io.kamax.matrix.ThreePid)

Aggregations

ThreePid (io.kamax.matrix.ThreePid)4 BackendAuthResult (io.kamax.mxisd.auth.provider.BackendAuthResult)4 io.kamax.matrix._MatrixID (io.kamax.matrix._MatrixID)2 AuthenticatorProvider (io.kamax.mxisd.auth.provider.AuthenticatorProvider)2 UserInfo (com.google.firebase.auth.UserInfo)1 NumberParseException (com.google.i18n.phonenumbers.NumberParseException)1 PhoneNumberUtil (com.google.i18n.phonenumbers.PhoneNumberUtil)1 ThreePidMedium (io.kamax.matrix.ThreePidMedium)1 io.kamax.matrix._ThreePid (io.kamax.matrix._ThreePid)1 UserIdType (io.kamax.mxisd.UserIdType)1 ThreePidMapping (io.kamax.mxisd.lookup.ThreePidMapping)1 IOException (java.io.IOException)1 HashSet (java.util.HashSet)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 TimeUnit (java.util.concurrent.TimeUnit)1 StringUtils (org.apache.commons.lang.StringUtils)1 CursorException (org.apache.directory.api.ldap.model.cursor.CursorException)1 CursorLdapReferralException (org.apache.directory.api.ldap.model.cursor.CursorLdapReferralException)1 EntryCursor (org.apache.directory.api.ldap.model.cursor.EntryCursor)1 Attribute (org.apache.directory.api.ldap.model.entry.Attribute)1