package com.psddev.cms.tool.page;
import java.io.IOException;
import java.security.SecureRandom;
import javax.servlet.ServletException;
import com.psddev.cms.db.ToolUser;
import com.psddev.cms.tool.AuthenticationFilter;
import com.psddev.cms.tool.PageServlet;
import com.psddev.cms.tool.ToolPageContext;
import com.psddev.dari.util.ObjectUtils;
import com.psddev.dari.util.RoutingFilter;
import com.psddev.dari.util.StringUtils;
@RoutingFilter.Path(application = "cms", value = "/toolUserTfa")
@SuppressWarnings("serial")
public class ToolUserTfa extends PageServlet {
private static final SecureRandom RANDOM = new SecureRandom();
@Override
protected String getPermissionId() {
return null;
}
@Override
protected void doService(ToolPageContext page) throws IOException, ServletException {
ToolUser user = page.getUser();
boolean verifyError = false;
if (page.isFormPost()
&& page.param(String.class, "action-verify") != null) {
if (!user.verifyTotp(page.param(int.class, "totpCode"))) {
verifyError = true;
} else {
user.setTfaEnabled(!user.isTfaEnabled());
user.save();
page.writeStart("script", "type", "text/javascript");
page.writeRaw("window.location = ");
String redirectUrl = page.param(String.class, AuthenticationFilter.RETURN_PATH_PARAMETER);
if (!StringUtils.isBlank(redirectUrl)) {
page.writeRaw('"' + redirectUrl + "\";");
} else {
page.writeRaw("window.location;");
}
page.writeEnd();
return;
}
}
if (user.getTotpSecret() == null) {
byte[] secret = new byte[20];
RANDOM.nextBytes(secret);
user.setTotpSecretBytes(secret);
user.save();
}
page.writeHeader();
page.writeStart("div",
"class", "widget",
"style", "overflow: hidden;");
page.writeStart("h1", "class", "icon icon-key");
page.writeHtml(page.localize(ToolUserTfa.class, user.isTfaEnabled() ? "title.disableTfa" : "title.enableTfa"));
page.writeEnd();
StringBuilder keyUri = new StringBuilder("otpauth://totp/");
String companyName = page.getCmsTool().getCompanyName();
if (!ObjectUtils.isBlank(companyName)) {
keyUri.append(StringUtils.encodeUri(companyName));
keyUri.append(StringUtils.encodeUri(" - "));
}
keyUri.append(StringUtils.encodeUri(!StringUtils.isEmpty(user.getUsername()) ? user.getUsername() : user.getEmail()));
keyUri.append("?secret=");
keyUri.append(user.getTotpSecret());
page.writeStart("div", "style", "float: right; margin-left: 10px; margin-top: -20px;");
page.writeElement("img",
"width", 200,
"height", 200,
"src", page.cmsUrl("/qrCode", "data", keyUri),
"style", "margin-left: 30px;");
page.writeStart("div");
page.writeHtml(page.localize(ToolUserTfa.class, "label.secretKey"));
page.writeHtml(": ");
page.writeTag("br");
page.writeRaw(user.getTotpSecret().replaceAll("(.{4})", "$1 "));
page.writeEnd();
page.writeEnd();
page.writeStart("div", "style", "margin-right: 280px;");
if (verifyError) {
page.writeStart("div", "class", "message message-error");
page.writeHtml(page.localize(ToolUserTfa.class, "message.invalidCode"));
page.writeEnd();
} else {
page.writeStart("div", "class", "message message-info");
if (user.isTfaEnabled()) {
page.writeHtml(page.localize(ToolUserTfa.class, "message.enabledInstructions"));
} else {
page.writeHtml(page.localize(ToolUserTfa.class, "message.disabledInstructions"));
}
page.writeEnd();
}
page.writeEnd();
page.writeStart("form",
"method", "post",
"action", page.url(""));
page.writeStart("div", "class", "inputContainer");
page.writeStart("div", "class", "inputLabel");
page.writeStart("label", "for", page.createId());
page.writeHtml(page.localize(ToolUserTfa.class, "label.code"));
page.writeEnd();
page.writeEnd();
page.writeStart("div", "class", "inputSmall");
page.writeElement("input",
"type", "text",
"id", page.getId(),
"name", "totpCode");
page.writeEnd();
page.writeEnd();
page.writeStart("div", "class", "actions");
page.writeStart("button",
"class", "action icon icon-action-save",
"name", "action-verify",
"value", true);
page.writeHtml(page.localize(ToolUserTfa.class, "action.verify"));
page.writeEnd();
page.writeEnd();
page.writeElement("input",
"type", "hidden",
"name", AuthenticationFilter.RETURN_PATH_PARAMETER,
"value", page.param(String.class, AuthenticationFilter.RETURN_PATH_PARAMETER));
page.writeEnd();
page.writeEnd();
page.writeFooter();
}
}