Skip to content

Commit

Permalink
fix: PubKey extraction for JWT Authhandler and other fixes
Browse files Browse the repository at this point in the history
With Vert.x 4.0 the way of passing public keys to the JWT AuthHandler
has changed. There was also a typo in NeonBeeOptions class and the order
of Logger parameters in Deployable class was wrong.
  • Loading branch information
pk-work committed Jan 28, 2021
1 parent 4f4fdf5 commit ff018e0
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/main/java/io/neonbee/NeonBeeOptions.java
Expand Up @@ -60,7 +60,7 @@ default Path getConfigDirectory() {
* @return the verticle directory path
*/
default Path getVerticlesDirectory() {
return getWorkingDirectory().resolve("verticle");
return getWorkingDirectory().resolve("verticles");
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/io/neonbee/internal/deploy/Deployable.java
Expand Up @@ -83,8 +83,8 @@ public PendingDeployment deploy(Vertx vertx, String correlationId) {
private Handler<AsyncResult<String>> getDeployHandler(String correlationId, Promise<String> deployPromise) {
return deployResult -> {
if (deployResult.failed()) {
LOGGER.correlateWith(correlationId).error("Deployment of {} failed", deployResult.cause(),
getIdentifier());
LOGGER.correlateWith(correlationId).error("Deployment of {} failed", getIdentifier(),
deployResult.cause());
deployPromise.fail(deployResult.cause());
} else {
LOGGER.correlateWith(correlationId).info("Deployment of {} succeeded", getIdentifier());
Expand Down Expand Up @@ -169,7 +169,7 @@ static Future<DeploymentOptions> readVerticleConfig(Vertx vertx, String identifi
new DeploymentOptions(defaultConfig != null ? defaultConfig : new JsonObject()));
} else {
LOGGER.correlateWith(correlationId).warn("Could not read deployment options for deployable {}",
throwable, identifier);
identifier, throwable);
return failedFuture(throwable);
}
});
Expand Down
31 changes: 30 additions & 1 deletion src/main/java/io/neonbee/internal/verticle/ServerVerticle.java
Expand Up @@ -40,6 +40,7 @@
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.PubSecKeyOptions;
import io.vertx.ext.auth.authentication.AuthenticationProvider;
import io.vertx.ext.auth.jwt.JWTAuth;
import io.vertx.ext.auth.jwt.JWTAuthOptions;
Expand Down Expand Up @@ -130,6 +131,12 @@ public class ServerVerticle extends AbstractVerticle {

protected static final String CONFIG_PROPERTY_SESSION_HANDLING_NONE = "none";

@VisibleForTesting
static final String BEGIN_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----";

@VisibleForTesting
static final String END_PUBLIC_KEY = "-----END PUBLIC KEY-----";

private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private HttpServer httpServer;
Expand Down Expand Up @@ -300,7 +307,8 @@ private AuthenticationProvider createAuthProvider(JsonObject options) {
// TODO return JDBCAuth.create(vertx, client).setAllSettersHere;
throw new UnsupportedOperationException("JDBC authentication provider is not implemented yet");
case "jwt":
return JWTAuth.create(vertx, new JWTAuthOptions(options));
JsonArray pubSecKeys = options.getJsonArray("pubSecKeys");
return JWTAuth.create(vertx, new JWTAuthOptions().setPubSecKeys(extractPubSecKeys(pubSecKeys)));
case "mongo":
// TODO return MongoAuth.create(mongoClient, jsonConfig);
throw new UnsupportedOperationException("MongoDB authentication provider is not implemented yet");
Expand All @@ -315,6 +323,27 @@ private AuthenticationProvider createAuthProvider(JsonObject options) {
}
}

@VisibleForTesting
static List<PubSecKeyOptions> extractPubSecKeys(JsonArray keys) {
return keys.stream().map(JsonObject.class::cast).map(pubKeyJson -> {
String algorithm = pubKeyJson.getString("algorithm");
String pubKey = pubKeyJson.getString("publicKey");

return new PubSecKeyOptions().setAlgorithm(algorithm).setBuffer(convertToPEM(pubKey));
}).collect(Collectors.toList());
}

/**
* Converts a given public key into a PEM format.
*
* @param publicKey The public key
* @return A String representing a Vert.x compatible PEM format
*/
private static String convertToPEM(String publicKey) {
return new StringBuilder(BEGIN_PUBLIC_KEY).append('\n').append(publicKey).append('\n').append(END_PUBLIC_KEY)
.toString();
}

/**
* Determine the session handling (none/local/clustered).
*
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/io/neonbee/NeonBeeOptionsTest.java
Expand Up @@ -83,7 +83,7 @@ public void checkThatSubfoldersExist() throws IOException {
assertThat((Object) opts.getLogDirectory()).isEqualTo(tempDirPath.resolve("logs"));
assertThat((Object) opts.getConfigDirectory()).isEqualTo(tempDirPath.resolve("config"));
assertThat((Object) opts.getModelsDirectory()).isEqualTo(tempDirPath.resolve("models"));
assertThat((Object) opts.getVerticlesDirectory()).isEqualTo(tempDirPath.resolve("verticle"));
assertThat((Object) opts.getVerticlesDirectory()).isEqualTo(tempDirPath.resolve("verticles"));
FileSystemHelper.deleteRecursiveBlocking(tempDirPath);
}

Expand Down
18 changes: 18 additions & 0 deletions src/test/java/io/neonbee/internal/verticle/ServerVerticleTest.java
@@ -1,12 +1,15 @@
package io.neonbee.internal.verticle;

import static com.google.common.truth.Truth.assertThat;
import static io.neonbee.internal.verticle.ServerVerticle.BEGIN_PUBLIC_KEY;
import static io.neonbee.internal.verticle.ServerVerticle.END_PUBLIC_KEY;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.Test;
Expand All @@ -17,7 +20,9 @@
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.PubSecKeyOptions;
import io.vertx.junit5.Checkpoint;
import io.vertx.junit5.Timeout;
import io.vertx.junit5.VertxTestContext;
Expand Down Expand Up @@ -128,6 +133,19 @@ void testLargerMaximumInitialLineAndCookieSizesConfig(VertxTestContext testCtx)
})));
}

@Test
void testExtractPubSecKeys() {
String algorithm = "RS256";
String pubKey = "Hodor";
JsonArray pubKeys = new JsonArray().add(new JsonObject().put("algorithm", "RS256").put("publicKey", pubKey));

String expectedBuffer = BEGIN_PUBLIC_KEY + "\n" + pubKey + "\n" + END_PUBLIC_KEY;
List<PubSecKeyOptions> keys = ServerVerticle.extractPubSecKeys(pubKeys);
assertThat(keys).hasSize(1);
assertThat(keys.get(0).getAlgorithm()).isEqualTo(algorithm);
assertThat(keys.get(0).getBuffer()).isEqualTo(expectedBuffer);
}

@Override
protected WorkingDirectoryBuilder provideWorkingDirectoryBuilder(TestInfo testInfo, VertxTestContext testContext) {
if ("testLargerMaximumInitialLineAndCookieSizesConfig"
Expand Down

0 comments on commit ff018e0

Please sign in to comment.