Modify POST /user/:id/setupTotp to work with adjusted requirements

This commit is contained in:
Colin McDonald 2016-06-24 18:55:47 -04:00
parent aa527fa567
commit aaba9cb369
5 changed files with 29 additions and 33 deletions

View File

@ -109,7 +109,7 @@
<version>2.7.0</version>
</dependency>
<!-- TOTP -->
<!-- Totp -->
<dependency>
<groupId>com.warrenstrange</groupId>
<artifactId>googleauth</artifactId>

View File

@ -25,6 +25,7 @@ import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.net.JksOptions;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
@ -218,7 +219,8 @@ public final class APIv3 extends AbstractVerticle {
private void setupHttpServer() {
HttpServer webServer = vertx.createHttpServer(
new HttpServerOptions()
//.setSsl(true) // TODO
//.setSsl(true)
//.setKeyStoreOptions(new JksOptions().setPath("c:\\Users\\cmcdonald\\Desktop\\apiv3.jks").setPassword("password"))
.setCompressionSupported(true)
);

View File

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableMap;
import com.mongodb.client.result.UpdateResult;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
import io.vertx.core.Handler;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import net.frozenorb.apiv3.APIv3;
import net.frozenorb.apiv3.model.User;
@ -24,20 +25,27 @@ public final class POSTUserSetupTotp implements Handler<RoutingContext> {
}
if (user.getTotpSecret() != null) {
ErrorUtils.respondInvalidInput(ctx, "User provided already has TOTP code set.");
ErrorUtils.respondInvalidInput(ctx, "User provided already has totp setup.");
return;
}
GoogleAuthenticatorKey generated = TotpUtils.generateTotpSecret();
JsonObject requestBody = ctx.getBodyAsJson();
String secret = requestBody.getString("secret");
int code = requestBody.getInteger("code");
user.setTotpSecret(generated.getKey());
if (TotpUtils.authorizeUser(secret, code)) {
user.setTotpSecret(secret);
BlockingCallback<UpdateResult> callback = new BlockingCallback<>();
user.save(callback);
callback.get();
APIv3.respondJson(ctx, ImmutableMap.of(
"qrCode", TotpUtils.getQrCodeUrl(user, generated)
"success", true,
"message", "Totp code set."
));
} else {
ErrorUtils.respondInvalidInput(ctx, "Confirmation code provided did not match.");
}
}
}

View File

@ -26,7 +26,7 @@ public final class POSTUserVerifyTotp implements Handler<RoutingContext> {
}
if (user.getTotpSecret() == null) {
ErrorUtils.respondInvalidInput(ctx, "User provided does not have TOTP code set.");
ErrorUtils.respondInvalidInput(ctx, "User provided does not have totp code set.");
return;
}
@ -45,7 +45,7 @@ public final class POSTUserVerifyTotp implements Handler<RoutingContext> {
if (recentlyUsedCallback.get()) {
APIv3.respondJson(ctx, ImmutableMap.of(
"authorized", false,
"message", "TOTP code was recently used."
"message", "Totp code was recently used."
));
return;
}
@ -63,12 +63,12 @@ public final class POSTUserVerifyTotp implements Handler<RoutingContext> {
APIv3.respondJson(ctx, ImmutableMap.of(
"authorized", true,
"message", "Valid TOTP code provided."
"message", "Valid totp code provided."
));
} else {
APIv3.respondJson(ctx, ImmutableMap.of(
"authorized", false,
"message", "TOTP code was not valid."
"message", "Totp code was not valid."
));
}
}

View File

@ -3,8 +3,6 @@ package net.frozenorb.apiv3.util;
import com.mongodb.async.SingleResultCallback;
import com.warrenstrange.googleauth.GoogleAuthenticator;
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
import com.warrenstrange.googleauth.GoogleAuthenticatorQRGenerator;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;
import lombok.experimental.UtilityClass;
@ -23,20 +21,8 @@ public class TotpUtils {
.setPort(Integer.parseInt(APIv3.getConfig().getProperty("redis.port")))
);
public static GoogleAuthenticatorKey generateTotpSecret() {
return googleAuthenticator.createCredentials();
}
public static boolean authorizeUser(User user, int code) {
return googleAuthenticator.authorize(user.getTotpSecret(), code);
}
public static String getQrCodeUrl(User user, GoogleAuthenticatorKey secret) {
return GoogleAuthenticatorQRGenerator.getOtpAuthURL(
"MineHQ Network",
user.getLastUsername(),
secret
);
public static boolean authorizeUser(String secret, int code) {
return googleAuthenticator.authorize(secret, code);
}
public static void isPreAuthorized(User user, String ip, SingleResultCallback<Boolean> callback) {
@ -68,7 +54,7 @@ public class TotpUtils {
}
public static void wasRecentlyUsed(User user, int code, SingleResultCallback<Boolean> callback) {
redisClient.exists(user.getId() + ":recentTOTPCodes:" + code, (result) -> {
redisClient.exists(user.getId() + ":recentTotpCodes:" + code, (result) -> {
if (result.succeeded()) {
callback.onResult(result.result() == 1 , null);
} else {
@ -78,7 +64,7 @@ public class TotpUtils {
}
public static void markRecentlyUsed(User user, int code, SingleResultCallback<Void> callback) {
String key = user.getId() + ":recentTOTPCodes:" + code;
String key = user.getId() + ":recentTotpCodes:" + code;
redisClient.set(key, "", (result) -> {
if (result.succeeded()) {