Properly handle v1 of 3pid/bind
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* mxisd - Matrix Identity Server Daemon
|
||||
* Copyright (C) 2019 Kamax Sarl
|
||||
*
|
||||
* https://www.kamax.io/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.kamax.mxisd.http.io.identity;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class BindRequest {
|
||||
|
||||
public static class Keys {
|
||||
|
||||
public static final String SessionID = "sid";
|
||||
public static final String Secret = "client_secret";
|
||||
public static final String UserID = "mxid";
|
||||
}
|
||||
|
||||
@SerializedName(Keys.SessionID)
|
||||
private String sid;
|
||||
|
||||
@SerializedName(Keys.Secret)
|
||||
private String secret;
|
||||
|
||||
@SerializedName(Keys.UserID)
|
||||
private String userId;
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public void setSid(String sid) {
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
}
|
@@ -30,6 +30,7 @@ import io.undertow.server.HttpHandler;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.HttpString;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,7 +39,10 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class BasicHttpHandler implements HttpHandler {
|
||||
|
||||
@@ -49,8 +53,16 @@ public abstract class BasicHttpHandler implements HttpHandler {
|
||||
}
|
||||
|
||||
protected String getQueryParameter(HttpServerExchange exchange, String name) {
|
||||
return getQueryParameter(exchange.getQueryParameters(), name);
|
||||
}
|
||||
|
||||
protected String getQueryParameter(Map<String, Deque<String>> parms, String name) {
|
||||
try {
|
||||
String raw = exchange.getQueryParameters().getOrDefault(name, new LinkedList<>()).peekFirst();
|
||||
String raw = parms.getOrDefault(name, new LinkedList<>()).peekFirst();
|
||||
if (StringUtils.isEmpty(raw)) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
return URLDecoder.decode(raw, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new InternalServerError(e);
|
||||
@@ -61,22 +73,33 @@ public abstract class BasicHttpHandler implements HttpHandler {
|
||||
return getQueryParameter(exchange, name);
|
||||
}
|
||||
|
||||
protected Optional<String> getContentType(HttpServerExchange exchange) {
|
||||
return Optional.ofNullable(exchange.getRequestHeaders().getFirst("Content-Type"));
|
||||
}
|
||||
|
||||
protected void writeBodyAsUtf8(HttpServerExchange exchange, String body) {
|
||||
exchange.getResponseSender().send(body, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
protected <T> T parseJsonTo(HttpServerExchange exchange, Class<T> type) {
|
||||
protected String getBodyUtf8(HttpServerExchange exchange) {
|
||||
try {
|
||||
return GsonUtil.get().fromJson(IOUtils.toString(exchange.getInputStream(), StandardCharsets.UTF_8), type);
|
||||
return IOUtils.toString(exchange.getInputStream(), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> T parseJsonTo(HttpServerExchange exchange, Class<T> type) {
|
||||
return GsonUtil.get().fromJson(getBodyUtf8(exchange), type);
|
||||
}
|
||||
|
||||
protected JsonObject parseJsonObject(HttpServerExchange exchange, String key) {
|
||||
return GsonUtil.getObj(parseJsonObject(exchange), key);
|
||||
}
|
||||
|
||||
protected JsonObject parseJsonObject(HttpServerExchange exchange) {
|
||||
try {
|
||||
JsonObject base = GsonUtil.parseObj(IOUtils.toString(exchange.getInputStream(), StandardCharsets.UTF_8));
|
||||
return GsonUtil.getObj(base, key);
|
||||
return GsonUtil.parseObj(IOUtils.toString(exchange.getInputStream(), StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@@ -23,14 +23,21 @@ package io.kamax.mxisd.http.undertow.handler.identity.v1;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.kamax.mxisd.exception.BadRequestException;
|
||||
import io.kamax.mxisd.http.IsAPIv1;
|
||||
import io.kamax.mxisd.http.io.identity.BindRequest;
|
||||
import io.kamax.mxisd.http.undertow.handler.BasicHttpHandler;
|
||||
import io.kamax.mxisd.invitation.InvitationManager;
|
||||
import io.kamax.mxisd.session.SessionMananger;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.QueryParameterUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Deque;
|
||||
import java.util.Map;
|
||||
|
||||
public class SessionTpidBindHandler extends BasicHttpHandler {
|
||||
|
||||
public static final String Path = IsAPIv1.Base + "/3pid/bind";
|
||||
@@ -47,12 +54,27 @@ public class SessionTpidBindHandler extends BasicHttpHandler {
|
||||
|
||||
@Override
|
||||
public void handleRequest(HttpServerExchange exchange) {
|
||||
String sid = getQueryParameter(exchange, "sid");
|
||||
String secret = getQueryParameter(exchange, "client_secret");
|
||||
String mxid = getQueryParameter(exchange, "mxid");
|
||||
BindRequest bindReq = new BindRequest();
|
||||
bindReq.setSid(getQueryParameter(exchange, BindRequest.Keys.SessionID));
|
||||
bindReq.setSecret(getQueryParameter(exchange, BindRequest.Keys.Secret));
|
||||
bindReq.setUserId(getQueryParameter(exchange, BindRequest.Keys.UserID));
|
||||
|
||||
String reqContentType = getContentType(exchange).orElse("application/octet-stream");
|
||||
if (StringUtils.equals("application/x-www-form-urlencoded", reqContentType)) {
|
||||
String body = getBodyUtf8(exchange);
|
||||
Map<String, Deque<String>> parms = QueryParameterUtils.parseQueryString(body, StandardCharsets.UTF_8.name());
|
||||
bindReq.setSid(getQueryParameter(parms, BindRequest.Keys.SessionID));
|
||||
bindReq.setSecret(getQueryParameter(parms, BindRequest.Keys.Secret));
|
||||
bindReq.setUserId(getQueryParameter(parms, BindRequest.Keys.UserID));
|
||||
} else if (StringUtils.equals("application/json", reqContentType)) {
|
||||
bindReq = parseJsonTo(exchange, BindRequest.class);
|
||||
} else {
|
||||
log.warn("Unknown encoding in 3PID session bind: {}", reqContentType);
|
||||
log.warn("The request will most likely fail");
|
||||
}
|
||||
|
||||
try {
|
||||
mgr.bind(sid, secret, mxid);
|
||||
mgr.bind(bindReq.getSid(), bindReq.getSecret(), bindReq.getUserId());
|
||||
respond(exchange, new JsonObject());
|
||||
} catch (BadRequestException e) {
|
||||
log.info("requested session was not validated");
|
||||
|
@@ -214,6 +214,10 @@ public class SessionMananger {
|
||||
}
|
||||
|
||||
public void bind(String sid, String secret, String mxidRaw) {
|
||||
if (StringUtils.isEmpty(mxidRaw)) {
|
||||
throw new IllegalArgumentException("No Matrix User ID provided");
|
||||
}
|
||||
|
||||
_MatrixID mxid = MatrixID.asAcceptable(mxidRaw);
|
||||
ThreePidSession session = getSessionIfValidated(sid, secret);
|
||||
|
||||
|
Reference in New Issue
Block a user