diff --git a/src/main/java/io/kamax/mxisd/http/io/identity/BindRequest.java b/src/main/java/io/kamax/mxisd/http/io/identity/BindRequest.java
new file mode 100644
index 0000000..031f6c9
--- /dev/null
+++ b/src/main/java/io/kamax/mxisd/http/io/identity/BindRequest.java
@@ -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 .
+ */
+
+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;
+ }
+
+}
diff --git a/src/main/java/io/kamax/mxisd/http/undertow/handler/BasicHttpHandler.java b/src/main/java/io/kamax/mxisd/http/undertow/handler/BasicHttpHandler.java
index 884c0c4..f4740ce 100644
--- a/src/main/java/io/kamax/mxisd/http/undertow/handler/BasicHttpHandler.java
+++ b/src/main/java/io/kamax/mxisd/http/undertow/handler/BasicHttpHandler.java
@@ -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> 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 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 parseJsonTo(HttpServerExchange exchange, Class 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 parseJsonTo(HttpServerExchange exchange, Class 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);
}
diff --git a/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidBindHandler.java b/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidBindHandler.java
index 69472fe..943f518 100644
--- a/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidBindHandler.java
+++ b/src/main/java/io/kamax/mxisd/http/undertow/handler/identity/v1/SessionTpidBindHandler.java
@@ -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> 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");
diff --git a/src/main/java/io/kamax/mxisd/session/SessionMananger.java b/src/main/java/io/kamax/mxisd/session/SessionMananger.java
index d9f5d9f..5f81898 100644
--- a/src/main/java/io/kamax/mxisd/session/SessionMananger.java
+++ b/src/main/java/io/kamax/mxisd/session/SessionMananger.java
@@ -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);