diff --git a/forms/src/main/java/org/keycloak/forms/QRServlet.java b/forms/src/main/java/org/keycloak/forms/QRServlet.java
deleted file mode 100644
index f1fddf635b..0000000000
--- a/forms/src/main/java/org/keycloak/forms/QRServlet.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2012, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.keycloak.forms;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.jboss.resteasy.logging.Logger;
-
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.client.j2se.MatrixToImageWriter;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.qrcode.QRCodeWriter;
-
-/**
- * @author Stian Thorgersen
- */
-@WebServlet(urlPatterns = "/forms/qrcode")
-public class QRServlet extends HttpServlet {
-
- private static final long serialVersionUID = 1L;
-
- private static final Logger log = Logger.getLogger(QRServlet.class);
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String[] size = req.getParameter("size").split("x");
- int width = Integer.parseInt(size[0]);
- int height = Integer.parseInt(size[1]);
-
- String contents = req.getParameter("contents");
-
- try {
- QRCodeWriter writer = new QRCodeWriter();
-
- BitMatrix bitMatrix = writer.encode(contents, BarcodeFormat.QR_CODE, width, height);
-
- MatrixToImageWriter.writeToStream(bitMatrix, "png", resp.getOutputStream());
- resp.setContentType("image/png");
- } catch (Exception e) {
- log.warn("Failed to generate qr code", e);
- resp.sendError(500);
- }
- }
-
-}
diff --git a/forms/src/main/java/org/keycloak/forms/TotpBean.java b/forms/src/main/java/org/keycloak/forms/TotpBean.java
index 9919ff4d23..a283c2e45e 100644
--- a/forms/src/main/java/org/keycloak/forms/TotpBean.java
+++ b/forms/src/main/java/org/keycloak/forms/TotpBean.java
@@ -78,7 +78,7 @@ public class TotpBean {
public String getTotpSecretQrCodeUrl() throws UnsupportedEncodingException {
String contents = URLEncoder.encode("otpauth://totp/keycloak?secret=" + totpSecretEncoded, "utf-8");
- return contextUrl + "/forms/qrcode" + "?size=246x246&contents=" + contents;
+ return contextUrl + "/rest/qrcode" + "?size=246x246&contents=" + contents;
}
public UserBean getUser() {
diff --git a/services/pom.xml b/services/pom.xml
index 187d7be695..52d2ab85e4 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -165,6 +165,10 @@
de.flapdoodle.embed.mongo
provided
+
+ com.google.zxing
+ javase
+
junit
junit
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index 7095eab7b4..fba3aa9e83 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -50,6 +50,7 @@ public class KeycloakApplication extends Application {
singletons.add(new SaasService(tokenManager));
singletons.add(new SocialResource(tokenManager, new SocialRequestManager()));
classes.add(SkeletonKeyContextResolver.class);
+ classes.add(QRCodeResource.class);
}
protected KeycloakSessionFactory createSessionFactory() {
diff --git a/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java b/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
new file mode 100644
index 0000000000..9d021117eb
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
@@ -0,0 +1,52 @@
+package org.keycloak.services.resources;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+
+import javax.servlet.ServletException;
+import javax.ws.rs.*;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author Stian Thorgersen
+ */
+@Path("/qrcode")
+public class QRCodeResource {
+
+ @GET
+ @Produces("image/png")
+ public Response createQrCode(@QueryParam("contents") String contents, @QueryParam("size") String size) throws ServletException, IOException, WriterException {
+ int width = 256;
+ int height = 256;
+
+ if (size != null) {
+ String[] s = size.split("x");
+ width = Integer.parseInt(s[0]);
+ height = Integer.parseInt(s[1]);
+ }
+
+ if (contents == null) {
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+
+ QRCodeWriter writer = new QRCodeWriter();
+ final BitMatrix bitMatrix = writer.encode(contents, BarcodeFormat.QR_CODE, width, height);
+
+ StreamingOutput stream = new StreamingOutput() {
+ @Override
+ public void write(OutputStream os) throws IOException,
+ WebApplicationException {
+ MatrixToImageWriter.writeToStream(bitMatrix, "png", os);
+ }
+ };
+
+ return Response.ok(stream).build();
+ }
+
+}