Search in sources :

Example 1 with ThreePidSession

use of io.kamax.mxisd.threepid.session.ThreePidSession in project mxisd by kamax-io.

the class SessionMananger method bind.

public void bind(String sid, String secret, String mxidRaw) {
    _MatrixID mxid = new MatrixID(mxidRaw);
    ThreePidSession session = getSessionIfValidated(sid, secret);
    if (!session.isRemote()) {
        log.info("Session {} for {}: MXID {} was bound locally", sid, session.getThreePid(), mxid);
        return;
    }
    log.info("Session {} for {}: MXID {} bind is remote", sid, session.getThreePid(), mxid);
    if (!session.isRemoteValidated()) {
        log.error("Session {} for {}: Not validated remotely", sid, session.getThreePid());
        throw new SessionNotValidatedException();
    }
    log.info("Session {} for {}: Performing remote bind", sid, session.getThreePid());
    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(Arrays.asList(new BasicNameValuePair("sid", session.getRemoteId()), new BasicNameValuePair("client_secret", session.getRemoteSecret()), new BasicNameValuePair("mxid", mxid.getId())), StandardCharsets.UTF_8);
    HttpPost bindReq = new HttpPost(session.getRemoteServer() + "/_matrix/identity/api/v1/3pid/bind");
    bindReq.setEntity(entity);
    try (CloseableHttpResponse response = client.execute(bindReq)) {
        int status = response.getStatusLine().getStatusCode();
        if (status < 200 || status >= 300) {
            String body = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
            log.error("Session {} for {}: Remote IS {} failed when trying to bind {} for remote session {}\n{}", sid, session.getThreePid(), session.getRemoteServer(), mxid, session.getRemoteId(), body);
            throw new RemoteIdentityServerException(body);
        }
        log.error("Session {} for {}: MXID {} was bound remotely", sid, session.getThreePid(), mxid);
    } catch (IOException e) {
        log.error("Session {} for {}: I/O Error when trying to bind mxid {}", sid, session.getThreePid(), mxid);
        throw new RemoteIdentityServerException(e.getMessage());
    }
}
Also used : HttpPost(org.apache.http.client.methods.HttpPost) BasicNameValuePair(org.apache.http.message.BasicNameValuePair) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) UrlEncodedFormEntity(org.apache.http.client.entity.UrlEncodedFormEntity) IOException(java.io.IOException) ThreePidSession(io.kamax.mxisd.threepid.session.ThreePidSession) IThreePidSession(io.kamax.mxisd.threepid.session.IThreePidSession) io.kamax.matrix._MatrixID(io.kamax.matrix._MatrixID) MatrixID(io.kamax.matrix.MatrixID) io.kamax.matrix._MatrixID(io.kamax.matrix._MatrixID)

Example 2 with ThreePidSession

use of io.kamax.mxisd.threepid.session.ThreePidSession in project mxisd by kamax-io.

the class SessionMananger method create.

public String create(String server, ThreePid tpid, String secret, int attempt, String nextLink) {
    PolicyTemplate policy = cfg.getPolicy().getValidation();
    if (!policy.isEnabled()) {
        throw new NotAllowedException("Validating 3PID is disabled globally");
    }
    synchronized (this) {
        log.info("Server {} is asking to create session for {} (Attempt #{}) - Next link: {}", server, tpid, attempt, nextLink);
        Optional<IThreePidSessionDao> dao = storage.findThreePidSession(tpid, secret);
        if (dao.isPresent()) {
            ThreePidSession session = new ThreePidSession(dao.get());
            log.info("We already have a session for {}: {}", tpid, session.getId());
            if (session.getAttempt() < attempt) {
                log.info("Received attempt {} is greater than stored attempt {}, sending validation communication", attempt, session.getAttempt());
                notifMgr.sendForValidation(session);
                log.info("Sent validation notification to {}", tpid);
                session.increaseAttempt();
                storage.updateThreePidSession(session.getDao());
            }
            return session.getId();
        } else {
            log.info("No existing session for {}", tpid);
            boolean isLocal = isLocal(tpid);
            log.info("Is 3PID bound to local domain? {}", isLocal);
            // This might need a configuration by medium type?
            PolicySource policySource = policy.forIf(isLocal);
            if (!policySource.isEnabled() || (!policySource.toLocal() && !policySource.toRemote())) {
                log.info("Session for {}: cancelled due to policy", tpid);
                throw new NotAllowedException("Validating " + (isLocal ? "local" : "remote") + " 3PID is not allowed");
            }
            String sessionId;
            do {
                sessionId = Long.toString(System.currentTimeMillis());
            } while (storage.getThreePidSession(sessionId).isPresent());
            String token = RandomStringUtils.randomNumeric(6);
            ThreePidSession session = new ThreePidSession(sessionId, server, tpid, secret, attempt, nextLink, token);
            log.info("Generated new session {} to validate {} from server {}", sessionId, tpid, server);
            // This might need a configuration by medium type?
            if (policySource.toLocal()) {
                log.info("Session {} for {}: sending local validation notification", sessionId, tpid);
                notifMgr.sendForValidation(session);
            } else {
                log.info("Session {} for {}: sending remote-only validation notification", sessionId, tpid);
                notifMgr.sendforRemoteValidation(session);
            }
            storage.insertThreePidSession(session.getDao());
            log.info("Stored session {}", sessionId, tpid, server);
            return sessionId;
        }
    }
}
Also used : IThreePidSessionDao(io.kamax.mxisd.storage.dao.IThreePidSessionDao) PolicySource(io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate.PolicySource) ThreePidSession(io.kamax.mxisd.threepid.session.ThreePidSession) IThreePidSession(io.kamax.mxisd.threepid.session.IThreePidSession) PolicyTemplate(io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate)

Example 3 with ThreePidSession

use of io.kamax.mxisd.threepid.session.ThreePidSession in project mxisd by kamax-io.

the class SessionMananger method createRemote.

public IThreePidSession createRemote(String sid, String secret) {
    ThreePidSession session = getSessionIfValidated(sid, secret);
    log.info("Creating remote 3PID session for {} with local session [{}] to {}", session.getThreePid(), sid);
    boolean isLocal = isLocal(session.getThreePid());
    PolicySource policy = cfg.getPolicy().getValidation().forIf(isLocal);
    if (!policy.isEnabled() || !policy.toRemote()) {
        throw new NotAllowedException("Validating " + (isLocal ? "local" : "remote") + " 3PID is not allowed");
    }
    log.info("Remote 3PID is allowed by policy");
    List<String> servers = mxCfg.getIdentity().getServers(policy.getToRemote().getServer());
    if (servers.isEmpty()) {
        throw new FeatureNotAvailable("Remote 3PID sessions are enabled but server list is " + "misconstrued (invalid ID or empty list");
    }
    String is = servers.get(0);
    String url = IdentityServerUtils.findIsUrlForDomain(is).orElseThrow(() -> new InternalServerError(is + " could not be resolved to an Identity server"));
    log.info("Will use IS endpoint {}", url);
    String remoteSecret = session.isRemote() ? session.getRemoteSecret() : RandomStringUtils.randomAlphanumeric(16);
    JsonObject body = new JsonObject();
    body.addProperty("client_secret", remoteSecret);
    body.addProperty(session.getThreePid().getMedium(), session.getThreePid().getAddress());
    body.addProperty("send_attempt", session.increaseAndGetRemoteAttempt());
    if (ThreePidMedium.PhoneNumber.is(session.getThreePid().getMedium())) {
        try {
            Phonenumber.PhoneNumber msisdn = phoneUtil.parse("+" + session.getThreePid().getAddress(), null);
            String country = phoneUtil.getRegionCodeForNumber(msisdn).toUpperCase();
            body.addProperty("phone_number", phoneUtil.format(msisdn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
            body.addProperty("country", country);
        } catch (NumberParseException e) {
            throw new InternalServerError(e);
        }
    } else {
        body.addProperty(session.getThreePid().getMedium(), session.getThreePid().getAddress());
    }
    log.info("Requesting remote session with attempt {}", session.getRemoteAttempt());
    HttpPost tokenReq = RestClientUtils.post(url + "/_matrix/identity/api/v1/validate/" + session.getThreePid().getMedium() + "/requestToken", body);
    try (CloseableHttpResponse response = client.execute(tokenReq)) {
        int status = response.getStatusLine().getStatusCode();
        if (status < 200 || status >= 300) {
            JsonObject obj = parser.parseOptional(response).orElseThrow(() -> new RemoteIdentityServerException("Status " + status));
            throw new RemoteIdentityServerException(obj.get("errcode").getAsString() + ": " + obj.get("error").getAsString());
        }
        RequestTokenResponse data = new GsonParser().parse(response, RequestTokenResponse.class);
        log.info("Remote Session ID: {}", data.getSid());
        session.setRemoteData(url, data.getSid(), remoteSecret, 1);
        storage.updateThreePidSession(session.getDao());
        log.info("Updated Session {} with remote data", sid);
        return session;
    } catch (IOException e) {
        log.warn("Failed to create remote session with {} for {}: {}", url, session.getThreePid(), e.getMessage());
        throw new RemoteIdentityServerException(e.getMessage());
    }
}
Also used : HttpPost(org.apache.http.client.methods.HttpPost) JsonObject(com.google.gson.JsonObject) RequestTokenResponse(io.kamax.mxisd.controller.identity.v1.io.RequestTokenResponse) IOException(java.io.IOException) ThreePidSession(io.kamax.mxisd.threepid.session.ThreePidSession) IThreePidSession(io.kamax.mxisd.threepid.session.IThreePidSession) GsonParser(io.kamax.mxisd.util.GsonParser) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) NumberParseException(com.google.i18n.phonenumbers.NumberParseException) PolicySource(io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate.PolicySource) Phonenumber(com.google.i18n.phonenumbers.Phonenumber)

Example 4 with ThreePidSession

use of io.kamax.mxisd.threepid.session.ThreePidSession in project mxisd by kamax-io.

the class EmailNotificationTest method forValidation.

@Test
public void forValidation() throws MessagingException, IOException {
    gm.setUser(user, user);
    String token = RandomStringUtils.randomAlphanumeric(128);
    ThreePidSession session = new ThreePidSession("", "", new ThreePid(ThreePidMedium.Email.getId(), target), "", 1, "", token);
    m.getNotif().sendForValidation(session);
    assertEquals(1, gm.getReceivedMessages().length);
    MimeMessage msg = gm.getReceivedMessages()[0];
    assertEquals(1, msg.getFrom().length);
    assertEquals(senderNameEncoded, msg.getFrom()[0].toString());
    assertEquals(1, msg.getRecipients(Message.RecipientType.TO).length);
    // We just check on the text/plain one. HTML is multipart and it's difficult so we skip
    MimeMultipart content = (MimeMultipart) msg.getContent();
    MimeBodyPart mbp = (MimeBodyPart) content.getBodyPart(0);
    String mbpContent = mbp.getContent().toString();
    assertTrue(mbpContent.contains(token));
}
Also used : MimeMessage(javax.mail.internet.MimeMessage) MimeMultipart(javax.mail.internet.MimeMultipart) ThreePidSession(io.kamax.mxisd.threepid.session.ThreePidSession) ThreePid(io.kamax.matrix.ThreePid) MimeBodyPart(javax.mail.internet.MimeBodyPart) Test(org.junit.Test) ServerSetupTest(com.icegreen.greenmail.util.ServerSetupTest)

Example 5 with ThreePidSession

use of io.kamax.mxisd.threepid.session.ThreePidSession in project mxisd by kamax-io.

the class SessionManager method validate.

public ValidationResult validate(String sid, String secret, String token) {
    log.info("Validating session {}", sid);
    ThreePidSession session = getSession(sid, secret);
    log.info("Session {} is from {}", session.getId(), session.getServer());
    session.validate(token);
    storage.updateThreePidSession(session.getDao());
    log.info("Session {} has been validated", session.getId());
    ValidationResult r = new ValidationResult(session);
    session.getNextLink().ifPresent(r::setNextUrl);
    return r;
}
Also used : NotificationManager(io.kamax.mxisd.notification.NotificationManager) Logger(org.slf4j.Logger) ThreePidSession(io.kamax.mxisd.threepid.session.ThreePidSession)

Aggregations

ThreePidSession (io.kamax.mxisd.threepid.session.ThreePidSession)10 IThreePidSession (io.kamax.mxisd.threepid.session.IThreePidSession)5 ThreePid (io.kamax.matrix.ThreePid)3 io.kamax.matrix._MatrixID (io.kamax.matrix._MatrixID)3 PolicySource (io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate.PolicySource)3 NotAllowedException (io.kamax.mxisd.exception.NotAllowedException)3 GsonParser (io.kamax.mxisd.util.GsonParser)3 IOException (java.io.IOException)3 CloseableHttpResponse (org.apache.http.client.methods.CloseableHttpResponse)3 JsonObject (com.google.gson.JsonObject)2 Phonenumber (com.google.i18n.phonenumbers.Phonenumber)2 PolicyTemplate (io.kamax.mxisd.config.SessionConfig.Policy.PolicyTemplate)2 NotificationManager (io.kamax.mxisd.notification.NotificationManager)2 IThreePidSessionDao (io.kamax.mxisd.storage.dao.IThreePidSessionDao)2 HttpPost (org.apache.http.client.methods.HttpPost)2 BasicNameValuePair (org.apache.http.message.BasicNameValuePair)2 Logger (org.slf4j.Logger)2 NumberParseException (com.google.i18n.phonenumbers.NumberParseException)1 ServerSetupTest (com.icegreen.greenmail.util.ServerSetupTest)1 MatrixID (io.kamax.matrix.MatrixID)1